• 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 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

    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 
      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 
    ​
    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 
    #include 
    ​
    // 创建线程
    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 
    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(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()<
    if(str4.contains(re))
        qDebug()< 
    

    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
    ​
    //延时功能
    void sleep(unsigned int msec){
    //currnentTime 返回当前时间 用当前时间加上我们要延时的时间msec得到一个新的时刻
        QTime reachTime = QTime::currentTime().addMSecs(msec);
        //用while循环不断比对当前时间与我们设定的时间
        while(QTime::currentTime() 
    
    #include
    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
    ​
    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 
    #include 
    ​
    QString picPath=QFileDialog::getOpenFileName(this,"选择图片文件","*.bmp *.png *.jpg *.jpeg");
    qDebug()< 
    

    4.3 解决标签字体显示不完全问题

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    在这里插入图片描述

    ###

    二、QT数据库

    1 数据库创建的基本步骤

    数据库头文件:

    #include #include #include

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

  • 相关阅读:
    应用配置管理,基础原理分析
    【买入看跌期权策略(Long Put)】
    小黑子—MyBatis:第一章
    【刷题篇】贪心算法(一)
    小程序的多种特性
    多线程Thread(初阶一:认识线程)
    【Visual Leak Detector】库的 22 个 API 使用说明
    Python学习之:如何将环境的安装嵌入到 python代码中
    基于bp神经网络汽车自动变速器最佳挡位判断(Matlab代码实现)
    Go语言hash/fnv应用实战:技巧、示例与最佳实践
  • 原文地址:https://blog.csdn.net/m0_61973119/article/details/139407830