【问题标题】:PyQt Update Child Widget PropertyPyQt 更新子小部件属性
【发布时间】:2021-04-19 09:33:45
【问题描述】:

我想从主窗口更新另一个窗口中的 TextBrowser 小部件。目标是简单地将字符串写入小部件以充当伪控制台。当我检查 QTextBrowser 对象时,我可以看到它支持setText() - 但我找不到从主窗口对象访问setText() 的方法(我怀疑这是因为我没有正确调用它)。不需要使用 TextBrowser 小部件。

我见过的例子谈到了使用信号和槽来进行此类操作,但这对于我想要完成的事情来说似乎有点过头了。是否需要将信号用于如此简单的事情,或者我可以从主窗口以某种方式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_())

【问题讨论】:

    标签: pyqt


    【解决方案1】:

    由“表单类”(Ui_dialog)创建的所有对象都是该表单类实例的成员。

    如果您查看setupUi() 代码,您会发现所有小部件都是作为Ui_dialog 类实例(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“表单类”作为独立对象通常不是很方便,特别是如果您没有创建对 ui 的持久引用:在您的情况下,只要主窗口的__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 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_()
    

    如您所见,它的工作方式几乎相同,只是它更简单、简洁和易读。

    【讨论】:

    • 感谢您花时间发布如此完整而周到的答案。我应该考虑将窗口子类化。干杯!
    猜你喜欢
    • 1970-01-01
    • 2014-01-19
    • 2012-07-25
    • 2016-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    相关资源
    最近更新 更多