前言
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();
}
當然信號和槽很靈活,不一定在多線程中,有需要都可以用。