QT入门知识回顾

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);
    

声明槽函数注意点:

  1. 如果是自己的定义的槽函数,建议不要以 on_ 开头,因为以 "on_" 开头,Qt会认为这个是它自动生成的槽函数,在它自己声明的参函数列表中又找不到这个声明,那么就会报警告!

  2. 槽函数一旦声明了,就一定要实现!!!否则就会报错!

信号与槽的连接方式: 信号与槽有两种连接方式:自动连接、手动接连

信号与槽的连接方式: 信号与槽有两种连接方式:自动连接、手动连接

自动连接:在UI设计器中,右键选择对象,选择转到槽,然后选择对应的信号, 那么就会在类中自动添加一个槽函数的声明以及在源文件(.cpp)文件中自动添加一个槽函数的定义,这个槽函数会自动和对应的信号连接

手动连接:手动调用connect函数来完成对应的信号与槽函数的连接

1.4 QT图片类型

QT图片的类型有4种,QPixmap,QImage,QBitmap,QPicture

QPixmap:

  1. 在加载图片的时候,是将图片加载到显存里面,如果图片太大可能会加载失败

  2. 在显示图片的时候,可以在不修改图片数据的前提下对图片进行缩放或者放大显示

  3. 在不同的系统下,显示图片的效果可能会不相同

  4. label->setPixmap(QPixmap(filename));

QImage:

  1. 在加载图片的时候,是将图片加载到内存中

  2. 在显示图片的时候,以原图显示

  3. 在不同的系统下,显示图片的效果是相同的

    显示图片:
        //直接使用文件的路径
        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 redpx color边框宽度以及颜色
border-color: rgba(255, 225, 255, 30);color边框颜色
font-family微软雅黑设定字体所属家族
font: bold 14pxbold 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 方法一

img

img

样式表常见设置

//加上#对象,则里面属性设置只针对于该对象
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>

  1. 先实例化一个Qt文件对象:

    QFile file;
    QFile file{文件路径名};
  2. 打开文件:

    file.open(文件打开标志);
    文件打开标志:
    QIODevice::NotOpen
    QIODevice::ReadOnly
    QIODevice::WriteOnly
    QIODevice::ReadWrite
    QIODevice::Append
    QIODevice::Truncate
    QIODevice::Text
  3. 读取数据:

    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)
  4. 写入数据:

    file.write();
    ​
    qint64 write(const char *data, qint64 maxSize)
    qint64 write(const char *data)
    qint64 write(const QByteArray &byteArray)
  5. 关闭文件:

     file.close();
  6. 案例介绍

    #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;
}

常见信号

  1. clicked() 点击

  2. pressed() 按下

  3. 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 控件

  1. 添加页面

    img

  1. 页面切换插入第三页

    img

  2. 代码跳转页面

    切记: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();

image-20230613103831783

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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/676128.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TH方程学习 (6)

一、内容介绍 本节旨在使用优化算法的方法&#xff0c;旨在利用最小的燃耗实现目标的交会&#xff0c;变量为目标的转移时间。整个问题描述为&#xff1a; 本节拟采取粒子群优化的算法&#xff0c;matlab中自带的粒子群函数为particleswarm&#xff0c;其用法不详细介绍&#…

LeetCode:环形链表II

文章收录于LeetCode专栏 LeetCode地址 环形链表II 题目 给定一个链表&#xff0c;返回链表开始入环的第一个节点。如果链表无环&#xff0c;则返回null。   为了表示给定链表中的环&#xff0c;我们使用整数pos来表示链表尾连接到链表中的位置&#xff08;索引从0开始&#…

C++青少年简明教程:数组

C青少年简明教程&#xff1a;数组 C数组是一种存储固定大小连续元素的数据结构。数组中的每个元素都有一个索引&#xff0c;通过索引可以访问或修改数组中的元素。 在C中&#xff0c;数组中的元素数据类型必须一致。数组是一个连续的内存区域&#xff0c;用于存储相同类型的元…

std::shared_ptr,reset()函数

感慨&#xff1a;不深入阅读源代码&#xff0c;真的心虚&#xff0c;也用不好。 上代码&#xff1a; class A01 { public://std::weak_ptr<B0> b_ptr;int data{ 1234 };~A01() {std::cout << "A01 deleted\n";}void Print() { std::cout << &quo…

C++进阶:C++11

C11简介 在 2003 年 C 标准委员会曾经提交了一份技术勘误表 ( 简称 TC1) &#xff0c;使得 C03 这个名字已经取代了 C98 称为 C11 之前的最新 C 标准名称。不过由于 C03(TC1) 主要是对 C98 标准中的漏洞 进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习…

初始操作系统

概念&#xff1a; 1.系统资源的管理者&#xff1a;实质控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机地工作和资源的分配 2.向上层提供方便易用的服务&#xff1a;以提供给用户和其他软件方便接口和环境 封装思想&#xff1a;操作系统把一些丑…

小熊家务帮day10- 门户管理

门户管理 1 门户介绍1.1 介绍1.2 常用技术方案 2 缓存技术方案2.1 需求分析2.1.1 C端用户界面原型2.1.2 缓存需求2.1.3 使用的工具 2.2 项目基础使用2.2.1 项目集成SpringCache2.2.2 测试Cacheable需求Service测试 2.1.3 缓存管理器&#xff08;设置过期时间&#xff09;2.1.4 …

React@16.x(17)Portals

