Qt基本控件总结

  • 1.QListWidget(Base Item)
  • 1.1单个Item添加
  • 1.2用QStringList添加多行文字
  • 2.QTreeWidget(Base Item)
  • 3.QTableWidget
  • 3.1添加Item
  • 3.2 int转QString
  • 4.Stacked Box
  • 5.下拉框
  • 6.label
  • 6.1显示图片
  • 6.2显示动态图片
  • 7.自定义控件封装
  • 8.鼠标事件
  • 9.定时器
  • 10.事件分发器
  • 11.QPainter绘图事件
  • 11.文件读写操作
  • 12.文件信息读取


1.QListWidget(Base Item)

1.1单个Item添加

qt显控的架构 qt 控件_qt

QListWidgetItem *list = new QListWidgetItem("添加一行");
ui->listWidget->addItem(list);
list->setTextAlignment(Qt::AlignHCenter);//添加对齐方式

1.2用QStringList添加多行文字

qt显控的架构 qt 控件_List_02

QStringList list;
list << "山" << "河" << "无" << "恙";
ui->listWidget->addItems(list);

2.QTreeWidget(Base Item)

qt显控的架构 qt 控件_List_03


设置表头

ui->treeWidget->setHeaderLabels(QStringList()<<"Hero"<<"attribute"<<"attribute2");

设置TopLevelItem

QTreeWidgetItem *item = new QTreeWidgetItem(QStringList()<<"张飞");
QTreeWidgetItem *item2 = new QTreeWidgetItem(QStringList()<<"黄忠");
QTreeWidgetItem *item3 = new QTreeWidgetItem(QStringList()<<"马超");
ui->treeWidget->addTopLevelItem(item);
ui->treeWidget->addTopLevelItem(item2);
ui->treeWidget->addTopLevelItem(item3);

设置Item的内容

QStringList list_1;
list_1 << "a1" << "a2"<< "a3";
QStringList list_2;
list_2 << "a11" << "a12" << "a23";
QStringList list_3;
list_3 << "a23" << "a23" << "a33";
QTreeWidgetItem *item_1 = new QTreeWidgetItem(list_1);
QTreeWidgetItem *item_2 = new QTreeWidgetItem(list_2);
QTreeWidgetItem *item_3 = new QTreeWidgetItem(list_3);

item->addChild(item_1);
item2->addChild(item_2);
item3->addChild(item_3);

3.QTableWidget

3.1添加Item

qt显控的架构 qt 控件_控件_04

ui->tableWidget->setColumnCount(3);//设置列数
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"第一列"<<"第二列"<<"第三列");//设置表头
ui->tableWidget->setRowCount(3);//设置行数
ui->tableWidget->setItem(0,0,new QTableWidgetItem("11"));//设置内容,col,row,text

3.2 int转QString

qt显控的架构 qt 控件_qt_05

QStringList namelist;
namelist << "name1" << "name2" << "name3";

QList<QString> att;//与QStringList等效
att << "att1" << "att2" << "att3";

for(int i=0;i<3;i++)
{
    int col=0;
    ui->tableWidget->setItem( i, col++, new QTableWidgetItem(namelist[i]));
    ui->tableWidget->setItem( i, col++, new QTableWidgetItem(att[i]));
    ui->tableWidget->setItem( i, col++, new QTableWidgetItem(QString::number(i)));
    }

4.Stacked Box

qt显控的架构 qt 控件_Qt_06


每次按钮切到下一页,类似Qt的左侧菜单栏

void MainWindow::on_pushButton_clicked()
{
    static int i = 0;
    ui->stackedWidget->setCurrentIndex(i++);
    if( i == 3)
    {
        i = 0;
    }
}

5.下拉框

添加项目

ui->comboBox->addItem("a");
ui->comboBox->addItem("b");
ui->comboBox->addItem("c");

通过索引选中Item

if(ui->comboBox->currentIndex() == 0)
{
    ui->groupBox->setDisabled(true);
    ui->comboBox_2->setDisabled(true);
}else if(ui->comboBox->currentIndex() == 1){
    ui->groupBox->setEnabled(true);
    ui->comboBox_2->setDisabled(true);
}else if(ui->comboBox->currentIndex() == 2){
    ui->groupBox->setDisabled(true);
    ui->comboBox_2->setEnabled(true);
}

