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

   前言        

        QT创建窗体工程,一般在MainWindow或Dialog类里可以直接通过ui指针访问控件,但是添加新的类后又如何访问呢,可以通过以下几种方式:

将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'

封装成公共函数

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


通过控件指针访问


如果每次只访问一两个控件的话,也可以直接将控件指针传给自定义类customclass=new CustomClass(this);
    customclass->SetUI(ui->pushButton);
void CustomClass::SetUI(QPushButton* btn)
{
    btn->setText("开始");
}

通过信号和槽访问


前面的方法一般够用了,但如果是多线程就必须用到信号和槽机制,因为非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控件的目的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/78965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Redis】深入探索 Redis 的数据类型 —— 列表 List

文章目录 一、List 类型介绍二、List 类型相关命令2.1 LPUSH 和 RPUSH、LPUSHX 和 RPUSHX2.2 LPOP 和 RPOP、BLPOP 和 BRPOP2.3 LRANGE、LINDEX、LINSERT、LLEN2.4 列表相关命令总结 三、List 类型内部编码3.1 压缩列表&#xff08;ziplist&#xff09;3.2 链表&#xff08;lin…

《向量数据库指南》——Milvus Cloud云原生分布式向量数据库的优势有哪些?

首先解释一下什么是分布式,什么是云原生。分布式的概念相对容易理解,就是系统的各个组件在不同的节点上进行协作和分工,以实现更大规模和更高性能的处理。而云原生并不仅仅指运行在 Kubernetes(K8s)上或在公有云上的服务。在我的理解中,分布式云原生意味着系统首先是一个…

【Java 基础篇】Java可变参数:灵活处理不定数量的方法参数

在Java编程中&#xff0c;可变参数是一项强大的功能&#xff0c;它允许你编写更加灵活的方法&#xff0c;接受不定数量的参数。本文将详细解释Java可变参数的用法、语法以及最佳实践。 什么是可变参数&#xff1f; 可变参数是Java 5引入的一项功能&#xff0c;它允许你在方法…

汇总selenium利用xpath等找网页节点的方法

一、通过子节点定位父节点&#xff0c;模拟建立一个test.html <!--子节点定位父节点--> <html> <body> <div id"A"><div>定位到这里1<div>定位到这里2<div>定位到这里3<div id"C">子节点</div><…

贝叶斯分位数回归、lasso和自适应lasso贝叶斯分位数回归分析免疫球蛋白、前列腺癌数据...

原文链接&#xff1a;http://tecdat.cn/?p22702 贝叶斯回归分位数在最近的文献中受到广泛关注&#xff0c;本文实现了贝叶斯系数估计和回归分位数&#xff08;RQ&#xff09;中的变量选择&#xff0c;带有lasso和自适应lasso惩罚的贝叶斯&#xff08;点击文末“阅读原文”获取…

vue基础知识十:Vue中组件和插件有什么区别?

一、组件是什么 回顾以前对组件的定义&#xff1a; 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式&#xff0c;在Vue中每一个.vue文件都可以视为一个组件 组件的优势 降低整个系统的耦合度&#xff0c;在保持接口不…

【洛谷 P1364】医院设置 题解(图论+深度优先搜索)

医院设置 题目描述 设有一棵二叉树&#xff0c;如图&#xff1a; 其中&#xff0c;圈中的数字表示结点中居民的人口。圈边上数字表示结点编号&#xff0c;现在要求在某个结点上建立一个医院&#xff0c;使所有居民所走的路程之和为最小&#xff0c;同时约定&#xff0c;相邻接…

C#,数值计算——64位哈希表的计算方法与实现代码