目录 1&#xff0c;使用2&#xff0c;事件冒泡 一句话总结&#xff1a;和 Vue3 的 Teleport 一个效果。 1&#xff0c;使用 import React, { PureComponent } from "react"; import ReactDOM from "react-dom";// 返回一个 React 元素&#xff08;ReactNo…

【Go语言精进之路】构建高效Go程序:零值可用、使用复合字面值作为初值构造器

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、深入理解并利用零值提升代码质量1.1 深入Go类型零值原理1.2 零值可用性的实践与优势1.2.1 切片(Slice)的零值与动态扩展1.2.2 Map的零值与安全访问1.2.3 函数参数与零值 二、使用复合字面值作为初值构造器2.1 结构体…

十分钟快速搭建检索、排序的大模型RAG系统

以上为实现效果 RAG是目前最火的大模型应用之一&#xff0c;如何能快速实现一个不错的demo呢&#xff1f; 参考 https://github.com/LongxingTan/open-retrievalshttps://colab.research.google.com/drive/1fJC-8er-a4NRkdJkwWr4On7lGt9rAO4P?uspsharing#scrollTo2Hrfp96UY…

【算法】一文搞懂归并排序

概念 归并排序利用了分治思想&#xff0c;将待排序的数组范围层层划分&#xff0c;每次划分会得到两个大小相近的区间。当无法划分时&#xff0c;递归结束&#xff0c;自下而上进行区间合并merge操作&#xff0c;合并操作依次比较两个区间的元素&#xff0c;进而使合并后的区间…

开发和渗透偷懒利器utools

目录 1.前言 1.1 工具简介 1.2 核心特性 1.3 使用场景 1.4 安装与使用 1.4.1 下载&#xff1a; 1.4.2 安装&#xff1a; 1.4.3 配置&#xff1a; 1.4.4 插件市场&#xff1a; 2.懒狗插件介绍 基本介绍 2.1 数据模拟 2.2 随机生成虚假数据 2.3 API市场 2.4 Hoppscot…

学习小心意——简单的循坏语句

for循坏 基本语法格式 for 变量 in 序列:代码块 示例代码如下 for i in range(10):print(i)#输出结果:0 1 2 3 4 5 6 7 8 9 简单案例代码如下 利用for语句遍历序列 # 遍历字符串打印每个字母 for letter in "python":print(letter)# 遍历列表并打印每个元素 a …

Spring Boot API 编写的十个最佳实践,你知道几个?

一个好的 API 不仅能提高开发效率&#xff0c;还能确保系统的安全性和稳定性。 第一部分&#xff1a;RESTful API 设计 资源名称&#xff1a;使用名词表示资源&#xff0c;比如 /users。 HTTP 方法&#xff1a;GET、POST、PUT、DELETE 分别对应查询、创建、更新和删除操作。 …

SaaS 电商设计 (十一) 那些高并发电商系统的限流方案设计

目录 一.什么是限流二.怎么做限流呢2.1 有哪些常见的系统限流算法2.1.1 固定窗口2.1.1 滑动窗口2.1.2 令牌桶2.1.3 漏桶算法 2.2 常见的限流方式2.2.1 单机限流&集群限流2.2.2 前置限流&后置限流 2.3 实际落地是怎么做的2.3.1 流量链路2.3.2 各链路限流2.3.2.1 网关层2…

【Java面试】七、SpringMvc的执行流程、SpringBoot自动装配原理

文章目录 1、SpringMVC的执行流程1.1 视图阶段1.2 前后端分离阶段 2、SpringBoot自动配置原理3、框架常用的注解3.1 Spring的注解3.2 SpringMvc的注解3.3 SpringBoot的注解 4、面试 1、SpringMVC的执行流程 1.1 视图阶段 旧项目中&#xff0c;未前后端分离时&#xff0c;用到…

计算机视觉与模式识别实验2-2 SIFT特征提取与匹配

文章目录 &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1;SIFT算法原理总结&#xff1a;实现SIFT特征检测和匹配通过RANSAC 实现图片拼接更换其他图片再次测试效果&#xff08;依次进行SIFT特征提取、RANSAC 拼接&#xff09; &#x1f9e1;&#x1f9e1;全部代…

(CVPRW,2024)可学习的提示:遥感领域小样本语义分割

文章目录 相关资料摘要引言方法训练基础类别新类别推理 相关资料 论文&#xff1a;Learnable Prompt for Few-Shot Semantic Segmentation in Remote Sensing Domain 代码&#xff1a;https://github.com/SteveImmanuel/OEM-Few-Shot-Learnable-Prompt 摘要 小样本分割是一项…

JMeter性能测试实现与分析分享

JMeter是由著名开源软件巨头Apache组织开发的纯Java的压力测试工具&#xff0c;它即能测试动态服务&#xff08;WebService&#xff09;&#xff0c;也能测试静态资源&#xff0c;包括Servlet服务、CGI脚本等&#xff0c;还能测试动态语言服务&#xff08;PHP、Java、ASP.NET等…

外汇天眼:总是权衡利弊,投资注定失败

投资股票的人往往会频繁地评估自己的投资结果&#xff0c;尤其是在信息时代&#xff0c;手机上随时可以查看股票行情&#xff0c;导致很多人时不时地打开行情软件&#xff0c;看一看自己的股票是涨了还是跌了&#xff0c;盈利了还是亏损了。 频繁评估结果的弊端 一、引发急躁…