6.label

6.1显示图片

ui->label_4->setPixmap(QPixmap("/Users/yangming/Desktop/crack.png"));

6.2显示动态图片

QMovie * movie = new QMovie("/Users/yangming/Desktop/wolf.gif");
ui->label_4->setMovie(movie);
movie->start();

7.自定义控件封装

7.1建立控件,然后在要调用的窗口将widget提升为mywidget(新建控件类名)

qt显控的架构 qt 控件_控件_07


7.2编写新建控件槽函数

(1)Spinbox数值变更时,Slider跟随滑动

connect(ui->spinBox,&QSpinBox::valueChanged,ui->horizontalSlider,&QSlider::setValue);

控件所有的具体Signal和SLot查看帮助文档,即valueChanged和setValue,上述代码会报错,因为函数重载中没明确参数类型,因此要建立下述指针。

void(QSpinBox:: * sigSpinbox)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,sigSpinbox,ui->horizontalSlider,&QSlider::setValue);

(2)SLider滑动,Spinbox跟随更新

qt显控的架构 qt 控件_qt显控的架构_08

connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

7.3点击按钮,获取当前值
在自建控件中编写setNum和getNum函数
smallWidget.h

public:
    void setNum(int num);
    int getNum(int num);

smallWidget.cpp

int smallWidget::getNum(int num)
{
    return ui->spinBox->value();
}

void smallWidget::setNum(int num)
{
    ui->spinBox->setValue(num);
}

点击按钮1,qDebug返回数值
widget.cpp

void Widget::on_pushButton_clicked()
{
    qDebug()<<ui->widget->getNum();
}

点击按钮2,控件设置数值

void Widget::on_pushButton_2_clicked()
{
    ui->widget->setNum(50);
}

qt显控的架构 qt 控件_控件_09

8.鼠标事件

(1)帮助文档查找事件函数

qt显控的架构 qt 控件_Qt_10


(2)封装控件

myLabel.h

public:
    explicit mouseLabel(QWidget *parent = nullptr);
    ~mouseLabel();
    void enterEvent(QEvent *event);
    void leaveEvent(QEvent *event);

myLabel.cpp

void mouseLabel::enterEvent(QEvent *event)
{
    qDebug()<<"鼠标进入";
}

void mouseLabel::leaveEvent(QEvent *event)
{
    qDebug()<<"鼠标离开";
}

(3)在主窗口中promote label

qt显控的架构 qt 控件_控件_11


父类选择QLabel,在封装控件中也要把继承父类改为QLabel:

qt显控的架构 qt 控件_Qt_12


qt显控的架构 qt 控件_qt显控的架构_13


至此鼠标进入和离开的事件函数编写完成,可以实现主窗口调用。

(4)鼠标移动事件

QLabel类中查找Reimplemented Protected Functions

qt显控的架构 qt 控件_List_14


label事件函数编写

myLabel.cpp

void mouseLabel::mouseMoveEvent(QMouseEvent *ev)
{
    qDebug()<<"鼠标移动";
}

void mouseLabel::mousePressEvent(QMouseEvent *ev)
{
    qDebug()<<"鼠标按下";
}

void mouseLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    qDebug()<<"鼠标释放";
}

(5)鼠标按下,输出鼠标坐标

qt显控的架构 qt 控件_控件_15


mouseEvent会返回鼠标坐标等信息

需要头文件#include "QMouseEvent"

void mouseLabel::mousePressEvent(QMouseEvent *ev)
{
    QString str = QString("鼠标按下").arg(ev->x()).arg(ev->y());
    qDebug()<<"鼠标按下 x=%1  y=%2";
}

左右键判断在返回值的button中

qt显控的架构 qt 控件_List_16

