除非我调整大小,否则 QML 文本不会更新 window
QML text doesn't update unless I resize window
我有以下Python代码
import sys
import os
import threading
from time import sleep
from PySide2.QtCore import QObject
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
def add_text(log_text):
i = 1
while True:
text = log_text.property("text")
log_text.setProperty("text", text + "\n" + str(i))
i += 1
sleep(1)
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
root = engine.rootObjects()[0]
log_text = root.findChild(QObject, 'log_text')
x = threading.Thread(target=add_text, args=(log_text,))
x.start()
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
以及下面的QML文件
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.13
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
RowLayout {
id: main_row
anchors.fill: parent
spacing: 0
Rectangle {
id: log_background
width: 250
height: 480
color: "#515151"
Layout.fillHeight: true
Text {
id: log_text
objectName: "log_text"
color: "#ffffff"
anchors.fill: parent
font.pixelSize: 12
verticalAlignment: Text.AlignBottom
}
}
ColumnLayout {
id: image_buttons_column
width: 100
height: 100
spacing: 0
Image {
id: image
width: 504
height: 429
source: "qrc:/qtquickplugin/images/template_image.png"
Layout.fillHeight: true
Layout.fillWidth: true
cache: true
smooth: true
mirror: false
mipmap: false
autoTransform: false
asynchronous: false
fillMode: Image.PreserveAspectFit
}
RowLayout {
id: buttons_row
width: 100
height: 100
spacing: 0
Button {
id: button_yes
objectName: "button_yes"
Layout.fillWidth: true
palette {
button: "#64e764"
}
font.pointSize: 16
text: "Yes"
signal pressed
onClicked: pressed()
}
Button {
id: button_maybe
objectName: "button_maybe"
Layout.fillWidth: true
palette {
button: "#ffff00"
}
font.pointSize: 16
text: "Maybe"
signal pressed
onClicked: pressed()
}
Button {
id: button_no
objectName: "button_no"
Layout.fillWidth: true
palette {
button: "#ff726f"
}
font.pointSize: 16
text: "No"
signal pressed
onClicked: pressed()
}
}
}
}
}
当我 运行 上面的 python 脚本时,文本会自行更新一次,显示数字 1,然后停止。每当我调整 window 的大小时,所有应该添加的数字都会突然显示出来。如何让文本区域在文本更改时自动更新,而不是在 window 调整大小时更新?
您正试图从主线程以外的线程操作 Qt。这将不起作用,并且可能会导致崩溃。几乎所有的 GUI 工具包都只能从主线程进行操作。
在这种特殊情况下,我会在您的 QML 文件中使用 QML Timer
对象。它会在主线程上执行,达到同样的目的。像这样:
Text {
id: log_text
objectName: "log_text"
color: "#ffffff"
anchors.fill: parent
font.pixelSize: 12
verticalAlignment: Text.AlignBottom
Timer {
interval: 1000
running: true
repeat: true
property int i: 1
onTriggered: {
log_text.text += `\n${i}`;
i += 1;
}
}
}
如果由于某些其他原因必须在单独的线程中完成此操作,您将需要从该线程调用主线程上的处理程序以通过信号实际操作 Qt。 Qt 信号机制检测信号何时跨线程并在其事件队列中正确调度接收端的信号。
我有以下Python代码
import sys
import os
import threading
from time import sleep
from PySide2.QtCore import QObject
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
def add_text(log_text):
i = 1
while True:
text = log_text.property("text")
log_text.setProperty("text", text + "\n" + str(i))
i += 1
sleep(1)
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
root = engine.rootObjects()[0]
log_text = root.findChild(QObject, 'log_text')
x = threading.Thread(target=add_text, args=(log_text,))
x.start()
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
以及下面的QML文件
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.13
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
RowLayout {
id: main_row
anchors.fill: parent
spacing: 0
Rectangle {
id: log_background
width: 250
height: 480
color: "#515151"
Layout.fillHeight: true
Text {
id: log_text
objectName: "log_text"
color: "#ffffff"
anchors.fill: parent
font.pixelSize: 12
verticalAlignment: Text.AlignBottom
}
}
ColumnLayout {
id: image_buttons_column
width: 100
height: 100
spacing: 0
Image {
id: image
width: 504
height: 429
source: "qrc:/qtquickplugin/images/template_image.png"
Layout.fillHeight: true
Layout.fillWidth: true
cache: true
smooth: true
mirror: false
mipmap: false
autoTransform: false
asynchronous: false
fillMode: Image.PreserveAspectFit
}
RowLayout {
id: buttons_row
width: 100
height: 100
spacing: 0
Button {
id: button_yes
objectName: "button_yes"
Layout.fillWidth: true
palette {
button: "#64e764"
}
font.pointSize: 16
text: "Yes"
signal pressed
onClicked: pressed()
}
Button {
id: button_maybe
objectName: "button_maybe"
Layout.fillWidth: true
palette {
button: "#ffff00"
}
font.pointSize: 16
text: "Maybe"
signal pressed
onClicked: pressed()
}
Button {
id: button_no
objectName: "button_no"
Layout.fillWidth: true
palette {
button: "#ff726f"
}
font.pointSize: 16
text: "No"
signal pressed
onClicked: pressed()
}
}
}
}
}
当我 运行 上面的 python 脚本时,文本会自行更新一次,显示数字 1,然后停止。每当我调整 window 的大小时,所有应该添加的数字都会突然显示出来。如何让文本区域在文本更改时自动更新,而不是在 window 调整大小时更新?
您正试图从主线程以外的线程操作 Qt。这将不起作用,并且可能会导致崩溃。几乎所有的 GUI 工具包都只能从主线程进行操作。
在这种特殊情况下,我会在您的 QML 文件中使用 QML Timer
对象。它会在主线程上执行,达到同样的目的。像这样:
Text {
id: log_text
objectName: "log_text"
color: "#ffffff"
anchors.fill: parent
font.pixelSize: 12
verticalAlignment: Text.AlignBottom
Timer {
interval: 1000
running: true
repeat: true
property int i: 1
onTriggered: {
log_text.text += `\n${i}`;
i += 1;
}
}
}
如果由于某些其他原因必须在单独的线程中完成此操作,您将需要从该线程调用主线程上的处理程序以通过信号实际操作 Qt。 Qt 信号机制检测信号何时跨线程并在其事件队列中正确调度接收端的信号。