热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用QProgressBar时:无法为位于不同线程中的父级创建子级

如何解决《使用QProgressBar时:无法为位于不同线程中的父级创建子级》经验,为你挑选了1个好方法。

我试图根据手册创建QProgressBar .但它的工作非常糟糕(例如,如果我在构造函数中创建QProgressDialog,它会在app运行时出现,所以我决定使用QProgressBar).但有个问题:

在此输入图像描述

虽然我使用了互联网上的建议.我的代码:

UPD![2]

// StudentAbsenceTableApp.h
using Job = std::function;
Q_DECLARE_METATYPE(Job)
class StudentAbsenceTableApp{
public:
    StudentAbsenceTableApp(QWidget *parent = 0);

private:
    Q_SIGNAL void reqLoadFile(const QString& fileName);
    Q_SIGNAL void reqSaveFile(const QString& fileName);
    Q_SIGNAL void reqGui(const Job&);

    bool documentModified;
    QProgressBar *progressBar;
};

// StudentAbsenceTableApp.cpp
StudentAbsenceTableApp::StudentAbsenceTableApp(QWidget *parent)
   : QMainWindow(parent)
{
    // ...

    setStatusBar(new QStatusBar(this));

    qRegisterMetaType();
    progressBar = new QProgressBar(statusBar());
    progressBar->setMinimum(0);
    progressBar->setMaximum(0);
    progressBar->setMaximumWidth(150);
    progressBar->hide();
    statusBar()->addPermanentWidget(progressBar);

    connect(this, &StudentAbsenceTableApp::reqLoadFile, this, [this] (const QString& fileName){
        QtConcurrent::run(this, &StudentAbsenceTableApp::loadFile, fileName);
    });
    connect(this, &StudentAbsenceTableApp::reqGui, [this](const Job & job){
        job();
    });
}

// funtion that emit reqLoadFile(fileName)

bool StudentAbsenceTableApp::loadFile(const QString& fileName)
{
    reqGui([=] () { progressBar->show(); });
    auto xmlParser = XMLParser(model);

    try
    {
        reqGui([&] () {
            xmlParser.read(fileName);
            setCurrentFileName(fileName);
            statusBar()->showMessage(tr("???? ????????"), 2000);
            documentModified = false;
        });
    }
    catch(FileOpenException)
    {
        reqGui([=] () {
            QMessageBox::warning(this, "??????!", "?????? ???????? ?????!", QMessageBox::Ok);
            statusBar()->showMessage(tr("???????? ????????"), 2000);
        });
        return false;
    }
    catch(FileReadException)
    {
        reqGui([=] () {
            QMessageBox::warning(this, "??????!", "?????? ?????? ?????!", QMessageBox::Ok);
            statusBar()->showMessage(tr("???????? ????????"), 2000);
        });
        return false;
    }

    reqGui([=] () { progressBar->hide(); });
    return true;
}

我不知道如何编写代码,可以编译,因为有很多代码.



1> Reinstate Mo..:

QWidgetQt提供的No (和派生类)方法是线程安全的.因此,您无法QProgressBar从GUI线程以外的任何线程访问任何其他小部件.

experimentFunction一个非GUI线程运行,因此不能访问部件.您必须找出一些其他通信方式,例如使用信号和插槽.回想一下,您可以自由发出信号experimentFunction,因为信号实现是通过合同线程安全的.

这一切都非常简单,你不需要未来的观察者.在您尝试"修复"该问题时,您已经无可救药地组合了您的代码.

有关在线程之间安全地调用方法的其他方法,请参阅此问题和该问题.

// https://github.com/KubaO/stackoverflown/tree/master/questions/thread-progress-future-44445248
#include 
#include 
#include 
#include 

struct FileOpenException : std::exception {};
struct FileReadException : std::exception {};
struct Model {};
struct XMLParser {
   XMLParser(Model &) {}
   void read(const QString &) {
      static int outcome;
      QThread::sleep(3);
      switch (outcome++ % 3) {
      case 0: return;
      case 1: throw FileOpenException();
      case 2: throw FileReadException();
      }
   }
};

using Job = std::function;
Q_DECLARE_METATYPE(Job)

class StudentAbsenceTable : public QMainWindow {
   Q_OBJECT
   QStatusBar m_statusBar;
   QProgressBar m_progress;
   QPushButton m_start{"Start Concurrent Task"};
   Model m_model;
   bool m_documentModified = {};
public:
   StudentAbsenceTable() {
      qRegisterMetaType();
      m_statusBar.addPermanentWidget(&m_progress);
      m_progress.setMinimum(0);
      m_progress.setMaximum(0);
      m_progress.setMaximumWidth(150);
      m_progress.hide();
      setStatusBar(&m_statusBar);
      setCentralWidget(&m_start);
      connect(&m_start, &QPushButton::clicked, this, [this]{
         m_start.setEnabled(false);
         QtConcurrent::run(this, &StudentAbsenceTable::loadFile);
      });
      connect(this, &StudentAbsenceTable::reqGui, this, [this](const Job & job){
         job();
      });
   }
private:
   bool loadFile() {
      reqGui([=]{ m_progress.show(); });
      auto fileName = QStringLiteral("/media/bsuir/data.xml");
      auto xmlParser = XMLParser(m_model);
      try {
         xmlParser.read(fileName);
         reqGui([=]{
            setCurrentFileName(fileName);
            statusBar()->showMessage(tr("???? ????????"), 2000);
            m_documentModified = false;
         });
      }
      catch(FileOpenException&) {
         reqGui([=]{
            QMessageBox::warning(this, "??????!", "?????? ???????? ?????!", QMessageBox::Ok);
            statusBar()->showMessage(tr("???????? ????????"), 2000);
         });
      }
      catch(FileReadException&) {
         reqGui([=]{
            QMessageBox::warning(this, "??????!", "?????? ?????? ?????!", QMessageBox::Ok);
            statusBar()->showMessage(tr("???????? ????????"), 2000);
         });
      }
      reqGui([=]{ m_progress.hide(); m_start.setEnabled(true); });
      return false;
   }
   Q_SIGNAL void reqGui(const Job &);
   void setCurrentFileName(const QString &) {}
};

int main(int argc, char ** argv) {
   QApplication app(argc, argv);
   StudentAbsenceTable ui;
   ui.setMinimumSize(350, 350);
   ui.show();
   return app.exec();
}
#include "main.moc"


推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 本文整理了Java中org.apache.solr.common.SolrDocument.setField()方法的一些代码示例,展示了SolrDocum ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • Flutter 布局(四) Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth详解
    本文主要介绍Flutter布局中的Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth四种控件,详细介绍了其布局 ... [详细]
author-avatar
贺bujak_491
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有