【问题标题】:QMainWindow - wait until 'show' function is doneQMainWindow - 等到“显示”功能完成
【发布时间】:2013-03-30 20:03:43
【问题描述】:

是否有信号表明“显示”功能何时结束?

我的代码有问题:如果我写:

QMainWinObj.show();
QMainWinObj.someGuiFunc();

代码不起作用。但是,如果我写:

QMainWinObj.show();
sleep(3000);
QMainWinObj.someGuiFunc();

确实如此。

所以我认为问题在于,在我调用“someGuiFunc”之前,“show”并没有完成它的任务。这就是为什么我想要某种“表演”结束的标志..

【问题讨论】:

  • 了解您在此处尝试执行的操作很重要。你的最终目标是什么? someGuiFunc() 在做什么?
  • 我同意@JanKundrát,为什么someGuiFunc() 依赖于QMainWinObj 的可见性?即使它确实依赖于它被绘制,someGuiFunc() 也只需要等到事件队列被刷新(有几种简单的方法可以做到这一点),但如果是这种情况,第二个示例仍然无法工作,因为sleep 暂停当前线程。

标签: qt qmainwindow


【解决方案1】:

这可能有点过时了,但因为除了这个之外没有其他人回答它: 由于没有“显示”信号,我建议像这样覆盖显示事件:

在您的 mainwindow.cpp 文件中:

void MainWindow::show()
{
   QMainWindow::show();
   QApplication::processEvents();
   emit windowShown();
}

在您的 mainwindow.h 文件中,在 MainWindow 的声明中:

...
class MainWindow: public QMainWindow
{
   ...
   signals:
       void windowShown();

   ...
}
...

然后,当您转到设计器时,右键单击主窗口(对象树的最顶部),然后选择“更改信号/插槽”。在“信号”框架中,单击“+”按钮,您需要添加“windowShown()”,然后按回车,然后单击“确定”按钮(注意省略号“...”表示其他代码已经在您的标题中)。

就是这样——您现在可以随时使用信号/插槽编辑器将插槽链接到“windowShown”信号。现在,如果您想要更像微软的“加载”事件,我认为它在 .NET 中使用,您将需要创建一些实例变量并标记它,以便每次显示窗口时都不会发出它,例如:

void MainWindow::show()
{
   QMainWindow::show();
   QApplication::processEvents();
   emit windowShown();
   if (firstTimeShown == true)
   {
      emit windowLoaded();
      firstTimeShown = false;
   }
}

另外,不要忘记在构造函数中将变量初始化为“true”:

MainWindow::MainWindow(QObject* parent)
 ...
{
   firstTimeShown = true; // put this somewhere before ui->setupUi()
}

但是,如果您决定将它放在初始化列表中,请确保它的顺序正确。如果变量没有按照类头文件中声明的从上到下的方式实例化,编译器会报错。

现在,请确保在标题中定义 firstTimeShown 时,将其设为私有。并且不要忘记添加的信号:

class MainWindow : public QMainWindow
{
    ...
    signals:
      void windowLoaded();
      void windowShown();

    private:
      bool firstTimeShown;
    ...

就是这样。借助信号和插槽的灵活性,它可以很容易地模仿您可能从 Windows 窗体或 MFC 中找到的任何事件。程序员只需要一点点努力。一旦你掌握了它的窍门,它就会成为第二天性。

注意:可能有 优化或更精确的方法来执行“已加载”和“已显示”信号,但为了简单起见,我已将此类内容排除在外。回到手头的问题,调用 QApplication::processEvents() 很可能是您想要做的,而不是等待固定的时间,因为谁知道如果用户正在运行其他 100 件事情需要多长时间最重要的是,等等等等。希望有所帮助,包括额外的解释,希望它可以为您提供更好的方法来做您想做的事情,而不是等待某事完成,“知道”它已经完成是一个更好的选择。

【讨论】:

    【解决方案2】:

    没有这样的信号,但是将 QMainWindow 子类化后,您可以覆盖 showEvent 事件。

    void MainWindow::showEvent(QShowEvent *){
        //your code
    }
    

    更多信息在这里:http://qt-project.org/doc/qt-4.8/qwidget.html#showEvent

    请注意,每次您的窗口即将显示时都会调用它。

    【讨论】:

      【解决方案3】:

      问题可以不用子类化来决定,只需像这样安装事件过滤器:

      class CWidgetIsPainting_EF : public QObject
      {
          bool m_bIsPainted = false;
      public:
          CWidgetIsPainting_EF( QObject * parent = 0 ) : QObject (parent) { }
      
          inline bool IsPainted() const { return m_bIsPainted; }
          inline void setIsPainted( bool bIsPainted ) { m_bIsPainted = bIsPainted; }
      
      protected:
          bool eventFilter( QObject * obj, QEvent *event )
          {
              if (event->type() == QEvent::Paint)
              {
                  m_bIsPainted = true;
                  return true;
              };
              return QObject::eventFilter(obj, event);
          }
      };
      

      ... ...

      CWidgetIsPainting_EF * pPaintingEF = new CWidgetIsPainting_EF( m_pWidget );
      m_pWidget->installEventFilter( pPaintingEF );
      

      ... ...

      while ( !pPaintingEF->IsPainted() )
          QApplication::processEvents();
      

      【讨论】:

        【解决方案4】:

        覆盖 bool event(QEvent *event) 并捕获 Paint 事件。至少在 Windows 上对我有用。

        // MainWindow.h
        class MainWindow : public QMainWindow
        {
            ...
            bool event(QEvent *event) override;
            void functionAfterShown();
            ...
            bool functionAfterShownCalled = false;
            ...
        }
        
        // MainWindow.cpp
        bool MainWindow::event(QEvent *event)
        {
            const bool ret_val = QMainWindow::event(event);
            if(!functionAfterShownCalled && event->type() == QEvent::Paint)
            {
                functionAfterShown();
                functionAfterShownCalled = true;
            }
            return ret_val;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-25
          • 1970-01-01
          • 1970-01-01
          • 2020-08-14
          相关资源
          最近更新 更多