void mouseLabel::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton)
    {
        QString str = QString("鼠标按下 x=%1 y=%2 globelX=%3 globelY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
void mouseLabel::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton)
    {
        QString str = QString("鼠标移动 x=%1 y=%2 globelX=%3 globelY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}

鼠标移动过程中先按下左键,然后中途按下右键会无法判断,这里可以使用ev的返回值buttons()来判断,即按位判断,按位操作不做赘述。

void mouseLabel::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->buttons() & Qt::LeftButton)
    {
        QString str = QString("鼠标移动 x=%1 y=%2 globelX=%3 globelY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}

(6)鼠标追踪
label中在没有获取焦点时,鼠标的移动不会产生响应,只有在点击即获取焦点后再鼠标移动才会响应,为解决此问题可以添加鼠标追踪setMouseTracking(true);

9.定时器

(1)事件重载函数

qt显控的架构 qt 控件_控件_17


widget.cpp

void Widget::timerEvent(QTimerEvent *e)
{
    static int num = 1;

    ui->label->setText(QString::number(num++));
}

定时器启动startTimer(1000);

(2)多个定时器
timerEvent除了构造外只有一个timerId返回值,多个定时器的判断可用该标识符。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    id1 = startTimer(1000);//.h定义 int
    id2 = startTimer(2000);
}
void Widget::timerEvent(QTimerEvent *e)
{

    if(e->timerId() == id1)
    {
        static int num = 1;
        ui->label->setText(QString::number(num++));
    }

    if(e->timerId() == id2)
    {
        static int num2 = 1;
        ui->label_2->setText(QString::number(num2++));
    }
}

(3)实例化定时器对象

QTimer中的singal中有一个timeout()信号,用来做触发,此方法也可实例化多个定时器,定时器更独立,逻辑更为清晰。

qt显控的架构 qt 控件_List_18

QTimer * timer1 = new QTimer(this);
timer1->start(500);
connect(timer1,&QTimer::timeout,this,[=](){
    static int num3 = 1;
    ui->label_3->setText(QString::number(num3++));
});

10.事件分发器

(1)事件分发器

在app响应事件时,要经过事件分发器,分发器的返回为bool类型,如果为true,即用户处理该事件,不像下分发事件,可起到拦截作用,但一般不用这种用途,其主要用来做事件的分发。

qt显控的架构 qt 控件_Qt_19


在HelpMannul中可以找到QEvent的Type都有哪些类型:

qt显控的架构 qt 控件_控件_20


qt显控的架构 qt 控件_qt显控的架构_21


据此实现鼠标单击事件的拦截:

除了鼠标按下事件,其他事件正常返回Widget::event(ev)

bool mouseLabel::event(QEvent *ev)
{
    if(ev->type() == QEvent::MouseButtonPress)
    {

        QMouseEvent * evv = static_cast<QMouseEvent *>(ev);
        QString str = QString("事件拦截:x=%1 y=%2").arg(evv->x()).arg(evv->y());
        qDebug() << str;
        return true;
    }

    return QLabel::event(ev);
}
}

上述代码包含QEvent向QMouseEvnet类型的转换,QEvent是QMouseEvent的父类

(2)事件过滤器

qt显控的架构 qt 控件_Qt_22


在分发器前有一个更高级的事件过滤,可在分发器前做一次拦截。

步骤:给控件安装事件过滤器->重写eventFilter函数。

bool Widget::eventFilter(QObject *obj, QEvent *ev)
{
    if(obj == ui->label)
    {
        if(ev->type() == QEvent::MouseButtonPress)
        {
            return true;
        }
    }

    return QWidget::eventFilter(obj,ev);
}

过滤器有两个参数,obj用来判断控件,ev用来判断事件,除了拦截的事件,其他的都正常返回。

11.QPainter绘图事件

(1)QWidget下的paintEvent事件函数重载

qt显控的架构 qt 控件_Qt_23

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawLine(QPoint(0,0),QPoint(100,100));
}

QPainter中指定Device,即画的位置

画圆:

painter.drawEllipse(QPoint(100,100),50,50);

画矩形:

painter.drawRect(0,0,50,50);

画文字:

painter.drawText(QRect(100,100,150,100),"山河无恙,春暖花开");

qt显控的架构 qt 控件_qt显控的架构_24


设置画笔:

QPainter painter(this);

QPen pen(QColor(255,0,0));
pen.setWidth(3);
pen.setStyle(Qt::DotLine);
painter.setPen(pen);

QBrush brush(Qt::cyan);
brush.setStyle(Qt::Dense1Pattern);
painter.setBrush(brush);

painter.drawLine(QPoint(0,0),QPoint(100,100));
painter.drawEllipse(QPoint(100,100),50,50);
painter.drawRect(0,0,50,50);
painter.drawText(QRect(100,100,150,100),"山河无恙,春暖花开");

其他参数查看帮助文档。

(2)painter高级设置

提高抗锯齿

qt显控的架构 qt 控件_Qt_25

qt显控的架构 qt 控件_List_26

painter.setRenderHint(QPainter::Antialiasing);

重设坐标原点

qt显控的架构 qt 控件_控件_27


如果给出了offset,即按offset更新原点坐标

painter.drawRect(100,100,100,100);
painter.translate(50,0);
painter.drawRect(100,100,100,100);

qt显控的架构 qt 控件_List_28


画家位置的保存与还原

painter.drawRect(100,100,100,100);

painter.translate(100,0);

painter.drawRect(100,100,100,100);

painter.save();

painter.translate(100,0);

painter.restore();

painter.drawRect(100,100,100,100);

restore函数将画家远点还原到save的位置,上述代码中最后一次绘制的矩形会和第二次绘制的矩形重叠。

(3)手动调用绘图事件
用painter画资源文件

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(20,100,QPixmap("/Users/yangming/Desktop/crack.png"));
}

