PyQt 更新子控件 属性
PyQt Update Child Widget Property
我想更新主 window 中另一个 window 中的 TextBrowser 小部件。目标是简单地将字符串写入小部件以充当伪控制台。当我检查 QTextBrowser 对象时,我可以看到它支持 setText()
- 但我找不到从主 window 对象访问 setText()
的方法(我怀疑是因为我'没有正确调用它)。不需要使用 TextBrowser 小部件。
我看到的示例讨论了使用信号和槽进行此类操作,但对于我要实现的目标来说,这似乎有点过头了。是否需要为如此简单的事情使用信号,或者我可以从主要 window 以某种方式 setText()
(或类似的东西)?
scratch.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
import sys
from log_dialog import Ui_dialog
class Application(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(Application, self).__init__(*args, **kwargs)
self.show()
# ===================================================
self.log_widget = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(self.log_widget)
self.log_widget.exec_()
# Write some text to log_widget <-----
# ===================================================
qApp = QtWidgets.QApplication(sys.argv)
application_window = Application()
sys.exit(qApp.exec_())
log_dialog.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'log_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.3
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dialog(object):
def setupUi(self, dialog):
dialog.setObjectName("dialog")
dialog.resize(398, 307)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(dialog.sizePolicy().hasHeightForWidth())
dialog.setSizePolicy(sizePolicy)
self.textBrowser = QtWidgets.QTextBrowser(dialog)
self.textBrowser.setGeometry(QtCore.QRect(9, 9, 381, 291))
self.textBrowser.setObjectName("textBrowser")
self.retranslateUi(dialog)
QtCore.QMetaObject.connectSlotsByName(dialog)
def retranslateUi(self, dialog):
_translate = QtCore.QCoreApplication.translate
dialog.setWindowTitle(_translate("dialog", "Log"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(dialog)
dialog.show()
sys.exit(app.exec_())
“表单 class”(Ui_dialog
)创建的所有对象都是该表单 class 实例的成员。
如果您查看 setupUi()
代码,您会发现所有小部件都是作为 Ui_dialog
class 实例(self.textBrowser
等)的成员创建的.
由于 ui
是实例,因此 self.someObject
可作为 ui.someObject
.
访问
ui = Ui_dialog()
ui.setupUi(self.log_widget)
ui.textBrowser.setText('Hello there!')
self.log_widget.exec_()
对于非常简单的情况,这可能没问题,但是使用 ui“形式 class”作为独立对象通常不是很方便,特别是如果您没有创建持久引用到ui:在你的情况下,一旦主windowreturns的__init__
(当对话框关闭时),你将没有更多的参考到 ui
,因为它只是一个仅存在于 __init__
.
范围内的未引用变量
尽管如此,您仍然可以访问该对话框并再次执行它,访问其任何子项的唯一方法是通过:
self.log_widget.findChild(QtWidgets.QTextBrowser, 'textBrowser')
不太方便吧?
一种可能性是使 ui 成为对话实例的成员:
self.log_widget.ui = Ui_dialog()
self.log_widget.ui.setupUi(self.log_widget)
self.log_widget.ui.textBrowser.setText('Hello there!')
更好,但不是很好:它只有 3 个字符,但它确实没有提供很多好处。此外,拥有 self.log_widget
的直接子对象但只能通过 self.log_widget.ui
.
访问的对象确实没有多大意义
更常见和推荐的方法是多重继承方法,它允许始终直接访问对象。唯一的缺点是,即使对于简单的小部件和对话框,您总是需要创建子class。
class LogWidget(QtWidgets.QDialog, Ui_dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
class Application(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(Application, self).__init__(*args, **kwargs)
# ...
self.log_widget = LogWidget()
self.log_widget.textBrowser.setText('hello there!')
self.log_widget.exec_()
如您所见,它的工作方式几乎相同,只是它更简单、简洁和可读。
我想更新主 window 中另一个 window 中的 TextBrowser 小部件。目标是简单地将字符串写入小部件以充当伪控制台。当我检查 QTextBrowser 对象时,我可以看到它支持 setText()
- 但我找不到从主 window 对象访问 setText()
的方法(我怀疑是因为我'没有正确调用它)。不需要使用 TextBrowser 小部件。
我看到的示例讨论了使用信号和槽进行此类操作,但对于我要实现的目标来说,这似乎有点过头了。是否需要为如此简单的事情使用信号,或者我可以从主要 window 以某种方式 setText()
(或类似的东西)?
scratch.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
import sys
from log_dialog import Ui_dialog
class Application(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(Application, self).__init__(*args, **kwargs)
self.show()
# ===================================================
self.log_widget = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(self.log_widget)
self.log_widget.exec_()
# Write some text to log_widget <-----
# ===================================================
qApp = QtWidgets.QApplication(sys.argv)
application_window = Application()
sys.exit(qApp.exec_())
log_dialog.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'log_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.3
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dialog(object):
def setupUi(self, dialog):
dialog.setObjectName("dialog")
dialog.resize(398, 307)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(dialog.sizePolicy().hasHeightForWidth())
dialog.setSizePolicy(sizePolicy)
self.textBrowser = QtWidgets.QTextBrowser(dialog)
self.textBrowser.setGeometry(QtCore.QRect(9, 9, 381, 291))
self.textBrowser.setObjectName("textBrowser")
self.retranslateUi(dialog)
QtCore.QMetaObject.connectSlotsByName(dialog)
def retranslateUi(self, dialog):
_translate = QtCore.QCoreApplication.translate
dialog.setWindowTitle(_translate("dialog", "Log"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog()
ui = Ui_dialog()
ui.setupUi(dialog)
dialog.show()
sys.exit(app.exec_())
“表单 class”(Ui_dialog
)创建的所有对象都是该表单 class 实例的成员。
如果您查看 setupUi()
代码,您会发现所有小部件都是作为 Ui_dialog
class 实例(self.textBrowser
等)的成员创建的.
由于 ui
是实例,因此 self.someObject
可作为 ui.someObject
.
ui = Ui_dialog()
ui.setupUi(self.log_widget)
ui.textBrowser.setText('Hello there!')
self.log_widget.exec_()
对于非常简单的情况,这可能没问题,但是使用 ui“形式 class”作为独立对象通常不是很方便,特别是如果您没有创建持久引用到ui:在你的情况下,一旦主windowreturns的__init__
(当对话框关闭时),你将没有更多的参考到 ui
,因为它只是一个仅存在于 __init__
.
范围内的未引用变量
尽管如此,您仍然可以访问该对话框并再次执行它,访问其任何子项的唯一方法是通过:
self.log_widget.findChild(QtWidgets.QTextBrowser, 'textBrowser')
不太方便吧?
一种可能性是使 ui 成为对话实例的成员:
self.log_widget.ui = Ui_dialog()
self.log_widget.ui.setupUi(self.log_widget)
self.log_widget.ui.textBrowser.setText('Hello there!')
更好,但不是很好:它只有 3 个字符,但它确实没有提供很多好处。此外,拥有 self.log_widget
的直接子对象但只能通过 self.log_widget.ui
.
更常见和推荐的方法是多重继承方法,它允许始终直接访问对象。唯一的缺点是,即使对于简单的小部件和对话框,您总是需要创建子class。
class LogWidget(QtWidgets.QDialog, Ui_dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
class Application(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(Application, self).__init__(*args, **kwargs)
# ...
self.log_widget = LogWidget()
self.log_widget.textBrowser.setText('hello there!')
self.log_widget.exec_()
如您所见,它的工作方式几乎相同,只是它更简单、简洁和可读。