python - 从 QML 到 Python Signal/Slots 的数据
问题描述
我试图弄清楚如何将数据从 TextField 输入传递到我的 Python 类。我认为解决这个问题的方法是使用信号和插槽;但是,我在传递数据的 widget.qml(主 qml 类)中使用了自定义 QML 组件。我需要这样做,以便可以对通过 TextField 传入的数据执行更复杂的操作。
我对如何将数据从我的 BasicContainer.qml 传递到我的 python 类感到困惑,并且不确定我的 widget.qml 类中的逻辑是否甚至支持它,因为它使用嵌套模型。我附上了一个例子,希望能用控制流来说明问题。我可以在我添加的 widget.qml 中使用基本信号,但如果我在 BasicContainer.qml 中做同样的事情,我会得到一个PySide6.QtQuick.QQuickItem object has no attribute 'displayValueChanged'
主文件
import os
import sys
from pathlib import Path
sys.path.append(os.path.join(os.path.dirname(sys.path[0]), ".."))
from PySide6.QtCore import Property, QUrl, QObject, Qt, QCoreApplication, Slot
from PySide6.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide6.QtQuick import QQuickView
CURRENT_DIRECTORY = Path(__file__).resolve().parent
# QstandardItem roles
SetText = Qt.UserRole + 1
class ControlledSignalWidget(QObject):
def __init__(self):
super().__init__()
self._model = QStandardItemModel()
# self._model.setItemRoleNames({Qt.DisplayRole: b"display"})
self._setpoints_models = []
@Property(QObject, constant=True)
def model(self):
return self._model
@Slot(int, result=QObject)
def setpoints(self, idx):
return self._setpoints_models[idx]
# create custom number of widgets
def create_widgets(self, widgets, allComponents):
counter = 1
# Iterates for the amount of widgets created
for general, widget in widgets.items():
# for key in widget:
print("Adding new widget")
item = QStandardItem(widget["Header"])
self._model.appendRow(item)
self.create_setpoints(allComponents["item" + str(counter) + "Components"])
print("Added widget")
counter += 1
def create_setpoints(self, component):
setpoints_model = QStandardItemModel()
setpoints_model.setItemRoleNames({SetText: b"textField"})
for subWidget in component:
print(subWidget)
item = QStandardItem()
item.setData(subWidget["title"], SetText)
setpoints_model.appendRow(item)
self._setpoints_models.append(setpoints_model)
def display(s):
print(s)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeViewToRootObject)
url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "widget.qml"))
def handle_status_changed(status):
if status == QQuickView.Error:
QCoreApplication.exit(-1)
widgets = {
"widget1": {"Header": "Header Text"},
"widget2": {"Header": "Header 2 Text"},
}
item1Components = [{"title": "widget1random"}, {"title": "widget1random2"}]
item2Components = [{"title": "widget2random"}, {"title": "widget2random2"}]
allComponents = {
"item1Components": item1Components,
"item2Components": item2Components,
}
mainWidget = ControlledSignalWidget()
mainWidget.create_widgets(widgets, allComponents)
view.rootContext().setContextProperty("mainWidget", mainWidget)
view.statusChanged.connect(
handle_status_changed, Qt.ConnectionType.QueuedConnection
)
view.setSource(url)
# SIGNAL CONNECTION MADE
root = view.rootObject()
root.displayValueChanged.connect(display)
view.show()
sys.exit(app.exec())
小部件.qml
import QtQuick 2.0
import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.12
Item {
id: root
width: 1000
height: 800
signal displayValueChanged(string setpoint)
GridLayout{
columns: 3
Repeater{
id: repeater1
model: mainWidget.model
ColumnLayout{
property int outerIndex: index
Repeater{
id: repeater2
model: mainWidget.setpoints(outerIndex)
ColumnLayout{
BasicContainer{
Component.onCompleted: {
//Signal called
displayValueChanged(inputText)
}
}
}
}
}
}
}
}
基本容器.qml
import QtQuick 2.12
import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.12
Item {
id: basicContainerItem
width: 300
height: 60
visible: true
signal valueChanged()
property alias inputText: containerInput.text
Rectangle {
id: rectangle
width: parent.width
ColumnLayout {
TextField {
id: containerInput
visible: true
placeholderText: qsTr("Text Field")
text: "Default value"
// Contended line
//textColor: "#FF3333"
onAccepted: {
console.log(text)
basicContainerItem.valueChanged()
}
}
}
}
}
重要编辑:
我修改了代码以使用信号将值从 BasicContainer 类一直传递到 Python,因此当您进行文本输入并按 Enter 时,将记录您输入的新文本。这应该解决了一切;但是,当我尝试进行任何样式更改(例如 BasicContainer.qml: 中的文本颜色更改行)时,textColor: "#FF3333"
将导致我的应用程序中断,从而导致此错误:
root.displayValueChanged.connect(display) AttributeError 'Nonetype' object has no attribute 'displayValueChanged'
解决方案
没关系,似乎正确的解决方案就是我上面所说的;期待我使用 textColor 的部分,因为显然这应该是color
而不是textColor
。但是,信号按预期工作,这是我对这个问题的目标。
推荐阅读
- javascript - 无论如何我可以使用 Yup.js 来验证排序数组吗?
- modelica - 查找我在dymola中构建的模型中的函数用法
- c++ - 我的 sumASCII 函数中的这个偏移量是多少?
- ios - 坚持通过 FetchedResultsController、Diffable Data Sources 和 CollectionView 添加搜索
- php - 图像分页 - 如何在一个查询中获取所有参数
- jasper-reports - JasperReports 和 Microsoft Word - 对齐文本对齐
- php - 您如何为不同的用户角色设置权限/视图/路由?
- bash - 如何通过脚本通过 ssh 查看远程 shell 中的日志并按 ctrl + C 停留在那里
- service - 如何停止报告 systemctl 单元的 FAILED
- python - 具有多个条件的 Pandas 函数 - 值错误