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添加
QListWidgetItem *list = new QListWidgetItem("添加一行");
ui->listWidget->addItem(list);
list->setTextAlignment(Qt::AlignHCenter);//添加对齐方式
1.2用QStringList添加多行文字
QStringList list;
list << "山" << "河" << "无" << "恙";
ui->listWidget->addItems(list);
2.QTreeWidget(Base Item)
设置表头
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
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
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的左侧菜单栏
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(新建控件类名)
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跟随更新
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);
}
8.鼠标事件
(1)帮助文档查找事件函数
(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
父类选择QLabel,在封装控件中也要把继承父类改为QLabel:
至此鼠标进入和离开的事件函数编写完成,可以实现主窗口调用。
(4)鼠标移动事件
QLabel类中查找Reimplemented Protected Functions
label事件函数编写
myLabel.cpp
void mouseLabel::mouseMoveEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标移动";
}
void mouseLabel::mousePressEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标按下";
}
void mouseLabel::mouseReleaseEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标释放";
}
(5)鼠标按下,输出鼠标坐标
mouseEvent会返回鼠标坐标等信息
需要头文件#include "QMouseEvent"
void mouseLabel::mousePressEvent(QMouseEvent *ev)
{
QString str = QString("鼠标按下").arg(ev->x()).arg(ev->y());
qDebug()<<"鼠标按下 x=%1 y=%2";
}
左右键判断在返回值的button中
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)事件重载函数
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()
信号,用来做触发,此方法也可实例化多个定时器,定时器更独立,逻辑更为清晰。
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,即用户处理该事件,不像下分发事件,可起到拦截作用,但一般不用这种用途,其主要用来做事件的分发。
在HelpMannul中可以找到QEvent的Type都有哪些类型:
据此实现鼠标单击事件的拦截:
除了鼠标按下事件,其他事件正常返回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)事件过滤器
在分发器前有一个更高级的事件过滤,可在分发器前做一次拦截。
步骤:给控件安装事件过滤器->重写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事件函数重载
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),"山河无恙,春暖花开");
设置画笔:
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高级设置
提高抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
重设坐标原点
如果给出了offset,即按offset更新原点坐标
painter.drawRect(100,100,100,100);
painter.translate(50,0);
painter.drawRect(100,100,100,100);
画家位置的保存与还原
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()函数
//构造函数
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的绘图可以理解为QPainter通过QPaintEngine通讯在QPaintDevice上绘图。
绘图设备即继承QPainterDevice的子类,Qt中共有四种:QPixmap、QBitmap、QImage
QPicture。
QPixmap:专门为图像在屏幕上的显示做了优化。
QBitmap:是QPixmap的子类,他的色深限定为1,即只有黑色和白色,可以使用QPixmap的isBitmap()函数来确定这个Pixmap是不是一个QBitmap。
QImage:专门为图像的像素级访问做了优化。
QPicture:可以记录和重现QPainter的各条命令。
QWidget是一个绘图设备,其父类为QObject和QPaintDevice。
例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");
例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的数据格式如下:
像素级访问:
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);
}
例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);
}
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支持格式如下:
如果是其他格式的文件,需要用到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
比较常用的:
后缀名: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类型,因为没有进行格式化,其打印效果如下:
在HelpMannul中查看QDateTime的格式化函数:
qDebug() << "创建日期:" << info.created().toString("yyyy/MM/dd/ hh:mm:ss");
修改后打印如下: