为什么一个懒惰加载的QWidget会显示,而一个存储的却不会
Why does a lazy-loaded QWidget get displayed but a stored one does not?
我有一组小的弹出窗口小部件,它们出现在不同的地方,但每次只有一个。对于简单的功能,新的显示和删除隐藏是可以的,并且可以像预期的那样工作,但当他们开始处理自己的数据时,我可以看到内存泄漏即将出现。
因此,因为我只需要每种类型中的一种,所以我想我应该在父构造函数中预先创建所有这些,并根据需要显示和隐藏它们。据我所知,这应该有效,但pop-up->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
);
}
我错过了什么?
您从未为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提到了z顺序,我还没有与之建立联系,这促使我在谷歌上进行了更多的搜索,很快找到了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
);
}
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 将数组信息存储到 c++ 向量中有一个"Access violation reading location"
- Boost program_options将多个配置文件解析结果存储到一个parsed_options中
- 将一个类的方法指针存储到另一个类中
- C++在一个映射中存储不同的指针类型(并处理销毁)
- 存储另一个函数返回的布尔数组时遇到问题
- 初始化一个由 p 指向的新 INTSTK,它最多可以存储 m 个
- 如何在循环中使用scanf,将值存储到一个变量中,然后打印出来?
- 将一个阵列中的数据存储到另外两个阵列中不起作用
- 一个 2D 数组,并按行存储值.第一个循环用于行索引,第二个循环用于列索引
- 对于存储另一个类所需信息的类,例如其构造,是否有设计模式?
- 生成一个类Name_class并将两种数据类型存储在一个向量中
- C 创建一个存储不同类型的向量
- 使用带有boost::program_options的多个源时,请使用最后一个存储值,而不是第一个存储值
- 创建一个伪元组,一个存储在其他地方的数据的前端
- 想要在C++中创建一个存储Nx3值的2D指针
- 一个存储大量元素的容器
- 为什么一个懒惰加载的QWidget会显示,而一个存储的却不会
- 我应该在什么时候为我的项目创建一个存储库
- 如何创建一个存储任意类型向量的向量