1 QT简介
1.1 Qt模块:
-
Qt Core模块: 是QT类库的核心,所有其他模块都依赖这个模块
-
Qt Gui模块: 提供GUI程序的基本功能
-
Qt Network模块:提供跨平台的网络功能
-
Qt Widgets模块:提供创建用户界面的功能
1.2Qt的signal/slot机制
任何一个类只要类体前部书写 Q_OBJECT即可使用Qt的信号/槽机制。
信号和槽的本质是函数
当一个Qt对象的内部状态发生变化的时候,就会发出一个信号,信号起始也是一个函数 当Qt对象收到信号以后,自动去执行对应的函数,这个自动执行的函数就是槽函数
信号与槽之间需要建立连接,才能够将信号与槽函数关联起来 对于信号与槽之间的连接,需要明确以下信息: 是哪个对象发出信号 发出了哪个信号 由谁来接收这个信号 接收到信号以后怎么处理
信号与槽是通过 connect 函数来建立连接的 所以,connect函数的常规参数如下: connect(sender,SIGNAL(信号函数的函数名(参数类型)),receiver,SLOT(槽函数的函数名(参数类型)));
1.2.1 写法一
private slots: void button_clicked_slot(); void Widget::button_clicked_slot() { qDebug()<<"按键被点击"; } QPushButton *button=new QPushButton(this); button->setText("OK"); connect(button,&QPushButton::clicked,this,&Widget::button_clicked_slot);
// 传统Qt是连接方式 // 传统Qt4连接方式为 信号发送者,信号,信号接受者,处理函数 QObject::connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(qT4_slot()));
//Qt5连接方式 //其实这么写的方式和Qt4没有啥却别,只是在Qt4 中引用了信号槽,在简单的使用时没有问题,但是在庞大的工程中,信号和曹 仅仅是宏替换,在编译的时候没有安全监测 //Qt5的新方法,在编译的时候就会有监测,如果我们手误操作失误,就会出现问题 QObject::connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::qT5_slot);
1.2.2 写法二
直接在ui设计里面生成一个按钮,然后转到对应的槽,写入要操作的内容,即可
1.2.3 写法三
//Qt5 Lambda表达式 //这里需要注意 Lambda表达式是C++ 11 的内容,所以,需要再Pro项目文件中加入 CONFIG += C++ 11 QObject::connect(ui->pushButton_3,&QPushButton::clicked,[=](){qDebug()<<"lambda 表达式";});
1.3 自定义信号和槽函数
signals: void windowClose(QString);//声明一个自定义信号 private slots: void m_on_windowClose(QString);//自定义槽函数,alt+enter 可以快速生成函数定义 //手动连接信号与槽 connect(this,SIGNAL(windowClose(QString)),this,SLOT(m_on_windowClose(QString))); //槽函数 void m_on_windowClose(QString) { this->close();//关闭主页面 } //发送信号 QString str{"你好"}; emit windowClose(str);
声明槽函数注意点:
-
如果是自己的定义的槽函数,建议不要以 on_ 开头,因为以 "on_" 开头,Qt会认为这个是它自动生成的槽函数,在它自己声明的参函数列表中又找不到这个声明,那么就会报警告!
-
槽函数一旦声明了,就一定要实现!!!否则就会报错!
信号与槽的连接方式: 信号与槽有两种连接方式:自动连接、手动接连
信号与槽的连接方式: 信号与槽有两种连接方式:自动连接、手动连接
自动连接:在UI设计器中,右键选择对象,选择转到槽,然后选择对应的信号, 那么就会在类中自动添加一个槽函数的声明以及在源文件(.cpp)文件中自动添加一个槽函数的定义,这个槽函数会自动和对应的信号连接
手动连接:手动调用connect函数来完成对应的信号与槽函数的连接
1.4 QT图片类型
QT图片的类型有4种,QPixmap,QImage,QBitmap,QPicture
QPixmap:
-
在加载图片的时候,是将图片加载到显存里面,如果图片太大可能会加载失败
-
在显示图片的时候,可以在不修改图片数据的前提下对图片进行缩放或者放大显示
-
在不同的系统下,显示图片的效果可能会不相同
-
label->setPixmap(QPixmap(filename));
QImage:
-
在加载图片的时候,是将图片加载到内存中
-
在显示图片的时候,以原图显示
-
在不同的系统下,显示图片的效果是相同的
显示图片: //直接使用文件的路径 ui->label->setPixmap(QPixmap("../showpic/image/caixukun.png")); ui->label->setScaledContents(true); //让图片自动适应控件大小 //使用资源文件中的文件 QPixmap pix{":/image/caixukun.png"}; ui->label->setPixmap(pix); ui->label->setScaledContents(true); //让图片自动适应控件大小 显示动图或者视频: QMovie *mov = new QMovie{":/image/caixukun.gif"}; ui->label->setMovie(mov); ui->label->setScaledContents(true); //让图片自动适应控件大小 mov->start(); 显示图片: //直接使用文件的路径 ui->label->setPixmap(QPixmap("../showpic/image/caixukun.png")); ui->label->setScaledContents(true); //让图片自动适应控件大小 //使用资源文件中的文件 QPixmap pix{":/image/caixukun.png"}; ui->label->setPixmap(pix); ui->label->setScaledContents(true); //让图片自动适应控件大小 显示动图或者视频: QMovie *mov = new QMovie{":/image/caixukun.gif"}; ui->label->setMovie(mov); ui->label->setScaledContents(true); //让图片自动适应控件大小 mov->start();
1.5 setStyleSheet()
样式-英文 | 参数 | 样式-中文 |
---|---|---|
color: | white rgb(110,110,110) #eb7350 | 前景颜色,字体颜色 |
background: | transparent | 背景为透明 |
background-color: | white rgb(110,110,110) #eb7350 | 背景颜色 |
background-position: | left right center top bottom | 设定图片的位置 |
background-image:url() | ./img/back.jpg | 背景图片 ,不缩放图片大小 |
border-image:url() | ./img/back.jpg | 背景图片,会对图片进行拉伸,平铺 |
border-style: | outset inset | 边框样式,按下是inset |
border-width: | px | 边框大小 |
border-radius: | px | 边框弧度 |
border:3px solid red | px color | 边框宽度以及颜色 |
border-color: rgba(255, 225, 255, 30); | color | 边框颜色 |
font-family | 微软雅黑 | 设定字体所属家族 |
font: bold 14px | bold px | 字体大小并加粗 |
font-size: | px | 字体大小 |
font-style: | inset | 字体样式 |
font-weight: | px | 字体深浅 |
selection-color: | color | 设定选中时候的颜色 |
eg: ui->pushButton->setStyleSheet("border-image: url(:/images/Coin0001.png);");
1.6 QT样式表ui设计
1.6.1 方法一:
样式表常见设置
//加上#对象,则里面属性设置只针对于该对象 QWidget#centralWidget { background-image: url(:/bg2.jpg);//直接设置背景图片,但是图片大小不会自适应 //border-image: url(:/bg2.jpg);图片大小会自适应centralWidget大小 } QPushButton#btn_test2 { border-image: url(:/caixukun.png); } QPushButton#btn_test:hover//当鼠标落在按钮上面时设置一种颜色 { background-color: rgb(87, 174, 201); } QPushButton#btn_test:pressed//当鼠标点击按钮上面时设置一种颜色 { background-color: rgb(87, 174, 201); } QPushButton#btn_test:!hover//当鼠标离开按钮时 { background-color: rgb(137, 194, 227); } QPushButton#btn_test { border-width:2px; border-color: rgb(243, 78, 20); border-style:solid; border-radius:50px;//border-radius 允许你设置元素的外边框圆角 color: rgb(239, 41, 41);//设置字体颜色 }
1.6.2 方法二:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); //可以看到在代码中设置样式,为了方便阅读,使用了繁琐的Tab和换行 //因此除了特殊地方需要在代码追加修改样式,项目里一般建议在文本文件内写样式表 ui->btn2->setStyleSheet("QPushButton{\ background:#EE6AA7;\ border:1px solid #8B7E66;\ border-radius:5px;\ color:white;\ }\ QPushButton:hover{\ background:#FF6EB4;\ }\ QPushButton:pressed{\ background:#CD6090; \ }"); }
1.7 QT定时器
Qt中的定时器能够实现定时执行某个函数 Qt中的定时器是通过 QTimer 来实现的 在使用 QTimer 之前需要添加头文件 #include <QTimer>
先实例化一个QTimer的定时器对象 QTimer timer(this); 设置定时器的间隔时间(定时时长) timer.setinterval(int msecs); //单位是 毫秒! 定时器会定时产生信号 timout() 所以,需要将该信号与对应的槽函数连接起来 connet(&timer,SIGNAL(timout()),this,SLOT(槽函数())); 连接以后,定时器不会自动启动(开始计时),需要手动调用start()函数来启动 以及通过 stop() 函数来停止 timer.start(); //启动定时器 timer.stop(); //停止定时器
定时器案例
void Dialog::timer_init() { //实例化一个定时器对象 timer = new QTimer(this); //设置定时的间隔时间(1秒钟=1000毫秒) timer->setInterval(1000); //连接定时器的定时信号和对应的槽函数 connect(timer,SIGNAL(timeout()),this,SLOT(m_on_timeout())); } void Dialog::m_on_timeout() { //获取系统时间 QDateTime dateTime = QDateTime::currentDateTime(); QString time = dateTime.toString("yyyy-MM-dd HH:mm:ss"); //显示到界面 ui->label->setText(time); } void Dialog::on_btn_start_clicked() { //启动定时器 timer->start(); } void Dialog::on_btn_stop_clicked() { //停止定时器 timer->stop(); }
单singleShot,表示它只会触发一次,发出一次信号,然后来执行槽函数。
QTimer::singleShot(2000, this, [this]() { //等待2s之后运行里面的程序 });
1.8 Qt的文件操作
Qt对文件的操作是通过Qt的文件对象来实现的 在Qt中 QFile 就是文件类型 在使用这个类型的时候需要加头文件 #include <QFile>
-
先实例化一个Qt文件对象:
QFile file; QFile file{文件路径名};
-
打开文件:
file.open(文件打开标志); 文件打开标志: QIODevice::NotOpen QIODevice::ReadOnly QIODevice::WriteOnly QIODevice::ReadWrite QIODevice::Append QIODevice::Truncate QIODevice::Text
-
读取数据:
file.read(); qint64 read(char *data, qint64 maxSize) QByteArray read(qint64 maxSize) QByteArray readAll() qint64 readLine(char *data, qint64 maxSize) QByteArray readLine(qint64 maxSize = 0)
-
写入数据:
file.write(); qint64 write(const char *data, qint64 maxSize) qint64 write(const char *data) qint64 write(const QByteArray &byteArray)
-
关闭文件:
file.close();
-
案例介绍
#include <QFileDialog> void Dialog::on_pushButton_clicked() { QString file_path = QFileDialog::getOpenFileName(this,"打开文件","../","*.txt *.h *.c *.cpp"); //实例化一个文件对象 QFile file{file_path,this}; //打开文件 bool ok = file.open(QIODevice::ReadOnly); if(!ok) { //文件打开失败 qDebug() << "open file error!"; return; } //读取数据 while(!file.atEnd()) { QString text = file.readLine(); //将读到的数据添加到listWidget这个控件中去 ui->listWidget->addItem(text); } //关闭文件 file.close(); }
1.9 QT网络编程
TCP协议只需要用两个类 QTcpServer、QTcpSocket
在Qt中如果需要用到网路,就需要在项目的项目管理文件(.pro)文件中添加网络模块:
QT += network
QTcpServer QTcpServer是Qt中的一个类型,它提供了基于TCP协议的服务器编程接口,可以实现服务器端的网络通信。通过QTcpServer这个类型,我们可以很方便、快速地创建一个TCP服务器, 接收来自客户端的连接请求,并与客户端进行通信。
QTcpServer提供了一些信号,如:newConnection()、disconnected()、readyRead()等 用于通知这些事件的发生。 所以,在使用QTcpServer时,可以将对应的信号与槽函数连接,实现各种功能。
QTcpSocket QTcpSocket为Qt的TCP通信提供了套接字,服务器和客户端之间就是通过套接字来通信的
Tcp服务器的使用
1. 实例化一个服务器对象: QTcpServer tcpServer{this}; 2. 服务器绑定IP地址和端口以及监听客户端的连接: tcpServer.listen(QHostAddress("192.168.110.233"),6666); 3. 当有客户端连接的时候,会发信号: newConnection(); 4. 当监听到客户端连接请求信号,就去处理该连接 connect(tcpServer,SIGNAL(newCConneciton()),this,SLOT(m_on_new_connevtion())); 5. 从连接列表中获取下一个连接对象 QTcpSocket *nextTcpSocket = tcpServer->nextPendingConnection(); 6. 获取对端(客户端)的IP地址和端口号 QString clientIp = nextTcpSocket->peerAddress().toString(); //获取IP地址 quint16 port = nextTcpSocket->peerPort(); //获取端口号
服务器和客户端传输数据
方法一: 写数据端: char data[200]={0}; data[0]='a'; data[1]='b'; data[2]='c'; socket.write(data,3); 读数据端: char data[200]={0}; socket.read(data,200); data里面既有数据
方法二: 写数据端: // 发送响应数据给客户端 QString message = "Hello, client!"; clientSocket->write(message.toUtf8()); // 等待数据发送完成 clientSocket->waitForBytesWritten(); 读数据端: // 等待接收服务器响应数据 clientSocket.waitForReadyRead(); QByteArray responseData = clientSocket.readAll(); QString response = QString::fromUtf8(responseData); qDebug() << "Received from server:" << response;
1.10 串口
Qt5中的串口模块为 Qt Serial Port Qt5中新增了串口模块,如果需要用到Qt的串口模块,就需要在Qt项目的配置文件中加入一下命令: QT += serialport
该模块中包含两个类,QSerialPort和QSerialPortInfo 本项目中只用QSerialPort类即可
大致的使用步骤:
1.加载头文件 #include <QSerialPort> 2.实例化一个串口对象 QSerialPort * = new QSerialPort(this); 3.设置串口的属性 //设置串口文件的路径名(/dev/ttySAC1) serial->setPortName("/dev/ttySAC1"); //设置串口波特率:9600 serial->setBaudRate(QSerialPort::Baud9600); //设置数据位:8位 serial->setDataBits(QSerialPort::Data8); //设置奇偶校验位:无校验 serial->setParity(QSerialPort::NoParity); //设置停止位:1位 serial->setStopBits(QSerialPort::OneStop); //设置流控:无流控 serial->setFlowControl(QSerialPort::NoFlowControl); 在开发板的右上角有4排串口引脚,只有前三排能用,对应的串口文件的路径为: /dev/ttySAC1 /dev/ttySAC2 /dev/ttySAC3 4.连接信号与槽 connect(serial,SIGNAL(readyRead()),this,SLOT(m_on_ready_read())); 5.打开串口 serial->open(QIODevice::ReadWrite); 6.通过串口读写数据,和文件io是一样的了 read() readAll() write() •当串口外接的设备有数据可读的时候,串口对象serial会自动发送信号:readyRead() •所以只要将这个信号关联起来,就可以在相应的槽函数中读到数据了 •写数据就通过write函数写就可以了!!!
1.11 线程
方法一:
#include <QDebug> #include <QThread> // 创建线程 QThread thread; // 将线程对象移动到新线程中 thread.moveToThread(&thread); // 连接线程的started信号到自定义的槽函数 QObject::connect(&thread, &QThread::started, [=]() { qDebug() << "Thread started"; // 模拟耗时操作 for (int i = 0; i < 5; i++) { QThread::sleep(1); qDebug() << "Thread working..."; } qDebug() << "Thread finished"; // 退出线程事件循环 QCoreApplication::quit(); }); // 启动线程 thread.start(); // 等待线程完成 thread.wait();
方法二:
自定义对象创建线程
class MyThread : public QThread { public: void run() override { // 执行线程的工作 for (int i = 0; i < 10; i++) { qDebug() << "Thread running" << i; sleep(1); // 暂停1秒 } } }; 主程序: MyThread thread; thread.start(); // 等待线程完成 thread.wait();
2 控件
2.1 pushButton
#include <QPushButton> int main(int argc,char *argv[]) { QApplication app(argc,argv); QPushButton helloButton("Hello QT!"); helloButton.resize(100,30); helloButton.show(); return app.exec; }
常见信号
-
clicked() 点击
-
pressed() 按下
-
release() 释放
2.2 QIcon和QPixmap
QIcon testIcon("\\blankProject\\temp.bmp"); ->setIcon(testIcon); ->setIcon(QIcon("\\blankProject\\temp.bmp")); ->setIconSize(QSize(200,200));
QPixmap dlg(":/picture/dialog.png"); ->setFixedSize(dlg.size()); ->setPixmap(dlg);
2.3 QWidget常见槽函数
QWidget: close() 关闭窗口 show() 显示窗口 hide() 隐藏窗口 setVisible(bool visible) 设置窗口是否可见 repaint() 重新绘制界面(控件),相当于刷新 update() 刷新 setEnabled(bool) 控制界面(控件)是否接收输入事件 setStyleSheet(const QString &styleSheet) 设置样式规则
2.4 QStackedWidget 控件
-
添加页面
-
页面切换插入第三页
-
代码跳转页面
切记:stackedWidget的页面是从第0面开始
//方法一:自定义连接函数,采用lambda表达式方式 connect(ui->pushButton, &QPushButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(0);}); connect(ui->pushButton_2, &QPushButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(1);}); connect(ui->pushButton_3, &QPushButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(2);});}
//方法二: void MainWindow::switchPage(){ QPushButton *button = qobject_cast<QPushButton*>(sender()); //当QPushButton发出一个信号时就记录发出这个信号的对象,sender获取发出信号的对象; if(button==ui->pushButton) ui->stackedWidget->setCurrentIndex(0); else if(button==ui->pushButton_2) ui->stackedWidget->setCurrentIndex(1); else if(button==ui->pushButton_3) ui->stackedWidget->setCurrentIndex(2); int i = 0; ui->stackedWidget->widget(i); } void MainWindow::on_pushButton_clicked() { switchPage(); } void MainWindow::on_pushButton_2_clicked() { switchPage(); } void MainWindow::on_pushButton_3_clicked() { switchPage(); }
2.5 QMessageBox
2.5.1 写法一
QMessageBox msgBox; msgBox.setText("The document has been modified."); msgBox.exec();
2.5.2 写法二
QMessageBox msgBox; msgBox.setText("The document has been modified."); msgBox.setInformativeText("Do you want to save your changes?"); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Save); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Save: // Save was clicked break; case QMessageBox::Discard: // Don't Save was clicked break; case QMessageBox::Cancel: // Cancel was clicked break; default: // should never be reached break; }
3 QT技巧
3.1 QString
#include<QDebug> //输出头文件 qDebug()<<text; //速出text //Qstring的用法 //初始化字符串 QString s1; s1 = "hello; //赋值 QString s2("hello"); //赋值 s2.clear(); //清空s2 QString s3("123456"); s3.size(); //计算s3的长度 s3.append(“789”); //追加数据“789” //字符串拼接加转换 int h=9,m=34,s=20; QString s4 = Qstring::fromUtf8("当前时间是 %1:%2:%3").arg(h).arg(m).arg(s); qDebug()<<s4; //输出是:当前时间是 9:34:20 //fromLocal8Bit 字符串转换为本地编码 也就是可以汉字显示 QString{"insert into user(username,passwd) values('%1','%2');"}.arg(name).arg(passwd); //字符串切割 QString str5("2023/3/1"); QStringList list = str5.split("/"); //List容器 for(int i = 0; i<list.size(); i++) { qDebug()<<list[i]; } //判断字符串是否以指定的字符串结尾,判断后缀名 str6 = "1.bmp"; if(str6.endsWith(".bmp") qDebug()<<"is bmp"; //字符串转换 //整形转换为字符串 int val = 123; QString s7 = QString::number(val); //将字符串转换为整数 int data = s7.toInt(); qDebug()<<data; //字符串QString 与 char *之间的转换 QString s8("hello"); char *str = s8.toLocal8Bit().data(); qDebug()<<str; //字符串QString 转换成 C++中的string std::string s9 = s8.toStdString(); qDebug()<<s9.c_str(); //QT没有做C++的string的重载,所以要.c_str(); //迭代器进行遍历 for(QString::iterator it = s9.begin(); it!=s9.end(); it++) { qDebug()<<*it; } //字符串查找或包含 QString str10 = hello 123; QRegExp re([0-9]{3,}); //使用正则表达式 需要头文件#include<QRegExp> if(str4.contains(re)) qDebug()<<yes; else qDebug()<<no;
QRegExp正则表达式解释
\d 任意一个数字,0~9 中的任意一个 \w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个 \s 包括空格、制表符、换页符等空白字符的其中任意一个 . 小数点可以匹配除了换行符(\n)以外的任意一个字符 [ab5@] 匹配 "a" 或 "b" 或 "5" 或 "@" [^abc] 匹配 "a","b","c" 之外的任意一个字符 [f-k] 匹配 "f"~"k" 之间的任意一个字母 [^A-F0-3] 匹配 "A"~"F","0"~"3" 之外的任意一个字符 {n} 表达式重复n次,比如:"\w{2}" 相当于 "\w\w";"a{5}" 相当于 "aaaaa" {m,n} 表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa" {m,} 表达式至少重复m次,比如:"\w\d{2,}"可以匹配 "a12","_456","M12344"... ? 匹配表达式0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad" + 表达式至少出现1次,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab"... * 表达式不出现或出现任意次,相当于 {0,},比如:"\^*b"可以匹配 "b","^^^b"... ^ 与字符串开始的地方匹配,不匹配任何字符 $ 与字符串结束的地方匹配,不匹配任何字符 \b 匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符
3.2 点击按钮弹出对话框/提示框
//这样的话当你点击按钮发送信号的时候会弹出一个提示框,提示内容就是括号里面内容 QMessageBox msgBox; msgBox.setText("The document has been modified."); msgBox.exec(); //扩展 QMessageBox msgBox; msgBox.setText(QString::fromUtf8("注册成功")); msgBox.setInformativeText("Do you want to save your changes?"); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Save); int ret = msgBox.exec();
3.3 按钮设置成特定图片样子
QPushButton *button=new QPushButton(this); QPixmap pix; bool ret=pix.load(":/images/Coin0001.png"); if(!ret) { qDebug()<<"图片加载失败"; return; } //设置图片固定大小 button->setFixedSize(pix.width(),pix.height()); //设置不规则图片样式 button->setStyleSheet("QPushButton{border:0px;}"); //设置图标 button->setIcon(pix); //设置图标大小 button->setIconSize(QSize(pix.width(),pix.height()));
3.4 设置按钮点击动态方法
void MyPushButton::zoom1() { QPropertyAnimation* animation = new QPropertyAnimation(this,"geometry");//animation动画制作 //设置动画时间间隔 animation->setDuration(200); //设置起始位置 animation->setStartValue(QRect(this->x(),this->y()+10,this->width(),this->height())); //设置结束位置 animation->setEndValue(QRect(this->x(),this->y(),this->width(),this->height())); //设置弹跳曲线 animation->setEasingCurve(QEasingCurve::OutBounce); //执行动画 animation->start(); }
3.5 自定义延时函数
#include<QTime> //延时功能 void sleep(unsigned int msec){ //currnentTime 返回当前时间 用当前时间加上我们要延时的时间msec得到一个新的时刻 QTime reachTime = QTime::currentTime().addMSecs(msec); //用while循环不断比对当前时间与我们设定的时间 while(QTime::currentTime()<reachTime){ //如果当前的系统时间尚未达到我们设定的时刻,就让Qt的应用程序类执行默认的处理, //以使程序仍处于响应状态。一旦到达了我们设定的时刻,就跳出该循环,继续执行后面的语句。 QApplication::processEvents(QEventLoop::AllEvents,100); } }
#include<QThread> QThread::sleep(1);
3.6 mainWindow的常见设置
//设置固定大小 setFixedSize(500,900); //设置图标 setWindowIcon(QIcon(":/resource/Coin0001.png")); //设置标题 setWindowTitle("翻金币主场景");
3.7 利用Label标签显示图片
//生成胜利图片在最上方 QLabel *winLabel=new QLabel; QPixmap winpix; winpix.load(":/resource/LevelCompletedDialogBg.png"); //或者 QPixmap winpix=QPixmap(":/resource/LevelCompletedDialogBg.png"); winLabel->setGeometry(0,0,winpix.width(),winpix.height()); //从窗体的(0,0)位置开始(即为最左上角的点),显示一个w*h的控件。即设置label标签的大小 label->setScaledContents(true); //如果图片大小没有标签那么大,那么让图片大小自适应控件大小 winLabel->setPixmap(winpix); winLabel->setParent(this); winLabel->move(winpix.width()/2,-winpix.height());
3.8 显示动图或者视频
#include<QMovie> QLabel *label=new QLabel; label->setParent(this); label->setGeometry(0,0,200,200); QMovie *movie=new QMovie(":/images/mov.gif"); label->setMovie(movie); label->setScaledContents(true); movie->start();
3.9 重写paintEvent函数实现画图
QWidget中的paintEvent事件处理器可以在子类中被重写来接收绘图事件,然后在指定区域完成图形的绘制。 首先在头文件的Widget子类中进行声明 void paintEvent(QPaintEvent *event);
void MainWindow::paintEvent(QPaintEvent *) { //画背景色 QPalette palette ; palette.setColor(QPalette::Background,QColor("#B1723C")); this->setAutoFillBackground(true); this->setPalette(palette); //画线 painter.drawLine(0,0,100,100); //画圆形 QBrush brush; brush.setStyle(Qt::SolidPattern); painter.setPen(Qt::NoPen); //去掉pen,避免画出的棋子边缘带线条 brush.setColor(Qt::black); painter.setBrush(brush); painter.drawEllipse(x0,y0,w,h); // 画图形 QPainter painter(this); QPixmap pix; pix.load(":/resource/PlayLevelSceneBg.png"); painter.drawPixmap(0,0,this->width(),this->height(),pix); this->update();//代码会自己调用一次这个函数,如果想要手动调用绘图事件,可以使用update()函数 }
3.10 Qt 定时器翻转金币
timer1=new QTimer(this); connect(timer1,&QTimer::timeout,[=](){ QPixmap pix; QString str=QString(":/resource/Coin000%1.png").arg(this->min++); pix.load(str); setCoinStyle(pix); //判断如果翻转完毕,则将Min置为1 if(min>max) { this->min=1; timer1->stop(); } }); timer->start(msec );
4 散乱知识点
4.1 创建Qt资源文件
4.1.1.第一步:打开工程目录文件夹
4.1.2.第二步:在项目目录文件夹中创建一个 resource 文件夹。
创建好了resource文件夹后继续往这个文件夹 放文件。
4.1.3.第三步:创建Qt资源文件
将名称填号后,浏览路径,找到resource文件夹选择它,然后点下一步,下一步后继续点 确定 就好了。 创建成功后会发现项目树里多了一个资源出来哦。
4.1.4.第四步:然后添加前缀,相当于一个文件夹把,拿来分类资源的
4.1.5 添加想要加入的资源路劲即可
4.2 文件过滤器
#include <QFileDialog> #include <QDebug> QString picPath=QFileDialog::getOpenFileName(this,"选择图片文件","*.bmp *.png *.jpg *.jpeg"); qDebug()<<picPath;
4.3 解决标签字体显示不完全问题
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
###
二、QT数据库
1 数据库创建的基本步骤
数据库头文件:
#include <QSqlDatabase> #include <QSqlError> #include <QSqlQuery>
1.1 Qt中的数据库相关的类型以及接口放在一个单独的模块中,模块名为 sql
QT += sql
1.2 连接数据库
//初始化连接对象,使用静态成员函数addDatabase,参数是数据库的类型 //其中sqlite3 以及 更高的版本的类型名为 QSQLITE userDb = QSqlDatabase::addDatabase("QSQLITE"); //设置数据库库名,建议带路径,如果数据库存在,则直接打开,如果数据不存在,则创建再打开 //使用成员函数setDatabaseName来设置数据库的名称 userDb.setDatabaseName("../sql/user.db");
1.3 打开数据库
bool ok = userDb.open(); if(!ok) { //打开数据库失败 qDebug() << "Open userDb error:" << userDb.lastError().text(); return; }
1.4 创建表格user
//需要执行SQL的语句,需要先实例化一个SQL的语句对象,建议在用到该对象的时候再去实例化 QSqlQuery query(userDb); //准备一条SQL的源语句,创建一个用户表 QString createTable = QString{"create table if not exists user(username varchar(20) primary key,passwd varchar(15));"}; //执行SQL语句对象 if(!query.exec(createTable)) { //创建用户表失败 qDebug() << "create user table error:" << query.lastError().text(); return; }
2 sqlite3知识
创建关系表:create create table "条件" 表名(列名1 数据类型 "约束",列名2 数据类型 "约束",...,列名3 数据类型 "约束"); 用双引号引来的部分表示可有可无
数据类型: 整数: integer(size) 整数,size用来表示数据最大值的位数 int(size) smallint(size) ... 浮点数: decimal(size,d) 十进制小数,size用来表示整数部分最大值的位数,d规定小数点后面的最大位数 float(size,d) double(size,d) real(size,d) ...
字符串: char(size) 定长的字符串,size用来指定国定长度 varchar(size) 可变字符串长度,size用来指定最大长度
约束: not null 数据不能为空 unique 数据唯一,不能重复 primary key 主键,主键就是 not null + unique 即 主键不能为空且不能重复 foreign key 外键,表示这个字段在其他的表中是主键,表与表之间的联系就是通过外键来连接的 check 检查数据的值是否满足条件(约束值的范围) 如: check(score >= 0 and score <= 100) 如果数据超过了这个范围,就不符合条件就不能设置这个值
条件: if not exists 如果表不存在,则创建,否则不创建
例子: QString createTable = QString{"create table if not exists user(username varchar(20) primary key,passwd varchar(15));"};
删除关系表:drop drop table 表名;
修改关系表名:alter alter table 表名 rename to 新名;
添加字段(列):alter alter table 表名 add 字段名 字段数据类型 "约束";
插入一行记录(数据):insert into insert into 表名(字段1,字段2,...,字段n) values(值1,值2,...,值n); 如: intser into user(name,passwd,number,score) values("zhangsan","666666",19,99.5); 往user表中插入一行数据,指定插入的列为name,passwd,number,score,指定插入的值为"zhangsan","666666",19,99.5
查找数据:select 查找所有的行 select * from 表名; //列举出表格中所有的信息
查找指定列的数据 select 字段1,字段2,...,字段n from 表名 where 列名 运算符 值; 运算符: = 等于 <> 不等于 > 大于 < 小于 between 值1 and 值2 值在值1和值2之间 and 并且 or 或者
修改一行数据:update update 表名 set 字段1=新值,字段2=新值,...; //将每一行的指定列的值都设置成指定的值
update 表名 set 字段1=新值,字段2=新值,... where 列名 运算符 值; //只有符合条件的行才修改数据
删除一行记录:delete delete from 表名 where 列名 运算符 值;
3 数据库的增删改查方法
方法一:
QSqlDatabase db; // 建立数据库连接 QSqlDatabase createConnection() { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("./database.db"); if (!db.open()) { qDebug() << "无法打开数据库!"; } return db; } // 创建表格 void createTable(QSqlDatabase db) { QSqlQuery query(db); QString createTable = "CREATE TABLE IF NOT EXISTS student (" "id INTEGER PRIMARY KEY AUTOINCREMENT," "name VARCHAR(20) NOT NULL," "age INTEGER NOT NULL)"; query.exec(createTable); } // 插入数据 void insertData(QSqlDatabase db, const QString& name, int age) { QSqlQuery query(db); query.prepare("INSERT INTO student (name, age) VALUES (:name, :age)"); query.bindValue(":name", name); query.bindValue(":age", age); query.exec(); } // 查询数据 void selectData(QSqlDatabase db) { QSqlQuery query(db); query.exec("SELECT * FROM student"); while (query.next()) { int id = query.value(0).toInt(); QString name = query.value(1).toString(); int age = query.value(2).toInt(); qDebug() << "ID:" << id << "Name:" << name << "Age:" << age; } } // 更新数据 void updateData(QSqlDatabase db, int id, int age) { QSqlQuery query(db); query.prepare("UPDATE student SET age = :age WHERE id = :id"); query.bindValue(":age", age); query.bindValue(":id", id); query.exec(); } // 删除数据 void deleteData(QSqlDatabase db, int id) { QSqlQuery query(db); query.prepare("DELETE FROM student WHERE id = :id"); query.bindValue(":id", id); query.exec(); }
方法二:
// 插入数据 void insertData(QSqlDatabase db, const QString& name, int age) { QSqlQuery query(db); query.prepare("INSERT INTO student (name, age) VALUES (?, ?)"); query.addBindValue(name); query.addBindValue(age); query.exec(); } // 更新数据 void updateData(QSqlDatabase db, int id, int age) { QSqlQuery query(db); query.prepare("UPDATE student SET age = ? WHERE id = ?"); query.addBindValue(age); query.addBindValue(id); query.exec(); } // 删除数据 void deleteData(QSqlDatabase db, int id) { QSqlQuery query(db); query.prepare("DELETE FROM student WHERE id = ?"); query.addBindValue(id); query.exec(); }