实现图像位置的移动,用到repaint()函数

qt显控的架构 qt 控件_Qt_29

//构造函数
posX = 0;
connect(ui->pushButton,&QPushButton::clicked,[=](){
    posX += 20;
    repaint();
});

void Widget::paintEvent(QPaintEvent *)
{
	if(posX > this->width())
	{
		poxX = 0;
	}
    QPainter painter(this);
    painter.drawPixmap(posX,100,QPixmap("/Users/yangming/Desktop/crack.png"));
}

(4)绘图设备

qt显控的架构 qt 控件_qt显控的架构_30


Qt的绘图可以理解为QPainter通过QPaintEngine通讯在QPaintDevice上绘图。

绘图设备即继承QPainterDevice的子类,Qt中共有四种:QPixmap、QBitmap、QImage

QPicture。

QPixmap:专门为图像在屏幕上的显示做了优化。
QBitmap:是QPixmap的子类,他的色深限定为1,即只有黑色和白色,可以使用QPixmap的isBitmap()函数来确定这个Pixmap是不是一个QBitmap。
QImage:专门为图像的像素级访问做了优化。
QPicture:可以记录和重现QPainter的各条命令。

QWidget是一个绘图设备,其父类为QObject和QPaintDevice。

qt显控的架构 qt 控件_List_31

例1 QPixmap设备,利用QPainter在QPixmap上画图

QPixmap pix(300,300);

QPainter painter1(&pix);
painter1.setPen(QPen(QColor(Qt::green)));
painter1.drawEllipse(100,100,100,100);

pix.save("/Users/yangming/Desktop/painter.png");

qt显控的架构 qt 控件_Qt_32


例2.QImage绘图设备

QImage img(300,300,QImage::Format_RGB32);

QPainter painter(&img);

img.fill(QColor(Qt::white));

painter.setPen(QPen(QColor(Qt::green)));

painter.drawEllipse(100,100,100,100);

img.save("/Users/yangming/Desktop/img.png");

QImage的数据格式如下:

qt显控的架构 qt 控件_qt_33

像素级访问:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    QImage img;
    img.load("/Users/yangming/Desktop/crack.png");
    for(int i = 0 ; i<50 ; i++)
    {
        for(int j = 0; j<50 ; j++)
        {
            QRgb rgb = qRgb(0,0,255);
            img.setPixel(i,j,rgb);
        }
    }
    painter.drawImage(0,0,img);

}

qt显控的架构 qt 控件_List_34


例3.QPicture绘图设备

绘制某个图形,并保存到自定义的文件中,该文件中保存了自己的绘图指令,而且自定义文件只能自己访问。

