QT-子线程或自定义类操作访问主界面UI控件的几种方法
前言
QT創建窗體工程,一般在MainWindow或Dialog類里可以直接通過ui指針訪問控件,但是添加新的類后又如何訪問呢,可以通過以下幾種方式:
1.將ui指針公開后直接訪問
(1)例如有個自己定義的類CustomClass,在自定義類里包含主界面指針MainWindow *
class MainWindow;
?
class CustomClass
{
public:
? ? CustomClass(MainWindow * parent);
? ? MainWindow * mainwidow;
? ?void SetUI();
};
(2)主界面類將成員Ui::MainWindow *ui 從私有private移動到public公共
class MainWindow : public QMainWindow
{
? ? Q_OBJECT
? ??
public:
? ? MainWindow(QWidget *parent = nullptr);
? ? ~MainWindow();
? ? Ui::MainWindow *ui;
? ? CustomClass* customclass;
private: ??
}
(3)自定義類包含頭文件:#include "ui_mainwindow.h",構造的時候傳入界面指針MainWindow*,就能通過 mainwidow->ui指針訪問UI控件了。
#include "mainwindow.h"
#include "ui_mainwindow.h"
?
CustomClass::CustomClass(MainWindow * parent)
{
? this->mainwidow = parent;
}
?
void CustomClass::SetUI()
{
? ? mainwidow->ui->pushButton->setText("開始");
}
記得要引用ui_mainwindow.h,不然會報錯誤:
error: member access into incomplete type 'Ui::MainWindow'
forward declaration of 'Ui::MainWindow'
?
2.封裝成公共函數
(1)所有對UI的操作都在主界面MainWindow類中,并封裝成公共的函數
class MainWindow : public QMainWindow
{
? ? Q_OBJECT
? ??
public:
? ? MainWindow(QWidget *parent = nullptr);
? ? ~MainWindow();
? ? ?void SetUI();
? ? CustomClass* customclass;
private: ??
? ? ? ? Ui::MainWindow *ui;
}
?
void MainWindow::SetUI()
{
? ? this->ui->pushButton->setText("開始");
}
(2)其他類要訪問UI調用函數就好了
CustomClass::CustomClass(MainWindow * parent)
{
? this->mainwidow = parent;
? this->mainwidow->SetUI();
}
3.通過控件指針訪問
如果每次只訪問一兩個控件的話,也可以直接將控件指針傳給自定義類
? ? customclass=new CustomClass(this);
? ? customclass->SetUI(ui->pushButton);
void CustomClass::SetUI(QPushButton* btn)
{
? ? btn->setText("開始");
}
4.通過信號和槽訪問
前面的方法一般夠用了,但如果是多線程就必須用到信號和槽機制,因為非UI線程不能跨線程訪問UI,例如定義一個線程類
class MyThread :public QThread
{
? ? Q_OBJECT
public:
? ? MyThread(MainWindow *parent);
? ? MainWindow * mainwidow;
? ? void run() override;
};
在主界面MainWindow類里有信號setui,和槽函數SetUI,所有對 UI的操作都封裝在槽函數函數中
MainWindow::MainWindow(QWidget *parent)
? ? : QMainWindow(parent)
? ? , ui(new Ui::MainWindow)
{
? ? ui->setupUi(this);
? ? //關聯信號
? ? ?connect(this,&MainWindow::setui,this,&MainWindow::SetUI);
? ? ?mythread = new MyThread(this);
? ? ?mythread->start();//啟動線程
}
?
void MainWindow::SetUI()
{
? ? this->ui->pushButton->setText("開始");
}
在非UI線程里需要訪問Ui通過發送信號就行了,槽函數會在UI線程中被執行
void MyThread::run()
{
? ? //發送信號,修改UI
? ? emit this->mainwidow->SetUI();
? ? exec();
}
當然信號和槽很靈活,不一定在多線程中,有需要都可以用。
/****************************************
在子線程里控制主界面的UI控件有兩種方法:第一種是在子線程中發送信號,然后在主線程中去更新;第二種方法是在子線程中創建同樣的對象,然后把主界面中控件的指針賦給創建的對象。
第一種方法在此不做實例展示,在此通過一個簡單的例子展示第二種方法:
下面是主界面的初始轉態:
?
下面這個是繼承自QThread類的子線程類
sonthread.h
#ifndef SONTHREAD_H
#define SONTHREAD_H
#include <QLabel>
#include <QThread>
#include <QDebug>
class sonThread : public QThread
{
? ? Q_OBJECT
public:
? ? explicit sonThread(QObject *parent = nullptr);
? ? void run();
public:
? ? QLabel *label;
};
#endif // SONTHREAD_H
sonthread.cpp
#include "sonthread.h"
sonThread::sonThread(QObject *parent) : QThread(parent)
{
? ? label = new QLabel;
}
void sonThread::run()
{
? ? qDebug()<<"run()"<<QThread::currentThreadId();
? ??
? ? label->setText("更新");
}
下面是主線程類
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QThread>
#include "sonthread.h"
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
? ? Q_OBJECT
public:
? ? explicit Dialog(QWidget *parent = 0);
? ? ~Dialog();
private:
? ? Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
? ? QDialog(parent),
? ? ui(new Ui::Dialog)
{
? ? ui->setupUi(this);
? ? sonThread *sonthread = new sonThread; ?//創建子線程對象
? ? sonthread->label=ui->label; ?//將主界面UI指針賦給子線程中的指針對象
? ? sonthread->start(); ?//啟動子線程
? ? qDebug()<<"Dialog()"<<QThread::currentThreadId();
}
Dialog::~Dialog()
{
? ? delete ui;
}
下面是運行結果:
?
可以看出run()函數與主線程不在同一個線程,而我只在run()中有修改過label的字符,所以實現了在子線程中操作主界面UI控件的目的。
?
總結
以上是生活随笔為你收集整理的QT-子线程或自定义类操作访问主界面UI控件的几种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QT c++ 中使用PostMessag
- 下一篇: @Deprecated 注解 (@Doc