Qt 调整大小期间不重新绘制窗口
我的QML应用程序(Qt5.4)基于Qt 调整大小期间不重新绘制窗口,qt,qml,qt-quick,qtquick2,Qt,Qml,Qt Quick,Qtquick2,我的QML应用程序(Qt5.4)基于窗口项。用户可以调整应用程序的大小。调整应用程序大小时,将分别调整应用程序内容的大小(使用onWidthChanged和onHeightChanged) 这一切都很好 但是为了避免闪烁,我不想在应用程序调整大小时更新应用程序的内容。QML中是否有可能检测用户何时实际调整窗口大小(在窗口边界上按住鼠标按钮),并且在调整完毕(释放鼠标按钮)之前不重新计算内容?编辑:Kuba Ober建议的方法非常简单和可靠,我仍然会在这里留下我的答案,因为我发现它有点有趣(并且C
窗口项。用户可以调整应用程序的大小。调整应用程序大小时,将分别调整应用程序内容的大小(使用onWidthChanged
和onHeightChanged
)
这一切都很好
但是为了避免闪烁,我不想在应用程序调整大小时更新应用程序的内容。QML中是否有可能检测用户何时实际调整窗口大小(在窗口边界上按住鼠标按钮),并且在调整完毕(释放鼠标按钮)之前不重新计算内容?编辑:Kuba Ober建议的方法非常简单和可靠,我仍然会在这里留下我的答案,因为我发现它有点有趣(并且C++自定义组件方法可以修改以过滤窗口事件,如建议)。
请原谅,我写了一篇快速而难看的文章,看看是否可能,它只涵盖了你问题的第二部分(不更新内容)。
我的解决方案会阻止项目的重新绘制,但也会在请求对其进行更新时将其隐藏(这对您来说可能不是问题)
在阅读了文档,尤其是这个短语之后
如果用户已在项目上设置QQuickItem::ItemHasContents标志,则该函数将作为QQuickItem::update()的结果调用
< P>我创建了一个C++类,在一个abqQuQuiType:上设置/取消这个标志
#ifndef ITEMUPDATEBLOCKER_H
#define ITEMUPDATEBLOCKER_H
#include <QObject>
#include <QQuickItem>
class ItemUpdateBlocker : public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickItem* target READ target WRITE setTarget NOTIFY targetChanged)
QQuickItem* m_target;
public:
explicit ItemUpdateBlocker(QObject *parent = 0) : QObject(parent), m_target(nullptr) { }
QQuickItem* target() const { return m_target; }
signals:
void targetChanged();
private:
static void blockUpdate(QQuickItem* target)
{
if (target)
target->setFlag(QQuickItem::ItemHasContents, false);
}
static void unblockUpdate(QQuickItem* target)
{
if (target)
{
target->setFlag(QQuickItem::ItemHasContents, true);
target->update();
}
}
public slots:
void setTarget(QQuickItem* target)
{
if (m_target == target)
return;
unblockUpdate(m_target);
blockUpdate(target);
m_target = target;
emit targetChanged();
}
};
#endif // ITEMUPDATEBLOCKER_H
当然,您可以向阻止程序添加一个active
属性来简化它的使用(比使用nulltarget
来禁用它更漂亮),但我将把它作为练习
也许你可以在窗口的宽度或高度发生变化时启动计时器,我还没有找到一种直接的方法来确定窗口的大小
但是为了避免闪烁,我不想在应用程序调整大小时更新应用程序的内容
我也有同样的意图,然后发现在我的例子中,当窗口不经常重新绘制时,它已经足以避免闪烁和高CPU负载。这可以通过计时器实现:
import QtQuick 2.12
import QtQuick.Controls 2.12
Window {
id: root
onWidthChanged: {
redrawTimer.running ? redrawTimer.restart() : redrawTimer.start()
}
onHeightChanged: {
redrawTimer.running ? redrawTimer.restart() : redrawTimer.start()
}
Timer {
id: redrawTimer
interval: 100
onTriggered: {
content.width = ...
content.height = ...
}
}
// Actual content of your window, here assumed to be in a custom QML type.
WindowContent {
id: content
}
}
上面的代码创建了一个窗口,该窗口仅在过去100毫秒内未收到调整大小事件时才重新绘制。这样,在调整大小结束和重新绘制之间,以及在调整大小期间暂停鼠标移动和重新绘制之间,会有一个很小但几乎不明显的延迟
这种方法尤其适用于具有快速、低质量和慢速、高质量重绘方式的元素,例如与SVG源一起使用的Qt QMLImage
类型。在这种情况下,基于光栅图形的缩放速度很快,可以在使用QML布局或锚定机制调整窗口大小期间完成,从而创建“预览”。通过设置重新绘制SVG的速度很慢,只有在如上所示的计时器触发时才会进行。过滤相关事件,直到松开鼠标按钮。具体来说,在按住鼠标按钮的同时“吃掉”调整大小事件,然后在释放鼠标后合成最终的调整大小事件。您可以在连接到显示QML界面的窗口/小部件对象的事件筛选器中完成这一切。我尝试了这一方法,但问题是在调整窗口大小时,您没有获得鼠标按下或释放事件,并且QGuiApplication::mouseButtons
返回没有按下任何按钮。
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import com.mycompany.qmlcomponents 1.0
ApplicationWindow {
width: 640
height: 480
visible: true
Rectangle {
color: "red"
id: root
anchors.fill: parent
Text {
text: blocker.target ? "Blocked" : "Not Blocked"
}
Rectangle {
color: "white"
anchors.centerIn: parent
width: parent.width/2
height: parent.height/2
ItemUpdateBlocker {
id: blocker;
}
MouseArea {
anchors.fill: parent
onClicked: blocker.target = blocker.target ? null : parent
}
}
}
}
import QtQuick 2.12
import QtQuick.Controls 2.12
Window {
id: root
onWidthChanged: {
redrawTimer.running ? redrawTimer.restart() : redrawTimer.start()
}
onHeightChanged: {
redrawTimer.running ? redrawTimer.restart() : redrawTimer.start()
}
Timer {
id: redrawTimer
interval: 100
onTriggered: {
content.width = ...
content.height = ...
}
}
// Actual content of your window, here assumed to be in a custom QML type.
WindowContent {
id: content
}
}