【问题标题】:QtQuick GeometryChanged method only works in one direction for loaded componentsQtQuick GeometryChanged 方法仅适用于加载组件的一个方向
【发布时间】:2019-05-03 02:02:12
【问题描述】:

我正在构建一个 Python + QtQuick 应用程序,该应用程序需要一个从 QQuickPaintedItem 下降的类。我在管理已绘制项目的布局和大小时遇到​​了一些问题。

特别是,我有一个看起来像这样的应用程序

左侧有一组按钮,窗口右侧是Loader(这是有充分理由的,这只是演示问题的最小示例)。

主 qml 文件 (main.qml) 如下所示:

import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3

ApplicationWindow {
    id: mainWindow
    visible: true
    width: 720
    height: 480
    title: qsTr("QML Sampler")
    onClosing: main.close_application()

    RowLayout {
        anchors.fill: parent

        ColumnLayout {
            id: sideBar
            Layout.fillHeight: true
            Layout.preferredWidth: 200
            Layout.minimumWidth: 150
            Layout.maximumWidth: 350

            Button {
                id: buttonScreen1
                text: "Button 1"
                Layout.fillWidth: true
            }

            Button {
                id: buttonScreen2
                text: "Button 2"
                Layout.fillWidth: true
            }
        }

        Loader {
            id: contentAreaLoader
            Layout.fillHeight: true
            Layout.preferredWidth: 520
            Layout.minimumWidth: 300

            source: 'loaded_content.qml'
        }
    }
}

加载的内容文件是实际包含自定义类的文件,如下所示(loaded_content.qml):

import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3

import CustomPaintedItem 1.0

ColumnLayout {
    anchors.fill: parent

    Label {
        text: "Here's a thing!"
    }

    CustomPaintedItem {
        Layout.fillHeight: true
        Layout.fillWidth: true
    }
}

当窗口调整大小时,我希望能够获得 QQuickPaintedItem 的新尺寸,所以在代码中,我重写了QQuickPaintedItem.geometryChanged() 方法。在本例中,我只是打印新旧几何图形。

所有这些的剩余代码如下。涉及三个python文件,一个用于main,一个用于CustomPaintedItem类,一个用于主控制器。

main.py 看起来像这样:

import os
import sys

from PyQt5.QtQml import QQmlApplicationEngine, qmlRegisterType
from PyQt5.QtWidgets import QApplication

from main_controller import MainController
from custom_painted_item import CustomPaintedItem


def main():
    print('main()')

    qmlRegisterType(CustomPaintedItem, "CustomPaintedItem", 1, 0, "CustomPaintedItem")

    app = QApplication(sys.argv)
    engine = QQmlApplicationEngine()
    main_controller = MainController()
    context = engine.rootContext()
    context.setContextProperty("main", main_controller)
    script_directory = os.path.dirname(os.path.abspath(__file__))
    engine.load(os.path.join(script_directory, 'main.qml'))

    main_controller.start()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

而控制器main_controller.py 看起来像这样:

from PyQt5.QtCore import QObject, pyqtSlot


class MainController(QObject):
    def __init__(self):
        super().__init__()
        print('ctor')

    def start(self):
        print('start')

    @pyqtSlot()
    def close_application(self):
        print('close')

最后,custom_painted_item.py

from PyQt5.QtQuick import QQuickPaintedItem
from PyQt5.QtCore import QTimer


class CustomPaintedItem(QQuickPaintedItem):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        QTimer.singleShot(100, self.update)

    def paint(self, QPainter):
        QTimer.singleShot(100, self.update)

    def geometryChanged(self, old_geom, new_geom):
        print('OLD: {0} x {1}'.format(old_geom.width(), old_geom.height()))
        print('NEW: {0} x {1}'.format(new_geom.width(), new_geom.height()))

当这段代码运行时,我可以在 y 维度上调整窗口的大小(使其更高或更短)并查看高度是否按预期变化:

OLD: 520.0 x 455.0
NEW: 520.0 x 454.0
OLD: 520.0 x 454.0
NEW: 520.0 x 453.0

但是,当我在 x 维度上调整窗口的大小(使其更宽或更窄)时,报告的宽度不会从初始值 520 (窗口宽度 720 减去首选侧边栏宽度 200 )。事实上,当我调整宽度时,geometryChanged() 方法甚至都不会被调用。

如果你把Loader组件注释掉,直接用ColumnLayout组件替换,像这样:

//        Loader {
//            id: contentAreaLoader
//            Layout.fillHeight: true
//            Layout.preferredWidth: 520
//            Layout.minimumWidth: 300

//            source: 'loaded_content.qml'
//        }

        ColumnLayout {
            Layout.fillHeight: true
            Layout.preferredWidth: 520
            Layout.minimumWidth: 300

            Label {
                text: "Here's a thing!"
            }

            CustomPaintedItem {
                Layout.fillHeight: true
                Layout.fillWidth: true
            }
        }

然后geometryChanged() 方法被正确调用以调整 x 和 y 大小。我不知道这是一个错误,还是我不了解加载程序的问题,还是有关布局的问题。

如果重要的话,我使用的是 Python 3.6 和 PyQt 5.11.3。

谁能告诉我如何使用装载机进行这项工作?谢谢!

【问题讨论】:

    标签: python python-3.x pyqt qml pyqt5


    【解决方案1】:

    布局仅处理子级,在不使用加载器的情况下:ColumnLayout 占用可用空间,因为 maximumWidth 已建立,因此它将是无限的(所有可以等同于Layout.fillWidth: true)。另一方面,不是 Layout 的 Loader 没有该大小策略,因此如果您希望它占据所有可用空间,则必须明确使用 Layout.fillWidth: true

    Loader {
        id: contentAreaLoader
        Layout.fillHeight: true
        Layout.preferredWidth: 520
        Layout.minimumWidth: 300
        Layout.fillWidth: true // <----
        source: 'loaded_content.qml'
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-19
      • 2018-12-06
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 2017-08-28
      • 2011-12-08
      • 1970-01-01
      相关资源
      最近更新 更多