Я работаю над созданием приложения Python + QtQuick, для которого требуется класс, начинающийся с QQuickPaintedItem .У меня возникли проблемы с управлением макетом и размером окрашенного предмета.
В частности, у меня есть приложение, которое выглядит так:
Слева находится набор кнопок, а в правой части окна находится Загрузчик (есть веская причина для этого, это лишь минимальный пример, демонстрирующий проблему).
Основной файл 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, один для основного, один для класса 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.
Кто-нибудь может дать мне некоторое представление о том, как заставить эту работу работать с загрузчиком?Спасибо!