前言
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_OBJECTpublic: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_OBJECTpublic: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_OBJECTpublic: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(){//发送信号,修改UIemit this->mainwidow->SetUI();exec();}
当然信号和槽很灵活,不一定在多线程中,有需要都可以用。