【发布时间】: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