Python 如何知道用户何时完成调整窗口大小?
我正在为自己编程一个PDF阅读器,以获得乐趣和笑声,但是当窗口被调整大小时,我遇到了麻烦。问题如下:当加载PDF时调整窗口大小时,PDF会再次渲染以匹配新窗口大小,但是resizeEvent会被调用多次,因此渲染功能会被调用多次,这是非常低效的,会导致延迟。是否有一种方法可以让程序在resizeEvent完全完成时发出通知,然后调用render函数?Python和C++中的解决方案都是欢迎的< p>假设你的类被命名为PDFXRead,你可以使用一个单点QTIMER通知你,当这个小部件没有被调整一个特定的时间长度时,比如说1秒,如果这个计时器不活动,只更新小部件。 一个基于QLabel的简单示例可能看起来像Python 如何知道用户何时完成调整窗口大小?,python,c++,qt,pyqt5,qt5,Python,C++,Qt,Pyqt5,Qt5,我正在为自己编程一个PDF阅读器,以获得乐趣和笑声,但是当窗口被调整大小时,我遇到了麻烦。问题如下:当加载PDF时调整窗口大小时,PDF会再次渲染以匹配新窗口大小,但是resizeEvent会被调用多次,因此渲染功能会被调用多次,这是非常低效的,会导致延迟。是否有一种方法可以让程序在resizeEvent完全完成时发出通知,然后调用render函数?Python和C++中的解决方案都是欢迎的< p>假设你的类被命名为PDFXRead,你可以使用一个单点QTIMER通知你,当这个小部件没有被调整一
class PDF_reader: public QLabel {
using super = QLabel;
using this_class = PDF_reader;
public:
PDF_reader ()
: super("Some text goes here")
{
m_timer.setSingleShot(true);
m_timer.setInterval(1000);
connect(&m_timer, &QTimer::timeout, this, [this]{ update(); });
}
virtual void resizeEvent (QResizeEvent *event) override
{
m_timer.stop();
m_timer.start();
}
virtual void paintEvent (QPaintEvent *event) override
{
if (!m_timer.isActive()) {
super::paintEvent(event);
}
event->accept();
}
private:
QTimer m_timer;
};
假设您的类名为PDF_reader,您可以使用单发QTimer通知您小部件在特定的时间长度(例如1秒)内未调整大小,并且仅在计时器处于非活动状态时更新小部件 一个基于QLabel的简单示例可能看起来像
class PDF_reader: public QLabel {
using super = QLabel;
using this_class = PDF_reader;
public:
PDF_reader ()
: super("Some text goes here")
{
m_timer.setSingleShot(true);
m_timer.setInterval(1000);
connect(&m_timer, &QTimer::timeout, this, [this]{ update(); });
}
virtual void resizeEvent (QResizeEvent *event) override
{
m_timer.stop();
m_timer.start();
}
virtual void paintEvent (QPaintEvent *event) override
{
if (!m_timer.isActive()) {
super::paintEvent(event);
}
event->accept();
}
private:
QTimer m_timer;
};
免责声明
下面的解决方案是对如何知道用户何时完成窗口大小调整的问题的回答,这一问题很清楚,可以回答
然而,我相信你有一个XY问题。您正在经历的缓慢渲染可能是由于使用了错误的技术,但是如果没有看到代码,就无法判断。我建议您在另一个问题中描述您的渲染问题,并用一个
解决方案
我解决这一问题的方法是:
在调整大小之前采取行动
正如@musicamante在评论中所写:
当您收到resizeEvent时,调整大小已经发生 超车的方法是改用并注意安全 尝试区分编程调整大小(即调用)和用户调整大小(即通过拖动窗口边缘) 可用于此目的,因为: 如果源于应用程序外部的事件是系统事件,则返回true;否则返回false 如果事件是非自发的程序调整大小,则允许生成resizeEvent来设置复杂小部件的初始大小。对于自发事件用户调整大小,请防止生成resizeEvent并手动处理复杂小部件的大小 获取用户完成调整窗口大小的确切时间,而不是使用计时器,如@G.M.。按照建议,我非常尊重@G.M 在这里,非客户端eamousebutonrelease事件类型可能会派上用场 这并不一定意味着用户正在调整窗口的大小。拖动窗口时也会生成此事件类型。但是,在这种情况下,这并不影响解决方案 注意:不要将复杂的小部件添加到任何布局中,因为它会破坏手动大小处理 实例
这里是C++的一个例子,我已经为您编写了,以说明如何实现所提出的解决方案:
#include <QApplication>
#include <QResizeEvent>
#include <QFormLayout>
#include <QLineEdit>
class MainWindow : public QWidget
{
QWidget *m_complexWidget;
public:
MainWindow(QWidget *parent = nullptr) :
QWidget(parent),
m_complexWidget(new QWidget(this)) {
auto *form = new QFormLayout(m_complexWidget);
for (int n = 0; n < 20; n++)
form->addRow(tr("Property ") + QString::number(n),
new QLineEdit(this));
resize(400, 400);
}
bool event(QEvent *event) override {
switch (event->type()) {
case QEvent::NonClientAreaMouseButtonRelease:
// The widget is resized at the end of a resize
m_complexWidget->resize(size());
break;
case QEvent::Resize:
// Prevent generation of a resize event
if (event->spontaneous())
return false;
break;
default:
break;
}
return QWidget::event(event);
}
protected:
void resizeEvent(QResizeEvent *event) override {
// The widget's size is set to the initial size of the window
m_complexWidget->resize(event->size());
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
免责声明
下面的解决方案是对如何知道用户何时完成窗口大小调整的问题的回答,这一问题很清楚,可以回答
然而,我相信你有一个XY问题。您正在经历的缓慢渲染可能是由于使用了错误的技术,但是如果没有看到代码,就无法判断。我建议您在另一个问题中描述您的渲染问题,并用一个
解决方案
我解决这一问题的方法是:
在调整大小之前采取行动
正如@musicamante在评论中所写:
当您收到resizeEvent时,调整大小已经发生 超车的方法是改用并注意安全 尝试区分编程调整大小(即调用)和用户调整大小(即通过拖动窗口边缘) 可用于此目的,因为: 如果源于应用程序外部的事件是系统事件,则返回true;否则返回false 如果事件是非自发的程序调整大小,则允许生成resizeEvent来设置复杂小部件的初始大小。对于自发事件用户调整大小,请防止生成resizeEvent并手动处理复杂小部件的大小 获取用户完成调整窗口大小的确切时间,而不是使用计时器,如@G.M.。按照建议,我非常尊重@G.M 在这里,非客户端eamousebutonrelease事件类型可能会派上用场 这并不一定意味着用户正在调整窗口的大小。拖动窗口时也会生成此事件类型。但是,在这种情况下,这并不影响解决方案 注意:不要将复杂的小部件添加到任何布局中,因为它会破坏手动大小处理 实例
这里是C++的一个例子,我已经为你编写了 o演示如何实施建议的解决方案:
#include <QApplication>
#include <QResizeEvent>
#include <QFormLayout>
#include <QLineEdit>
class MainWindow : public QWidget
{
QWidget *m_complexWidget;
public:
MainWindow(QWidget *parent = nullptr) :
QWidget(parent),
m_complexWidget(new QWidget(this)) {
auto *form = new QFormLayout(m_complexWidget);
for (int n = 0; n < 20; n++)
form->addRow(tr("Property ") + QString::number(n),
new QLineEdit(this));
resize(400, 400);
}
bool event(QEvent *event) override {
switch (event->type()) {
case QEvent::NonClientAreaMouseButtonRelease:
// The widget is resized at the end of a resize
m_complexWidget->resize(size());
break;
case QEvent::Resize:
// Prevent generation of a resize event
if (event->spontaneous())
return false;
break;
default:
break;
}
return QWidget::event(event);
}
protected:
void resizeEvent(QResizeEvent *event) override {
// The widget's size is set to the initial size of the window
m_complexWidget->resize(event->size());
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
请添加您迄今为止尝试的内容当您收到一个调整大小的事件时,调整大小已经发生,问题是一些小部件可能会重复或甚至递归地收到它,这通常发生在滚动条播放时。你如何展示这些文件?您可以共享吗?请添加您迄今为止尝试的内容当您收到一个调整大小的事件时,已经发生了调整大小的事件,问题是一些小部件可能会重复或甚至递归地收到它,这通常发生在滚动条播放时。你如何展示这些文件?你能分享一个吗?非常感谢你的例子和解释。今天晚些时候我会试试这个。关于如何防止多次调用resizeEvent,我有另一个想法:停用调整大小的动画。我的渲染尚未优化,我将在稍后执行此操作。我目前的渲染问题是,我在同一时间渲染整个PDF,这显然是愚蠢的,但我会在这个周末解决这个问题probably@Mettigel4_1正如我所说的,您真正的问题不在于调整大小。请按照我回答中的建议,发布另一个有足够详细信息的问题,这样才能确定真正的问题并提出解决方案。至于调整大小,如果你尝试这个例子,它是完美的,所以我建议你考虑接受和/或投票我的答案。我将继续工作。谢谢你的问题部分是在调整大小,因为没有点渲染PDF的3倍,因为我点击调整我的窗口按钮。我很清楚我的渲染问题,我已经在解决它非常感谢你的例子和解释。今天晚些时候我会试试这个。关于如何防止多次调用resizeEvent,我有另一个想法:停用调整大小的动画。我的渲染尚未优化,我将在稍后执行此操作。我目前的渲染问题是,我在同一时间渲染整个PDF,这显然是愚蠢的,但我会在这个周末解决这个问题probably@Mettigel4_1正如我所说的,您真正的问题不在于调整大小。请按照我回答中的建议,发布另一个有足够详细信息的问题,这样才能确定真正的问题并提出解决方案。至于调整大小,如果你尝试这个例子,它是完美的,所以我建议你考虑接受和/或投票我的答案。我将继续工作。谢谢你的问题部分是在调整大小,因为没有点渲染PDF的3倍,因为我点击调整我的窗口按钮。我很清楚我的渲染问题,我已经在修复它了。我不希望使用计时器,我认为这是一个解决方案,而不是一个解决方案。但谢谢你举个例子,我不想使用计时器,我认为这是一种解决方法,而不是一种解决方案。但是谢谢你的例子