qt 滚动条 美化

阅读 20

2024-11-06

1024程序员快乐,如果这博客让你学习到了知识,请给我一个免费的赞❤️

父子线程演示

一、创建界面文件

LCDnumber

二、创建mythread类,继承QObject

三、在MyThread.h文件做修改,并且加上函数声明

引入头文件,改变继承

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);

protected:
    void run(); // 入口函数 -- 需要start()启动

signals:
    void sigDone();

public slots:
};

#endif // MYTHREAD_H

四、实现run方法

#include "mythread.h"

MyThread::MyThread(QObject *parent) : QThread(parent)
{

}

void MyThread::run()
{
    // 模拟复杂的操作
    sleep(5); //休眠5s
    emit sigDone();
}

五、使用计时器来控制LCDnumber

//计时器
    mytimer = new QTimer(this);
    myt = new MyThread(this);

    connect(mytimer, &QTimer::timeout, this, [=](){
        static int num = 0;
        ui->lcdNumber->display(num++);
    });

六、实现按钮的槽函数

void MyWidget::on_begin_clicked()
{
    //如果计时器开着
    if(mytimer->isActive() == true)
    {
        return;
    }
    // 启动定时器
    mytimer->start(1000); // ms

    // 启动子线程
    myt->start();
}

子线程运行结束后,停止计数器

完整代码

mythread.cpp

#include "mythread.h"

MyThread::MyThread(QObject *parent) : QThread(parent)
{

}

void MyThread::run()
{
    // 模拟复杂的操作
    sleep(5); //休眠5s
    emit sigDone();
}

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);

protected:
    void run(); // 入口函数 -- 需要start()启动

signals:
    void sigDone();

public slots:
};

#endif // MYTHREAD_H

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>
#include <QDebug>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    //计时器
    mytimer = new QTimer(this);
    myt = new MyThread(this);

    connect(mytimer, &QTimer::timeout, this, [=](){
        static int num = 0;
        ui->lcdNumber->display(num++);
    });

    // 子线程信号,子线程运行结束停止计数器
    connect(myt, &MyThread::finished, mytimer, &QTimer::stop);

}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::on_begin_clicked()
{
    //如果计时器开着
    if(mytimer->isActive() == true)
    {
        return;
    }
    // 启动定时器
    mytimer->start(1000); // ms

    // 启动子线程
    myt->start();
}

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <QTimer>
#include "mythread.h"

namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

private slots:
    void on_begin_clicked();

private:
    Ui::MyWidget *ui;

    QTimer* mytimer;
    MyThread *myt;
};

#endif // MYWIDGET_H

多线程演示

一、创建界面文件

LCDnumber

二、创建子线程Mywork类,继承QObject

三、在mywork.h文件加上函数声明,成员变量

#ifndef MYWORK_H
#define MYWORK_H

#include <QObject>

class MyWork : public QObject
{
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = 0);

    // 业务处理函数
    void doMyWork();

    void setFlag(bool bl);

signals:
public slots:
    
private:
    bool isStop;
};

#endif // MYWORK_H

四、父线程mywidget.h实现

引入头文件(包括子线程的头文件)、信号函数、槽函数

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QThread>
#include <QTimer>
#include <QWidget>
#include "mywork.h"

namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

signals:
    // 发信号, 让子线程工作
    void sigWorking();
    
public slots:
    // 开始按钮
    void slotStart();
    // 关闭按钮
    void slotStop();
    // 定时器
    void slotTimeout();
    // 关闭线程
    void slotCloseThread();

private:
    Ui::MyWidget *ui;

    QTimer *mytimer;
    MyWork *work;
    QThread *pthread; //子线程
};

#endif // MYWIDGET_H

五、实现子线程mywork.cpp

比较简单、模拟线程处理作业

#include "mywork.h"
#include <QThread>
#include <QMessageBox>
#include <QDebug>

MyWork::MyWork(QObject *parent) : QObject(parent)
{
    isStop = false;
}

void MyWork::doMyWork()
{
    while(!isStop)
    {
        // 操作
        QThread::sleep(1);  // 当前线程处理操作用了1s
        // 每执行一次循环发一次信号
        qDebug() << QThread::currentThread() << "sub thread";
        // QMessageBox::aboutQt(NULL);
    }
}

void MyWork::setFlag(bool bl)
{
    isStop = bl;
}

六、实现mywidget.cpp

        多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口

