在调整大小期间不要重新绘制窗口 [英] Do not repaint window during resize

查看:52
本文介绍了在调整大小期间不要重新绘制窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 QML 应用程序 (Qt 5.4) 基于 Window 项.用户可以调整应用程序的大小.当应用程序调整大小时,应用程序的内容将分别调整大小(使用 onWidthChangedonHeightChanged).

My QML application (Qt 5.4) is based on a Window item. The application can be resized by the user. When the application is resized the content of the application is being resized respectively (with onWidthChanged and onHeightChanged).

这一切都很好.

但为了避免闪烁,我不想在调整应用程序大小时更新应用程序的内容.QML 中是否有可能检测用户何时实际调整窗口大小(在窗口边界上按住鼠标按钮)并且在调整大小完成(释放鼠标按钮)之前不重新计算内容?

But to avoid flickering I don't want to update the content of the application while the applicaiton is beeing resized. Is there a possibility in QML to detect when the user is actually resizing the window (holding the mouse button down over the border of the window) and don't recalculate the content before the resize is finished (the mouse button is released)?

推荐答案

EDIT :Kuba Ober 所建议的更简单、更强大,我仍然会在这里留下我的答案,因为我发现它有点有趣(以及 C++ 自定义组件可以修改方法以按照建议过滤窗口事件).

EDIT : What Kuba Ober suggested is infinitely simpler and more robust, I'll still leave my answer here as I found it somewhat interesting (and the C++ custom component approach can be modified to filter the window events as suggested).

对不起,我写了一个快速而丑陋的黑客来看看它是否可能,它只涵盖了您问题的第二部分(不更新内容).我的解决方案会阻止重绘项目,但也会在请求更新时立即隐藏它(这对您来说可能不是问题).

Pardon me but I have written a quick and ugly hack to see if it was possible, it only covers the second part of your question (not updating the content). My solution blocks the repainting of an Item, but also hide it as soon as an update is requested on it (which may not be a problem for you).

阅读QQuickItem::updatePaintNode 文档后,尤其是这句话

After reading the QQuickItem::updatePaintNode documentation and especially this phrase

如果用户在项目上设置了 QQuickItem::ItemHasContents 标志,则该函数作为 QQuickItem::update() 的结果被调用.

The function is called as a result of QQuickItem::update(), if the user has set the QQuickItem::ItemHasContents flag on the item.

我创建了一个 C++ 类来在任意 QQuickItem 上设置/取消设置此标志:

I created a C++ class to set/unset this flag on an abitrary QQuickItem :

#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

下一步是注册这个类,以便它可以在 QML 中使用:

next step is to register this class so that it can be used in QML :

qmlRegisterType<ItemUpdateBlocker>("com.mycompany.qmlcomponents", 1, 0, "ItemUpdateBlocker");

你可以像这样在 QML 中使用它:

And you can use it in QML like this :

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
            }
        }
    }
}

您当然可以向阻止程序添加一个 active 属性以简化它的使用(比使用 null target 禁用它更漂亮),但我会保留它作为练习.

You can of course add an active property to the blocker to simplify it's use (prettier than using a null target to disable it), but I'll leave that as an exercise.

也许您可以在 Window 的宽度或高度发生变化时启动计时器,我还没有找到直接的方法来确定窗口是否调整大小.

Maybe you can use that with a timer started whenever the width or the height of your Window is changed, I have not yet found a direct way to find if a window is resized.

这篇关于在调整大小期间不要重新绘制窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