【问题标题】:Why does a lazy-loaded QWidget get displayed but a stored one does not?为什么延迟加载的 QWidget 会显示而存储的 QWidget 不会显示?
【发布时间】:2015-12-15 03:11:09
【问题描述】:

我有一组小弹出窗口小部件,它们出现在不同的地方,但每次只有一个。对于简单的功能,new-to-show 和 delete-to-hide 是可以的,并且工作正常,但是当他们开始处理自己的数据时,我可以看到内存泄漏。

所以因为我只需要每一种,我想我会在父构造函数中预先创建所有它们,并根据需要显示和隐藏它们。据我所知,这应该可以,但是 popup->show() 没有显示。此示例所基于的复杂应用程序表明弹出窗口确实存在于正确的位置,并且可以与用户交互...除了它是不可见的。

这是显示的惰性版本:

#ifndef MAIN_H
#define MAIN_H

#include <QtWidgets>

class Popup : public QLabel
{
    Q_OBJECT
public:
    explicit Popup(int x, int y, int width, int height, QWidget* parent = 0);
};

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget* parent = 0);
    ~MainWindow() {}
    void mousePressEvent(QMouseEvent* ev);
private:
    Popup* popup;
};

#endif // MAIN_H

/***************
*** main.cpp ***
***************/
#include "main.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}



MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
{
    popup = 0;

    QWidget* cWidget = new QWidget(this);
    cWidget->setStyleSheet("background-color: lightgray");
    setCentralWidget(cWidget);

    showMaximized();
}

void MainWindow::mousePressEvent(QMouseEvent* ev)
{
    if(popup != 0)
    {
        if(!popup->geometry().contains(ev->x(), ev->y()))
        {
            delete popup;
            popup = 0;
        }
    }
    else
    {
        popup = new Popup(ev->x(), ev->y(), 100, 100, this);
        popup->show();
    }
    ev->accept();
}



Popup::Popup(int x, int y, int width, int height, QWidget* parent) :
    QLabel(parent)
{
    setStyleSheet("background-color: black");
    setGeometry(
                x - (width  / 2),   // Left
                y - (height / 2),   // Top
                width ,             // Width
                height              // Height
                );
}

这是未显示的预创建版本:

#ifndef MAIN_H
#define MAIN_H

#include <QtWidgets>

class Popup : public QLabel
{
    Q_OBJECT
public:
    explicit Popup(QWidget* parent = 0);
    void setup(int x, int y, int width, int height);
};

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget* parent = 0);
    ~MainWindow() {}
    void mousePressEvent(QMouseEvent* ev);
private:
    Popup* popup;
};

#endif // MAIN_H

/***************
*** main.cpp ***
***************/
#include "main.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}



MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
{
    popup = new Popup(this);

    QWidget* cWidget = new QWidget(this);
    cWidget->setStyleSheet("background-color: lightgray");
    setCentralWidget(cWidget);

    showMaximized();
}

void MainWindow::mousePressEvent(QMouseEvent* ev)
{
    if(popup->isVisible())
    {
        if(!popup->geometry().contains(ev->x(), ev->y()))
        {
            popup->hide();
        }
    }
    else
    {
        popup->setup(ev->x(), ev->y(), 100, 100);
        popup->show();
    }
    ev->accept();
}



Popup::Popup(QWidget* parent) :
    QLabel(parent)
{
    setStyleSheet("background-color: black");
}

void Popup::setup(int x, int y, int width, int height)
{
    setGeometry(
                x - (width  / 2),   // Left
                y - (height / 2),   // Top
                width ,             // Width
                height              // Height
                );
}

我错过了什么?

【问题讨论】:

    标签: c++ qt user-interface qwidget


    【解决方案1】:

    您永远不会为您的 popup 小部件设置窗口标志(例如 Qt::Popup)。
    它实际上是MainWindow w 的子小部件,应该显示在某处。

    在 Qt 中,周围没有布局的 QWidget 只是简单地堆叠在一起。出现的 z 顺序取决于实例化的顺序。这就是为什么懒惰的 QLabel 可见而另一个不可见的原因。

    务实地在 cWidget 之后实例化弹出窗口可能就足够了:

    MainWindow::MainWindow(QWidget* parent)
        : QMainWindow(parent)
    {
        // popup = new Popup(this); // not here
    
        QWidget* cWidget = new QWidget(this);
        cWidget->setStyleSheet("background-color: lightgray");
        setCentralWidget(cWidget);
    
        popup = new Popup(this); // but here (untested, but should work)
    
        showMaximized();
    }
    

    但是要以 Qt 方式执行此操作,您应该避免堆叠小部件,而是为您的 popup 提供真正的弹出外观:

    popup->setWindowFlags(Qt::Popup); // this lets popup have its own window
    

    【讨论】:

    • 感谢@Martin 的帮助。正如我的回答中提到的,我最终使用了不同的解决方案,但你让我开始朝那个方向发展。为此 +1。
    【解决方案2】:

    Martin 提到 z-order,我还没有与之建立联系,这促使我进行了更多的谷歌搜索,很快找到了 QWidget::raise() 方法。现在它按我的预期工作了。

    实例化顺序确实有效,但如果您动态创建更多小部件则无效。弹出窗口仍会出现在动态小部件下方。

    我确信有办法让它工作(这我的第一个 Qt 项目,所以尽管我尽了最大努力,但我完全希望在几年后将其称为“丑陋”),但是窗口标志打破了弹出窗口和应用程序已经编写的方式之间的耦合。如果我从窗口标志开始,我可能会让它工作得很好,甚至更好,但我没有。

    这就是我现在正在做的,有效的:

    #ifndef MAIN_H
    #define MAIN_H
    
    #include <QtWidgets>
    
    class Popup : public QLabel
    {
        Q_OBJECT
    public:
        explicit Popup(QWidget* parent = 0);
        void setup(int x, int y, int width, int height);
    };
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        MainWindow(QWidget* parent = 0);
        ~MainWindow() {}
        void mousePressEvent(QMouseEvent* ev);
    private:
        Popup* popup;
    };
    
    #endif // MAIN_H
    
    /***************
    *** main.cpp ***
    ***************/
    #include "main.h"
    #include <QApplication>
    
    int main(int argc, char* argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    
    
    MainWindow::MainWindow(QWidget* parent)
        : QMainWindow(parent)
    {
        popup = new Popup(this);
    
        QWidget* cWidget = new QWidget(this);
        cWidget->setStyleSheet("background-color: lightgray");
        setCentralWidget(cWidget);
    
        showMaximized();
    }
    
    void MainWindow::mousePressEvent(QMouseEvent* ev)
    {
        if(popup->isVisible())
        {
            if(!popup->geometry().contains(ev->x(), ev->y()))
            {
                popup->hide();
            }
        }
        else
        {
            popup->setup(ev->x(), ev->y(), 100, 100);
            popup->raise();     /*** THIS IS WHAT I WAS MISSING!!! ***/
            popup->show();
        }
        ev->accept();
    }
    
    
    
    Popup::Popup(QWidget* parent) :
        QLabel(parent)
    {
        setStyleSheet("background-color: black");
    }
    
    void Popup::setup(int x, int y, int width, int height)
    {
        setGeometry(
                    x - (width  / 2),   // Left
                    y - (height / 2),   // Top
                    width ,             // Width
                    height              // Height
                    );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-18
      • 2022-01-19
      • 2022-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-29
      • 1970-01-01
      相关资源
      最近更新 更多