QPicture picture;
QPainter painter;
painter.begin(&picture);
painter.setPen(QColor(Qt::red));
painter.drawEllipse(QPoint(100,100),100,100);
painter.end();
picture.save("/Users/yangming/desktop/pic.ym");

重现指令

void Widget::paintEvent(QPaintEvent *)
{
    QPicture pic;
    QPainter painter(this);
    pic.load("/Users/yangming/Desktop/pic.ym");
    painter.drawPicture(0,0,pic);

}

qt显控的架构 qt 控件_qt_35

11.文件读写操作

读文件要用到QFIleDialog,File默认支持的格式为utf-8。

connect(ui->pushButton,&QPushButton::clicked,this,[=](){
       QString path = QFileDialog::getOpenFileName(this,"打开文件","/Users/yangming/Desktop");
       ui->lineEdit->setText(path);
       QFile file(path);
       file.open(QIODevice::ReadOnly);
       QByteArray array = file.readAll();
       ui->textEdit->setText(array);
    });

QFile的QIODevice支持格式如下:

qt显控的架构 qt 控件_qt显控的架构_36


qt显控的架构 qt 控件_qt显控的架构_37


如果是其他格式的文件,需要用到QTextCodec编码格式类:

connect(ui->pushButton,&QPushButton::clicked,this,[=](){
       QString path = QFileDialog::getOpenFileName(this,"打开文件","/Users/yangming/Desktop/dachuang.txt");
       ui->lineEdit->setText(path);
       QFile file(path);
       QTextCodec * codec = QTextCodec::codecForName("gbk");//gbk为目标格式
       file.open(QIODevice::ReadOnly);
       QByteArray array = file.readAll();

//       ui->textEdit->setText(array);
       ui->textEdit->setText(codec->toUnicode(array));//利用codec转化数据格式

    });

按行读取文件:

ui->setupUi(this);
    connect(ui->pushButton,&QPushButton::clicked,this,[=](){
       QString path = QFileDialog::getOpenFileName(this,"打开文件","/Users/yangming/Desktop/dachuang.txt");
       ui->lineEdit->setText(path);
       QFile file(path);
       QTextCodec * codec = QTextCodec::codecForName("gbk");
       file.open(QIODevice::ReadOnly);
//       QByteArray array = file.readAll();

//       ui->textEdit->setText(array);
       QByteArray array;
       while(!file.atEnd())
       {
           array += file.readLine();
       }
       ui->textEdit->setText(codec->toUnicode(array));
       file.close();
    });

文件追加内容:

file.open(QIODevice::Append);
file.write("山河无恙,春暖花开");
file.close();

注意使用完要close()文件。

12.文件信息读取

文件信息类:QFIleInfo

qt显控的架构 qt 控件_qt显控的架构_38


比较常用的:

后缀名:suffix()

文件名:filename()

最后修改日期:lastModified()

创建时间:created()

文件路径:path()/filepath()

connect(ui->pushButton,&QPushButton::clicked,this,[=](){
       QString path = QFileDialog::getOpenFileName(this,"打开文件","/Users/yangming/Desktop/dachuang.txt");
       ui->lineEdit->setText(path);
       QFile file(path);
       QTextCodec * codec = QTextCodec::codecForName("gbk");
       file.open(QIODevice::ReadOnly);
//       QByteArray array = file.readAll();

//       ui->textEdit->setText(array);
       QByteArray array;
       while(!file.atEnd())
       {
           array += file.readLine();
       }


       ui->textEdit->setText(codec->toUnicode(array));
       file.close();

       file.open(QIODevice::Append);
       file.write("山河无恙,春暖花开");
       file.close();

       QFileInfo info(path);
       qDebug() << "大小:" << info.size() << "后缀名:" << info.suffix() << "文件路径:" << info.filePath();
       qDebug() << "创建日期:" << info.created();
    });

打印创建日期,因为是QDateTime类型,因为没有进行格式化,其打印效果如下:

qt显控的架构 qt 控件_控件_39


在HelpMannul中查看QDateTime的格式化函数:

qt显控的架构 qt 控件_qt_40

qDebug() << "创建日期:" << info.created().toString("yyyy/MM/dd/ hh:mm:ss");

修改后打印如下:

qt显控的架构 qt 控件_qt_41