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

當然信號和槽很靈活,不一定在多線程中,有需要都可以用。

發佈了25 篇原創文章 · 獲贊 48 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章