1 文本格式 using System; namespace Legalsoft.Truffer { public class HashAll { public HashAll() { } /// <summary> /// Pseudo-DES hashing of the 64-bit word(lword, rword). Both 32-bit arguments /// are …

GDB之调试系统接口syscall(九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

JavaScript 知识扫盲

JavaScript 知识扫盲 写在前面一、JavaScript 写入形式二、常用输入输出三、JS 是动态类型语言四、运算符五、数组1、数组创建2、获取和修改数组元素3、新增元素4、删除元素 六、函数七、对象1、对象的创建2、属性方法的使用 八、JavaScript 和 Java 对比九、事件1、常见事件2、…

Kubernetes(k8s)上搭建nacos集群

Kubernetes上搭建nacos集群 环境准备Kubernetes准备数据库准备 部署nacos集群官方镜像地址创建configmap创建部署文件根据yaml资源清单文件部署nacos 环境准备 Kubernetes准备 你需要准备一个Kubernetes集群&#xff0c;如图我的集群已经准备完毕&#xff1a; 数据库准备 …

【蓝桥杯选拔赛真题60】Scratch旋转风车 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析

目录 scratch旋转风车 一、题目要求 编程实现 二、案例分析 1、角色分析

【脑机接口论文与代码】 基于自适应FBCCA的脑机接口控制机械臂

Brain-Controlled Robotic Arm Based on Adaptive FBCCA 基于自适应FBCCA的脑机接口控制机械臂论文下载&#xff1a;算法程序下载&#xff1a;摘要1 项目介绍2 方法2.1CCA算法2.2FBCCA 算法2.3自适应FBCCA算法 3数据获取4结果4.1脑地形图4.2频谱图4.3准确率 5结论 基于自适应FB…

Spring底层的核心原理解析

这篇文章大致讲解一下spring的整个执行流程&#xff0c;也就是在我们脑子里面建立一个笼统的概念 spring如何创建一个容器呢 容器里面是对象 上面就是利用AnnotationConfigApplicationContext这个对象&#xff0c;然后传入了一个配置类的字节码对象给我们创建一个Spring容器&am…

Hyper-V 安装 CentOS (二)

总目录 https://preparedata.blog.csdn.net/article/details/132877836 文章目录 总目录一、Hyper-V 创建centos的虚拟机实例二、虚拟机安装Centos ISO镜像三、重启后&#xff0c;进入系统 一、Hyper-V 创建centos的虚拟机实例 网络连接先不选择&#xff0c;后面文章专门配置网…

【软考】系统架构设计师 - 知识扩展 - “区块链技术“

目录 一 简介&#x1f451; 1 比特币❤️ 2 区块链的特点❤️ 3 共识算法❤️ 二 练习题&#x1f451; 三 扩展&#x1f451; 1 哈希算法❤️ 2 哈希指针❤️ 3 UTXO❤️ 4 参考资料❤️ 一 简介&#x1f451; 1 比特币❤️ 比特币底层采用了区块链技术。 比特币交易…

03目标检测-传统方法与深度学习算法对比

目录 一、目标学习的检测方法变迁及对比 二、深度学习目标检测算法基本流程 三、传统目标检测算法VS深度学习目标检测算法 一、目标学习的检测方法变迁及对比 “目标检测“是当前计算机视觉和机器学习领域的研究热点。从Viola-Jones Detector、DPM等冷兵器时代的智…

【数据结构】二叉树的链式结构

【数据结构】二叉树的链式存储结构 二叉树的存储结构 typedef int BTDataType; // 二叉树的结构 typedef struct BinaryTreeNode {BTDataType data; // 树的值struct BinaryTreeNode *left; // 左孩子struct BinaryTreeNode *right;// 右孩子 } BinaryTreeNode;二…

EXCEL如何把一个单元格内的文本和数字分开?例如:龚龚15565 = 龚龚 15565

使用工具&#xff1a;WPS 举例&#xff1a; EXCEL如何把一个单元格内的文本和数字批量分开&#xff1f;不使用数据分列。 第一步、将第二行数据冻结 第二步、在B1、C1单元格输入需要分开的示例 第三步、点击选中B1单元格&#xff0c;输入快捷键【CTRLE】进行填充。B2单元格也是…

【AIGC】图片生成的原理与应用

前言 近两年 AI 发展非常迅速&#xff0c;其中的 AI 绘画也越来越火爆&#xff0c;AI 绘画在很多应用领域有巨大的潜力&#xff0c;AI 甚至能模仿各种著名艺术家的风格进行绘画。 目前比较有名商业化的 AI 绘画软件有 Midjourney、DALLE2、以及百度出品的文心一格&#xff1a;…