4

是否有信号告诉“显示”功能何时完成?

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

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

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

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

确实如此。

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

4

4 回答 4

5

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

在您的 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 件事情需要多长时间最重要的是,等等等等。希望有所帮助,包括额外的解释,希望它可以为您提供更好的方法来做您想做的事情,而不是等待某事完成,“知道”它已经完成是一个更好的选择。

于 2013-12-22T08:01:39.233 回答
3

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

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

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

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

于 2013-04-08T16:35:02.363 回答
1

问题可以在没有子类化的情况下决定,只需像这样安装事件过滤器:

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();
于 2017-07-06T11:17:26.257 回答
0

覆盖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;
}
于 2016-09-27T18:31:16.923 回答