alin的学习之路(Qt篇:三)(常用控件,自定义控件,事件捕捉)
1. 常用控件
1.QListWidget
listWidget的每一行都是一个QListWidgetItem,有两种添加的方式
- 一次添加一个QListWidgetItem
QListWidgetItem *item = new QListWidgetItem("锄禾日当午");
ui->listWidget->addItem(item);
//给Item设置对齐方式
item->setTextAlignment(Qt::AlignHCenter);
- 一次性添加一组QListWidgetItems
//一次性添加多个QListWidgetItem需要使用QStringList,相当于QList<QString> -> list<string>
//这种方式添加无法设置格式
QStringList list;
list << "锄禾日当午" << "汗滴禾下土" << "谁知盘中餐" << "粒粒皆辛苦" ;
ui->listWidget->addItems(list);
2.QTreeWidget
-
设置头标签 注意参数类型是QStringList
-
创建item 注意参数类型是QStringList
-
添加到顶层级别的Item
-
再添加的子Item要挂载到顶层Item下
- 创建每个信息的Item
- 将Item挂载到顶层Item上
//1.设置头标签 注意参数类型是QStringList
ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄简介");
//2.创建QTreeWidgetItem 注意参数类型是QStringList
QTreeWidgetItem *liItem = new QTreeWidgetItem(QStringList() << "力量");
//3.添加到顶层级别的QTreeWidgetItem
ui->treeWidget->addTopLevelItem(liItem);
QTreeWidgetItem *minItem = new QTreeWidgetItem(QStringList() << "敏捷");
ui->treeWidget->addTopLevelItem(minItem);
QTreeWidgetItem *zhiItem = new QTreeWidgetItem(QStringList() << "智力");
ui->treeWidget->addTopLevelItem(zhiItem);
//4.再添加的子QTreeWidgetItem要挂载到顶层QTreeWidgetItem下
QStringList heroL1;
QStringList heroL2;
heroL1 << "刚被猪" << "前排坦克,能在吸收伤害的同时造成可观的范围输出";
heroL2 << "船长" << "前排坦克,能肉能输出能控场的全能英雄";
QStringList heroM1;
QStringList heroM2;
heroM1 << "月骑" << "中排物理输出,可以使用分裂利刃攻击多个目标";
heroM2 << "小鱼人" << "前排战士,擅长偷取敌人的属性来增强自身战力";
QStringList heroZ1;
QStringList heroZ2;
heroZ1 << "死灵法师" << "前排法师坦克,魔法抗性较高,拥有治疗技能";
heroZ2 << "巫医" << "后排辅助法师,可以使用奇特的巫术诅咒敌人与治疗队友";
//4.1创建每个信息的QTreeWidgetItem
QTreeWidgetItem *l1 = new QTreeWidgetItem(heroL1);
QTreeWidgetItem *l2 = new QTreeWidgetItem(heroL2);
QTreeWidgetItem *m1 = new QTreeWidgetItem(heroM1);
QTreeWidgetItem *m2 = new QTreeWidgetItem(heroM2);
QTreeWidgetItem *z1 = new QTreeWidgetItem(heroZ1);
QTreeWidgetItem *z2 = new QTreeWidgetItem(heroZ2);
//4.2将Item挂载到顶层Item上
liItem->addChild(l1);
liItem->addChild(l2);
minItem->addChild(m1);
minItem->addChild(m2);
zhiItem->addChild(z1);
zhiItem->addChild(z2);
3.QTableWidget
-
设置列数
-
设置表头水平标签
-
设置行数
-
设置正文
//1.设置列数 ui->tableWidget->setColumnCount(3); //2.设置水平表头标签 ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄"); //3.设置行数 ui->tableWidget->setRowCount(5); //4.设置正文 QStringList namelist; namelist << "亚瑟" << "刘备" << "妲己" << "上官婉儿" << "梦琪"; QStringList sexlist; sexlist << "男" << "男" << "女" << "女" << "男"; for(int i=0 ;i<5 ;++i) { int col = 0; //插入正文的每一个元素都是一个QTableWidgetItem ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i])); ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexlist.at(i))); ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(18+i))); }
-
创建两个按钮来添加和删除一行内容
connect(ui->btn_add,&QPushButton::clicked,[=](){ //判断赵云是否已在表格中,findItems返回的是一个QList bool isEmpty = ui->tableWidget->findItems("赵云",Qt::MatchExactly).isEmpty(); if(!isEmpty) { QMessageBox::warning(this,"警告","赵云已存在,无法重复添加"); } else { int col = 0; //先添加一行,再在添加的这行上操作 ui->tableWidget->insertRow(0); ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString("赵云"))); ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString("男"))); ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString::number(30))); } }); connect(ui->btn_del,&QPushButton::clicked,[=](){ bool isEmpty = ui->tableWidget->findItems("赵云",Qt::MatchExactly).isEmpty(); if(isEmpty) { QMessageBox::warning(this,"警告","赵云不存在,无法删除"); } else { int rowNum = ui->tableWidget->findItems("赵云",Qt::MatchExactly).first()->row(); ui->tableWidget->removeRow(rowNum); } });
4.stackedWidget
-
概述:可以用来显示不同的界面,达到隐藏其他界面的效果
-
使用它来存放:scrollArea,toolBox和tabWidget,并且使用三个按钮达到点击切换的效果
//设置初始显示 ui->stackedWidget->setCurrentIndex(0); //点击按钮显示指定的stackedWidget页 connect(ui->btn_Scroll,&QPushButton::clicked,[=](){ ui->stackedWidget->setCurrentIndex(0); }); connect(ui->btn_Tool,&QPushButton::clicked,[=](){ ui->stackedWidget->setCurrentIndex(1); }); connect(ui->btn_Tab,&QPushButton::clicked,[=](){ ui->stackedWidget->setCurrentIndex(2); });
5.comboBox
下拉框式选择
//添加comboBox中的Item
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("保时捷");
connect(ui->btn_select,&QPushButton::clicked,[=](){
//点击跳转到目的Item
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("保时捷");
});
6.label添加图片
-
静态图:使用QPixmap进行添加
//给label添加图片,并且要贴合大小 QPixmap pix; pix.load(":/Image/butterfly.png"); ui->label_picture->setPixmap(pix); ui->label_picture->resize(pix.width(),pix.height());
-
动图:使用QMovie进行添加,添加后要调用start()才能放映
//利用label显示动图 使用QMovie QMovie *movie = new QMovie(":/Image/mario.gif"); ui->label_movie->setMovie(movie); movie->start(); //有这条语句才可播放 movie->setSpeed(500); //设置倍速 //设置播放完就停止 不循环播放 //方法:当动图播放到最后一帧时设置停止 connect(movie,&QMovie::frameChanged,[=](int frameId){ if(frameId == movie->frameCount()-1) { movie->stop(); } });
2.自定义控件
需求:使用SpinBox和HorizontalSlider进行联动,改变SpinBox的值HorizontalSlider的进度条会移动,移动HorizontalSlider的进度条SpinBox的值会改变
步骤:
1. 创建一个Qt设计师界面类并将两个控件进行封装成一个类
2. 在主界面添加一个Widget将其提升为类
3. 在封装的类中书写实现联动的代码
//更改SpinBox的值 Slider跟着滑动
void(QSpinBox::* signal)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,signal,ui->horizontalSlider,&QSlider::setValue);
//滑动Slider 更改Spinbox的值
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
创建两个按钮:一个点击实现将值设置为50,一个点击获取值
//点击设置为50
connect(ui->btn_set,&QPushButton::clicked,[=](){
ui->widget->setData(50);
});
//点击返回当前值
connect(ui->btn_get,&QPushButton::clicked,[=](){
qDebug() << ui->widget->getData();
});
3.事件捕捉
1.鼠标相关事件
捕捉鼠标进入一个label和在label中点击相关的事件
步骤:
- 添加一个label并创建一个MyLabel类
- 将label提升为MyLabel类,在MyLabel类中重写事件捕捉的相关函数
//MyLabel.h
public:
explicit MyLabel(QWidget *parent = nullptr);
//鼠标进入事件
void enterEvent(QEvent *event);
//鼠标离开事件
void leaveEvent(QEvent *event);
//鼠标点击事件
void mousePressEvent(QMouseEvent *ev);
//鼠标释放事件
void mouseReleaseEvent(QMouseEvent *ev);
//鼠标移动事件
void mouseMoveEvent(QMouseEvent *ev);
//事件分发器
bool event(QEvent *e);
//MyLabel.cpp
//鼠标进入事件
void MyLabel::enterEvent(QEvent *event)
{
//qDebug() << "鼠标进入了";
}
//鼠标离开事件
void MyLabel::leaveEvent(QEvent *event)
{
//qDebug() << "鼠标离开了";
}
//鼠标点击事件
void MyLabel::mousePressEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
QString str = QString("鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
qDebug() << str;
}
}
//鼠标释放事件
void MyLabel::mouseReleaseEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
QString str = QString("鼠标释放了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
qDebug() << str;
}
}
//鼠标移动事件
void MyLabel::mouseMoveEvent(QMouseEvent *ev)
{
//注意判断按键时,要使用buttons()的接口&相应的枚举值
if(ev->buttons() & Qt::LeftButton)
{
QString str = QString("鼠标移动了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
qDebug() << str;
}
}
2.事件分发器
事件分发器处于app与事件捕获函数之间,是高一级的事件处理
//事件分发器
bool MyLabel::event(QEvent *e)
{
//捕获事件
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent* ev = dynamic_cast<QMouseEvent*>(e);
QString str = QString("在event中 鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
qDebug() << str;
return true; //true代表拦截,不向下分发
}
//其他交给父类处理
return QLabel::event(e);
}
3.事件过滤器
事件过滤器处于app和事件分发器之间,是更高一级的事件处理
步骤:
- 给指定控件添加事件过滤器
- 重写事件过滤器函数
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//1.先给控件安装过滤器
ui->label->installEventFilter(this);
}
//2.重写事件过滤器函数
//参数1:判断控件 参数2:判断事件
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
//判断是哪一控件
if(watched == ui->label)
{
//捕获事件
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* ev = dynamic_cast<QMouseEvent*>(event);
QString str = QString("在eventFilter中 鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
qDebug() << str;
return true; //true代表拦截
}
}
//其他交给父类处理
return QWidget::eventFilter(watched,event);
}
4.定时器事件
定时器事件用于定时触发事件,有两种书写方法:
-
定时器事件
//开启一个定时器,单位是毫秒,返回一个该定时器的唯一标识int this->m_Id1 = startTimer(1000); this->m_Id2 = startTimer(2000); //定时器事件 void Widget::timerEvent(QTimerEvent *event) { if(event->timerId() == m_Id1) { static int num = 1; ui->label->setText(QString::number(num++)); } if(event->timerId() == m_Id2) { static int num = 1; ui->label_2->setText(QString::number(num++)); } }
-
定时器类(同时设定两个按钮来控制暂停和开始)
//使用定时器类 QTimer *timer = new QTimer(this); timer->start(500); //与定时器事件的接口区分,该接口是start() connect(timer,&QTimer::timeout,[=](){ static int num = 1; ui->label_3->setText(QString::number(num++)); }); //按钮暂停 connect(ui->pushButton,&QPushButton::clicked,[=](){ timer->stop(); }); //按钮开始 connect(ui->pushButton_2,&QPushButton::clicked,[=](){ timer->start(500); });