文章目录
- 1 概述
- 1.1 优点
- 1.2 QT成功使用案例
- 1.3 安装教程
- 1.3.1 在线安装流程
- 1.3.2 离线安装流程
- 2 创建工程
- 2.1 快捷键
- 2.1.1 常用快捷键
- 2.1.2 修改快捷键
- 2.2 proj文件
- 3 对象树
- 4 信号和槽
- 4.1 自定义信号和槽
- 4.1.1 信号连接信号
- 4.1.2 一个信号连接多个槽函数
- 4.1.3 多个信号连接同一个槽函数
- 4.1.3 信号和槽函数的参数列表必须一一对应,但是信号的参数个数可以多于槽
- 4.1.4 断开信号
- 4.2 QT4版本的信号和槽
- 4.3 lambda表达式
- 4.3.1 mutable关键字
- 4.3.2 返回值
- 4.3.3 利用lambda表达式实现槽函数功能
- 4.4 小结
- 5 控件
- 5.1 窗口
- 5.1.1 菜单栏
- 5.1.2 工具栏
- 5.1.3 状态栏
- 5.2 PushButton
- 5.3 对话框
- 5.3.1 模态对话框
- 5.3.2 非模态对话框
- 5.3.3 消息对话框
- 5.3.3.1 消息对话框是模态对话框
- 5.3.3.2 使用案例
- 5.3.4 颜色对话框
- 5.3.4 文件对话框
- 5.3.4 字体对话框
- 5.4 按钮组
- 5.4.1 Radio button
- 5.4.2 Check box
- 5.5 ListWidget
- 5.6 TableWidget
- 5.7 ComboBox
- 5.8 封装自定义控件
- 5.8.1 添加一个新的Widget类
- 5.8.2 设计自定义的控件
- 5.8.3 界面引用自定义的控件
- 5.8.4 实现自定义控件功能
- 6 事件
- 6.1 鼠标Event
- 6.2 定时器
- 6.2.1 Event方式
- 6.2.1 QTimer对象
- 6.3 事件分发器
- 6.4 事件过滤器
- 6.4.1 使用步骤
- 6.4.2 代码示例
- 7 资源文件
- 7.1 添加使用资源文件
- 8 国际化
- 8.1 操作步骤
- 9 参考资料
1 概述
1.1 优点
- 跨平台,几乎支持所有的平台
- 接口设计良好,使用简单
- 一定程度上简化了内存回收机制
- 开发效率高,能够快速的构建应用程序。
- 社区氛围良好,市场份额上升
- 支持嵌入式开发
1.2 QT成功使用案例
- Linux桌面环境KDE
- WPS office软件
- Skype网络电话
- Google Earth
- VLC多媒体播放器
- VirtualBox
1.3 安装教程
从5.15之后了都是在线安装了。
1.3.1 在线安装流程
在线安装流程:
https://blog.csdn.net/Python_0011/article/details/131699443
1.3.2 离线安装流程
【选择组件】
2 创建工程
2.1 快捷键
2.1.1 常用快捷键
Go back: Alt + Left 返回,光标上一次到的那个位置,如从一个文本到了另一个中。
Go Forward: Alt + Right前进
2.1.2 修改快捷键
有时Qt Creator快捷键与系统中的快捷键冲突了,可以自定义或者修改原来的快捷键,步骤如下: 工具-》选项-》环境-》键盘-》,此处比如切换书签的快捷键,Ctrl+M显示红色,就说明冲突了,我们选中这一行,点击Record重新记录,再点击Apply和OK即可
2.2 proj文件
3 对象树
4 信号和槽
4.1 自定义信号和槽
- 定义信号
singals
后面的函数都可以作为信号,信号只有声明,没有实现。
class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:void hungry();void hungry(QString foodName);
};
- 定义槽
public slots
后面的函数都可以作为slot,slot需要有实现。
class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);signals:public slots:void treat();void treat(QString foodName);
};
void Student::treat()
{qDebug() << "请老师吃饭";
}void Student::treat(QString foodName) {qDebug() << "请老师吃饭, 老师要吃" << foodName.toUtf8().data();
}
- 建立连接
调用connect函数建立连接。
void (Teacher::*hungryMethod)(QString) = &Teacher::hungry;
void (Student::*treatMethod)(QString) = &Student::treat;connect(teacher, hungryMethod, student, treatMethod);
- 发出信号
void MainWindow::classOver() {emit this->teacher->hungry("Noodles");
}
【自定义信号或者槽出现重载的情况的解决】
使用函数指针的方式来明确指向的函数的地址。
void (Teacher::*hungryMethod)(QString) = &Teacher::hungry;
void (Student::*treatMethod)(QString) = &Student::treat;
【一个小知识点:QString转为char*】
void Student::treat(QString foodName) {qDebug() << "请老师吃饭, 老师要吃" << foodName.toUtf8().data();
}
4.1.1 信号连接信号
//信号连接信号
void (Teacher::*hungryMethodPure)(void) = &Teacher::hungry;
void (Student::*treatMethodPure)(void) = &Student::treat;
connect(teacher, hungryMethodPure, student, treatMethodPure);
connect(classOverButton, &QPushButton::clicked, teacher, hungryMethodPure);
4.1.2 一个信号连接多个槽函数
4.1.3 多个信号连接同一个槽函数
4.1.3 信号和槽函数的参数列表必须一一对应,但是信号的参数个数可以多于槽
不匹配的情况下会报如下错误:
4.1.4 断开信号
disconnect(classOverButton, &QPushButton::clicked, teacher, hungryMethodPure);
4.2 QT4版本的信号和槽
【优点】
参数直观
【缺点】
编译器不会检测参数类型
4.3 lambda表达式
4.3.1 mutable关键字
//mutable关键字表示可以修改值传递的变量,但是修改的是拷贝,并不是变量本身QPushButton* myBtn = new QPushButton(this);QPushButton* myBtn2 = new QPushButton(this);myBtn2->move(100, 100);int m = 10;connect(myBtn, &QPushButton::clicked, this, [m]()mutable {m = 110; qDebug() << m;});connect(myBtn2, &QPushButton::clicked, this, [=](){qDebug() << m;});qDebug() << m;
4.3.2 返回值
void testReturnInLambda() {int ret = []()->int{return 1000;}();qDebug() << "ret = " << ret;
}
4.3.3 利用lambda表达式实现槽函数功能
/*** @brief testOnButtonClick,利用lambda表达式实现槽函数功能** @param mainWindow*/
void testOnButtonClick(MainWindow* mainWindow) {QPushButton* button = new QPushButton("Clock window", mainWindow);button->move(100, 100);mainWindow->connect(button, &QPushButton::clicked, mainWindow, [=](){mainWindow->getStudent()->treat("Coco cola");mainWindow->close();});
}
4.4 小结
5 控件
5.1 窗口
5.1.1 菜单栏
最多只有一个
5.1.2 工具栏
可以有多个
5.1.3 状态栏
5.2 PushButton
5.3 对话框
5.3.1 模态对话框
不可以操作其他窗口了。
void showModeDialog(QWidget* parent) {QDialog dialog(parent);dialog.resize(200, 100);dialog.exec();
}
5.3.2 非模态对话框
还可以操作其他窗口
void showNoneModeDialog(QWidget* parent) {QDialog* dialog = new QDialog(parent);dialog->resize(200, 100);dialog->setAttribute(Qt::WA_DeleteOnClose);dialog->show();
}
5.3.3 消息对话框
5.3.3.1 消息对话框是模态对话框
5.3.3.2 使用案例
void showMessageBox(QWidget* parent, int dialogType) {switch (dialogType) {case 1:{QMessageBox::critical(parent, "critial", "critial happened");break;}case 2:{QMessageBox::information(parent, "information", "information happened");break;}case 3:{QMessageBox::StandardButton result = QMessageBox::question(parent, "ques", "question happened", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);if (result == QMessageBox::Yes) {qDebug() << "Yes";} else {qDebug() << "No";}break;}case 4:{QMessageBox::warning(parent, "warning", "warning happened");break;}default:QMessageBox::critical(parent, "critial", "critial happened");break;}
}
5.3.4 颜色对话框
void showColorDialog(QWidget* parent) {QColor color = QColorDialog::getColor(QColor(255, 0, 0));QString str = QString("[%1, %2, %3]").arg(color.red()).arg(color.green()).arg(color.blue());qDebug() << str;
}
5.3.4 文件对话框
void showFileDialog(QWidget* parent) {QString filePath = QFileDialog::getOpenFileName(parent, "Sk Open File", "C:\\Users\\imt2047\\Desktop", "(*.png)");qDebug() << filePath;
}
5.3.4 字体对话框
void showFontDialog(QWidget* parent) {bool flag;QFont font = QFontDialog::getFont(&flag, QFont("Times New Roman", 14));QString res = QString("Family:%1, Size:%2, Bold:%3, Italic:%4").arg(font.family()).arg(font.pointSize()).arg(font.bold()).arg(font.italic());qDebug() << res;
}
5.4 按钮组
5.4.1 Radio button
设置默认选中
ui->rBtnMan->setChecked(true);
5.4.2 Check box
5.5 ListWidget
void MainWindow::initListWidget() {
// QListWidgetItem* item = new QListWidgetItem("Hello hello, jin gou bei, jin goubei");
// item->setTextAlignment(Qt::AlignHCenter);
// ui->listWidget->addItem(item);QStringList list;list << "Hello hello, jin gou bei, jin goubei" << "Hello hello, jin gou bei, jin goubei"<< "Hello hello, jin gou bei, jin goubei" << "Hello hello, jin gou bei, jin goubei";ui->listWidget->addItems(list);
}
5.6 TableWidget
void MainWindow::initTableWidget() {ui->tableWidget->setColumnCount(3);ui->tableWidget->setRowCount(5);ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"Name" << "Sex" << "Age");QStringList nameList;nameList << "yase" << "zhoayun" << "zhangfei" << "guanyu" << "huamulan";QList<QString> sexList;sexList<< "Male" << "Male" << "Male" << "Male" << "Female";for (int i = 0; i < 5; i++) {int columnIndex = 0;ui->tableWidget->setItem(i, columnIndex++, new QTableWidgetItem(nameList[i]));ui->tableWidget->setItem(i, columnIndex++, new QTableWidgetItem(sexList[i]));ui->tableWidget->setItem(i, columnIndex++, new QTableWidgetItem(QString::number(i)));}
}
5.7 ComboBox
void MainWindow::initComboBox() {ui->comboBox->addItem("Benz");ui->comboBox->addItem("BMW");ui->comboBox->addItem("125 Moto");connect(ui->selectCarPushButton, &QPushButton::clicked, this, [=](){// ui->comboBox->setCurrentIndex(2);ui->comboBox->setCurrentText("BMW");});
}
5.8 封装自定义控件
5.8.1 添加一个新的Widget类
5.8.2 设计自定义的控件
拖拖拽拽
5.8.3 界面引用自定义的控件
5.8.4 实现自定义控件功能
spinbox和slider联动。
void SmallWidget::setValue(int value) {ui->spinBox->setValue(value);
}int SmallWidget::getValue() {return ui->spinBox->value();
}void SmallWidget::initBaseFunction() {// SpinBox数值变化,Slider跟随滑动void (QSpinBox::* valueChangedSignal)(int) = &QSpinBox::valueChanged;connect(ui->spinBox, valueChangedSignal, ui->horizontalSlider, &QSlider::setValue);// Slider滑动,SpinBox跟随数值变化connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);
}
6 事件
6.1 鼠标Event
#ifndef MYLABEL_H
#define MYLABEL_H#include <QLabel>
#include <QDebug>
#include <QMouseEvent>class MyLabel : public QLabel
{Q_OBJECT
public:explicit MyLabel(QWidget* parent = 0);/*** @brief enterEvent: 覆写基类方法* @param event*/void enterEvent(QEvent *event);void leaveEvent(QEvent *event);void mousePressEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void mouseDoubleClickEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);
};#endif // MYLABEL_H
#include "mylabel.h"MyLabel::MyLabel(QWidget* parent):QLabel(parent)
{// 开启鼠标追踪setMouseTracking(true);
}void MyLabel::enterEvent(QEvent *event) {qDebug() << "mouse in in la.";
}void MyLabel::leaveEvent(QEvent *event) {qDebug() << "mouse out out la.";
}void MyLabel::mousePressEvent(QMouseEvent *event) {// 如果鼠标左键和右键按下,提示信息QString string = QString("Mouse click happened");if (event->button() == Qt::LeftButton) {string = QString("Mouse left button click, x = %1, y = %2").arg(event->x()).arg(event->y());} else if (event->button() == Qt::RightButton) {string = QString("Mouse right button click, x = %1, y = %2").arg(event->x()).arg(event->y());} else {}qDebug() << string;
}void MyLabel::mouseReleaseEvent(QMouseEvent *event) {QString string = QString("Mouse release, x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << string;
}void MyLabel::mouseDoubleClickEvent(QMouseEvent *event) {QString string = QString("Mouse double click, x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << string;
}void MyLabel::mouseMoveEvent(QMouseEvent *event){if (event->buttons() & Qt::LeftButton) {QString string = QString("Mouse moving, x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << string;}
}
6.2 定时器
6.2.1 Event方式
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void timerEvent(QTimerEvent* event);private:Ui::MainWindow *ui;int timerId1;int timerId2;void onTimer1Event(QTimerEvent* event);void onTimer2Event(QTimerEvent* event);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 启动定时器timerId1 = startTimer(1000);timerId2 = startTimer(2000);
}void MainWindow::timerEvent(QTimerEvent* event) {if (event ->timerId() == timerId1) {onTimer1Event(event);} else if (event->timerId() == timerId2) {onTimer2Event(event);}
}void MainWindow::onTimer1Event(QTimerEvent* event) {static int num = 1;ui->label->setText(QString::number(num++));
}void MainWindow::onTimer2Event(QTimerEvent* event) {static int num = 1;ui->label_2->setText(QString::number(num++));
}
6.2.1 QTimer对象
void startQTimer(MainWindow* parent) {QTimer* timer = new QTimer(parent);parent->connect(timer, &QTimer::timeout, parent, [=](){static int num = 1;parent->getUi()->label_3->setText(QString::number(num++));});timer->start(500);parent->connect(parent->getUi()->pauseButton, &QPushButton::clicked, parent, [=](){timer->stop();});parent->connect(parent->getUi()->resumeButton, &QPushButton::clicked, parent, [=](){timer->start(500);});
}
6.3 事件分发器
bool MyLabel::event(QEvent *e) {// 拦截处理鼠标按下事件if (e->type() == QEvent::MouseButtonPress) {QMouseEvent* event = static_cast<QMouseEvent*>(e);handleMousePressEvent(event, "event()");return true;}// 交给父类处理return QLabel::event(e);
}
6.4 事件过滤器
6.4.1 使用步骤
- 控件安装事件过滤器
- 覆写eventFilter函数。
6.4.2 代码示例
void MainWindow::initLabel() {//1. install event filterui->label->installEventFilter(this);
}
/*** 2. override eventFilter** @brief MainWindow::eventFilter* @param object* @param e* @return*/
bool MainWindow::eventFilter(QObject* object, QEvent* e) {if (object == ui->label) {// 拦截处理鼠标按下事件if (e->type() == QEvent::MouseButtonPress) {QMouseEvent* event = static_cast<QMouseEvent*>(e);handleMousePressEvent(event, "eventFilter()");return true;}}return QMainWindow::eventFilter(object, e);
}
7 资源文件
7.1 添加使用资源文件
-
将资源文件拷贝到目录中
-
创建资源文件(qrc文件)
-
编辑资源文件
添加前缀,添加文件。
-
使用资源文件
void MainWindow::initFileMenuItems() {QAction* newAction = new QAction("New");//使用QT资源: : + 前缀名 + 资源名newAction->setIcon(QIcon(":/image/robot_hand.svg"));this->fileMenuItems.append(newAction);this->fileMenuItems.append(new QAction("Open"));
}
8 国际化
8.1 操作步骤
- 生成ts文件
- pro文件增加内容
TRANSLATIONS = ListTableWidgetTest_EN.ts \ListTableWidgetTest_CN.ts
- 使用lupdate生成ts文件
- 查看生成的ts文件
生成的文件就在工程目录中。ts文件就是xml文件。
- 生成qm文件
使用linguist生成。
- 代码中加载qm文件,安装translator,retranslateUi
void MainWindow::on_selectLanguangeComboBox_activated(int index)
{switch(index) {// chinesecase 0:translator->load(":/language/res/ListTableWidgetTest_CN.qm");isChinese = true;break;// englishcase 1:translator->load(":/language/res/ListTableWidgetTest_EN.qm");isChinese = false;break;default:break;}qApp->installTranslator(translator);ui->retranslateUi(this);
}
- 注意ComboBox
retranslateUi刷新UI的时候,会把组合框默认选择第一个。如果同组合框切换语言的时候,要处理下这个选择框。
解决办法就是记录全局变量,记录每一次选择的原因。 如果组合框因为刷新的原因发生了不一致,就根据全局变量重新恢复。
void MainWindow::changeEvent(QEvent *e) {switch (e->type()) {case QEvent::LanguageChange:ui->retranslateUi(this);if (!isChinese && ui->comboBox->currentIndex() == 0) {ui->selectLanguangeComboBox->setCurrentIndex(1);}break;default:break;}
}
9 参考资料
[1] https://www.bilibili.com/video/BV1g4411H78N/?p=11&spm_id_from=pageDriver&vd_source=f4dcb991bbc4da0932ef216329aefb60
[2] https://blog.csdn.net/weixin_51081223/article/details/121671615
[3] https://cloud.tencent.com/developer/article/2245901
[4] https://blog.csdn.net/ihmhm12345/article/details/127408975
[5] 创建PyQT项目: https://www.pythonguis.com/tutorials/first-steps-qt-creator/
[6] ui转换为py,并生成exe: https://www.cnblogs.com/linyfeng/p/11223707.html