不建议在析构函数中进行与线程相关的操作。析构函数通常用于以下几种情况:

  1. 使用 new 分配的内存需要使用 delete 释放动态分配的资源。
  2. 关闭文件或网络连接
  3. 断开信号和槽连接
  4. 日志记录与打印

    /* 多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口
    */
    mytimer  = new QTimer(this);
    // 1. 业务对象
    work = new MyWork();
    // 2. 子线程类
    pthread = new QThread(this);
    // 3. 移动业务对象到子线程
    work->moveToThread(pthread);
    // 5. 子线程工作
    connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);

    connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);
    connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);
    // 定时器
    connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);

    // 窗口析构的时候干掉线程
    connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);

    qDebug() << QThread::currentThread() << "main thread";


void MyWidget::slotStart()
{
    if(mytimer->isActive() == true)
    {
        return;
    }
    if(pthread->isRunning())
    {
        return;
    }
    mytimer->start(500);
    // 4. 启动子线程
    pthread->start();

    // 发信号, 让子线程工作
    emit sigWorking();
}

void MyWidget::slotStop()
{
    if(mytimer->isActive() == false)
    {
        return;
    }
    mytimer->stop();
    // 停止子线程
    pthread->quit();
    work->setFlag(true);
}

void MyWidget::slotTimeout()
{
    static int num = 0;
    ui->lcdNumber->display(num++);
}
// 窗口析构的时候干掉线程
void MyWidget::slotCloseThread()
{
    work->setFlag(true);

    pthread->quit();
    pthread->wait();    // 等待线程手头上的工作处理完成
}

完整代码

mywork.cpp

#include "mywork.h"
#include <QThread>
#include <QMessageBox>
#include <QDebug>

MyWork::MyWork(QObject *parent) : QObject(parent)
{
    isStop = false;
}

void MyWork::doMyWork()
{
    while(!isStop)
    {
        // 操作
        QThread::sleep(1);  // 当前线程处理操作用了1s
        // 每执行一次循环发一次信号
        qDebug() << QThread::currentThread() << "sub thread";
        // QMessageBox::aboutQt(NULL);
    }
}

void MyWork::setFlag(bool bl)
{
    isStop = bl;
}

mywork.h

#ifndef MYWORK_H
#define MYWORK_H

#include <QObject>

class MyWork : public QObject
{
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = 0);

    // 业务处理函数
    void doMyWork();

    void setFlag(bool bl);

signals:
public slots:

private:
    bool isStop;
};

#endif // MYWORK_H

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QThread>
#include <QTimer>
#include <QWidget>
#include "mywork.h"

namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

signals:
    // 发信号, 让子线程工作
    void sigWorking();

public slots:
    // 开始按钮
    void slotStart();
    // 关闭按钮
    void slotStop();
    // 定时器
    void slotTimeout();
    // 关闭线程
    void slotCloseThread();

private:
    Ui::MyWidget *ui;

    QTimer *mytimer;
    MyWork *work;
    QThread *pthread; //子线程
};

#endif // MYWIDGET_H

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
  ,ui(new Ui::MyWidget)
{
    ui->setupUi(this);

    /* 多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口
    */
    mytimer  = new QTimer(this);
    // 1. 业务对象
    work = new MyWork();
    // 2. 子线程类
    pthread = new QThread(this);
    // 3. 移动业务对象到子线程
    work->moveToThread(pthread);
    // 5. 子线程工作
    connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);


    connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);
    connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);
    // 定时器
    connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);

    // 窗口析构的时候干掉线程
    connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);

    qDebug() << QThread::currentThread() << "main thread";

    /* connect 的第 5 参数
     * 1. 自动连接 -- 默认
     *      多线程 -- 指定队列连接
     *      单线程 -- 指定直接连接
     * 2. 队列连接 -- 多线程
     *      槽函数在信号接受者(receiver)所在的线程中执行
     * 3. 直接连接 -- 单线程
     *      信号和槽函数在同一个线程中执行
     */
}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::slotStart()
{
    if(mytimer->isActive() == true)
    {
        return;
    }
    if(pthread->isRunning())
    {
        return;
    }
    mytimer->start(500);
    // 4. 启动子线程
    pthread->start();

    // 发信号, 让子线程工作
    emit sigWorking();
}

void MyWidget::slotStop()
{
    if(mytimer->isActive() == false)
    {
        return;
    }
    mytimer->stop();
    // 停止子线程
    pthread->quit();
    work->setFlag(true);
}

void MyWidget::slotTimeout()
{
    static int num = 0;
    ui->lcdNumber->display(num++);
}
// 窗口析构的时候干掉线程
void MyWidget::slotCloseThread()
{
    work->setFlag(true);

    pthread->quit();
    pthread->wait();    // 等待线程手头上的工作处理完成
}

精彩评论(0)

0 0 举报