QT-子线程或自定义类操作访问主界面UI控件的几种方法

2023-11-17

前言
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控件的目的。
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT-子线程或自定义类操作访问主界面UI控件的几种方法 的相关文章

随机推荐

  • Palindrome subsequence【区间DP+冗斥】

    题目链接HDU 4632 题目让我们求给定的一段字符串上回文串的长度 一个数也算是回文串 于是我就想怎样去找其中的规律 我举了些例子 先是从相同的字符串开始举例 aaa 对于aaa dp 1 1 1 dp 2 2 1 dp 1 2 dp 1
  • 遥感+python 目录

    遥感 python 1 遥感影像预处理 环境搭建 辐射定标 大气校正 RPC校正 重投影 2 遥感影像样本读取 CSV 格式样本读取 XLS 格式样本读取 TIFF 格式样本读取 SHAPE 格式样本读取 3 遥感影像分类器构建 KNN分类
  • Linux——进程信号的发送

    目录 一 信号发送的概念 首先来讲几个发送术语 它有三种情况 注意 二 信号在内核中的表示示意图 三 信号捕捉 所以总结一下 此时 会出现这样一个疑问 操作系统是如何得知现在被执行的进程是用户态还是内核态 问题2 CPU在执行某个进程时是如
  • Node.js 应用:Koa2 使用 JWT 进行鉴权

    前言 在前后端分离的开发中 通过 Restful API 进行数据交互时 如果没有对 API 进行保护 那么别人就可以很容易地获取并调用这些 API 进行操作 那么服务器端要如何进行鉴权呢 Json Web Token 简称为 JWT 它定
  • React全部api解读

    很多同学用react开发的时候 真正用到的React的api少之又少 基本停留在Component React memo等层面 实际react源码中 暴露出来的方法并不少 只是我们平时很少用 但是React暴露出这么多api并非没有用 想要
  • pip(Python包管理工具)安装第三方库教程

    目录 1 python环境检查 2 pip库的常用命令 2 1 更新包 2 1 1 更新pip工具 2 1 2 更新三方库 2 2 安装包 2 2 1 在线安装 2 2 1 1 直接安装 2 2 1 2 镜像安装 2 2 2 离线安装 2
  • 机器学习概述和数据预处理

    概述 机器学习定义 机器学习是一门能够让编程计算机从数据中学习的计算机科学 一个计算机程序在完成任务T之后 获得经验E 其表现效果为P 如果任务T的性能表现 也就是用来衡量的P 随着E增加而增加 那么这样计算机程序就被称为机器学习系统 自我
  • Vue 2项目如何升级到Vue 3?

    应不应该从 Vue 2 升级到 Vue 3 应不应该升级 这个问题不能一概而论 首先 如果你要开启一个新项目 那直接使用 Vue 3 是最佳选择 后面课程里 我也会带你使用 Vue 3 的新特性和新语法开发一个项目 以前我独立使用 Vue
  • Linux磁盘管理命令

    Linux磁盘管理命令 Linux磁盘管理命令 1 pwd命令 2 cd命令 3 df命令 4 mkdir命令 5 mount及umount命令 6 ls命令 7 history命令 Linux磁盘管理命令 1 pwd命令 作用 显示当前工
  • ubuntu18.04安装Azure Kinect传感器摄像头教程

    官方教程 Azure Kinect DK文档 配置存储库 可以通过安装适用于 Linux 分发版和版本的 Linux 包自动配置存储库 此包将安装存储库配置以及工具 如 apt yum zypper 使用的 GPG 公钥来验证已签名的包和
  • 基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了

    目录 目的 编写一个可以稳定连接到局域网的STM32网络通信程序 硬件和软件 具体步骤 1 利用STM32CubeMX建立Keil工程文件 2 在keil中修改代码和配置工程 3 代码烧录 功能验证 目的 编写一个可以稳定连接到局域网的ST
  • 关于xpath的安装

    1 xpath简介 使用xpath需要安装模块 pip install lxml 导入模块 from lxml import etree xpath是用来载xml中查找指定的元素 它是一种路径表达式 详细内容可在文档中查找 https de
  • linux中软链接的使用方法

    在 Linux 中的连结有两种 一种是类似 Windows 的快捷方式功能的档案 可以让你快速的链接到目标档案 或目彔 另一种则是透过文件系统的 inode 连结来产生新的文档名 而不是产生新档案 这种称为实体链接 hard link Ha
  • C++ std::Thread多线程和mutex锁通俗易懂

    记录学习过程 如有新的发现 随时补充 如有错误或补充 请各位大佬指正 一 前言 多线程有多种方式 std Thread boost Thread pthread Windows库等 本文只关注std Thread 可以跨平台运行 二 std
  • 已解决-NVIDIA安装程序失败-win10

    这个错误界面没截图 去别的地方盗过来一个 我的电脑显示cuda版本是11 0的 所以一直努力装11 0版本的 新电脑刚开始装的前几次还没问题 卸的次数多了报应就来了 一直报错 整的都快崩溃了 现在解决了 我装的是10 0版本的 把方法贴出来
  • 使用Docker伪分布式安装hadoop

    1 安装Docker Desktop 官网地址 2 下载linux内核更新包 安装好Docker重启之后 会自动提示安装它 官网地址 3 重启计算机后打开docker desktop 4 win r 打开 cmd窗口 5 拉取镜像 dock
  • 在linux服务器上进行VTM的cmake并进行编解码

    前不多言 直接进入主题 一 上传VTM源码至linux服务器端 源码压缩包可以去这个网站进行下载 二 上传后使用linux操作命令解压 unzip xxx zip 三 解压后进行cmake操作 输入命令行进行操作 第一步 进入至解压后的vt
  • git操作总结

    git操作总结 一 配置Git 1 配置用户信息 安装git后 第一件事是配置用户名和邮件地址 记录是谁对文件进行了修改 global命令运行一次 永久生效 git config global user name git config gl
  • pandas DataFrame.to_sql() 用法

    to sql 的语法如下 https pandas pydata org pandas docs stable reference api pandas DataFrame to sql html DataFrame to sql name
  • QT-子线程或自定义类操作访问主界面UI控件的几种方法

    前言 QT创建窗体工程 一般在MainWindow或Dialog类里可以直接通过ui指针访问控件 但是添加新的类后又如何访问呢 可以通过以下几种方式 1 将ui指针公开后直接访问 1 例如有个自己定义的类CustomClass 在自定义类里