跨多个窗口访问项目和属性

Posted

技术标签:

【中文标题】跨多个窗口访问项目和属性【英文标题】:Access items and attributes across multiple windows 【发布时间】:2021-01-20 15:42:55 【问题描述】:

我有一个主 GUI 窗口,我可以通过单击按钮打开一个新窗口(FCT 弹出窗口):

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()  # sets ui = to the main window from the ui-file
        self.ui.setupUi(self)
        [...]
    def enter_fct_results(self):
        self.FCTpopup = FCT_Window()
        self.FCTpopup.show()

在窗口中,我有一个要填写的 QTable 和一个提交数据并关闭窗口的按钮:

    class FCT_Window(QMainWindow):
    
     def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_FCT_Window()
        self.ui.setupUi(self)
        [...]

        self.ui.pushButton_submitFCT.clicked.connect(lambda: MainWindow.store_fct_data(MainWindow, self.on_submit()[0]))

     def on_submit(self):  # event when user clicks
                  fct_nparray = np.zeros((self.ui.tableFCTinputs.rowCount(), self.ui.tableFCTinputs.columnCount()))
                      for j in range(self.ui.tableFCTinputs.columnCount()):
                            for i in range(self.ui.tableFCTinputs.rowCount()):
                                fct_nparray[i, j] = float(self.ui.tableFCTinputs.item(i, j).text())
                  return  fct_nparray, lambda: self.close()
    
    self.ui.pushButton_submitFCT.clicked.connect(lambda: MainWindow.store_fct_data(MainWindow, self.on_submit()[0]))

主窗口中的接收函数如下所示:

def store_fct_data(self, data):
    self.fct_data = data

现在我只想了解如何禁用主窗口或打开第二个窗口的按钮。在 enter_fct_results() 中禁用是可行的,但是如果我想使用 store_fct_data 或 on_submit 再次启用它,则会提供如下错误:

self.ui.pushButton_FCTresults.setEnabled(1)
self.ui.pushButton_submitFCT.clicked.connect(lambda: MainWindow.store_fct_data(MainWindow, self.on_submit()[0]))
AttributeError: type object 'MainWindow' has no attribute 'ui'

我不认为我在这里理解如何处理多个窗口和东西。例如,我将如何通过使用 window2 中的按钮来更改主窗口中按钮的颜色。我如何访问小部件?如果我在同一个窗口内,我很容易做到这一点

self.ui.pushbutton.setText("New Text")

我不知道如何跨 Windows 访问项目和属性:(你能帮帮我吗?

【问题讨论】:

请提供minimal reproducible example 【参考方案1】:

访问另一个实例的属性

enter_fct_results 中禁用第二个窗口的按钮与您在 lambda 中尝试的操作之间存在根本区别:在第一种情况下,您访问的是 instance 属性(例如, self.FCTpopup.ui.pushButton),而在第二次你试图访问 class 属性。

self.ui 对象是在__init__ 中创建的(当类实例创建时),所以instance 将有一个ui 属性,不是班级:

class Test:
    def __init__(self):
        self.value = True

test = Test()
print(test.value)

>>> True

print(Test.value)

>>> AttributeError: type object 'Test' has no attribute 'value'

提供一个参考

简单的解决方案是为第二个窗口创建第一个窗口实例的引用:

   def enter_fct_results(self):
        self.FCTpopup = FCT_Window(self)
        self.FCTpopup.show()

class FCT_Window(QMainWindow):
    def __init__(self, mainWindow):
        QMainWindow.__init__(self)
        self.mainWindow = mainWindow
        self.ui.pushButton_submitFCT.clicked.connect(self.doSomething)

    def doSomething(self):
        # ...
        self.mainWindow.ui.pushButton.setEnabled(True)

使用模态窗口(又名对话框)

当某些临时交互(数据输入、文档预览等)需要窗口时,首选对话框:使用对话框的主要好处是它们对父级模态,防止在该父级上进行交互,直到对话框关闭;另一个好处是(至少在 Qt 上)它们在 exec() 函数中还有一个 blocking 事件循环,只有在对话框关闭后才会返回。这两个方面也使得不必要地禁用父窗口中的任何按钮。另一个重要的原因是 QMainWindow 不适合这种操作,也因为它具有通常不需要的功能(工具栏、状态栏、菜单等)。

   def enter_fct_results(self):
        self.FCTpopup = FCT_Window(self)
        self.FCTpopup.exec_()

class FCT_Window(QDialog):
    def __init__(self, parent):
        QMainWindow.__init__(self, parent)
        self.ui.pushButton_submitFCT.clicked.connect(self.doSomething)

    def doSomething(self):
        # ...
        self.accept()

以上要求强制使用 QDialog(而不是 QMainWindow)在设计器中重新创建 ui。您可以创建一个新的并从原始的拖放小部件。

【讨论】:

【参考方案2】:

我终于发现了我的错误:这是信号连接的地方。它必须在第二个窗口打开之前:

def enter_fct_results(self):
    self.FCTpopup = Dialog(self.fct_data)
    self.FCTpopup.submitted.connect(self.store_fct_data)
    self.FCTpopup.exec_()

现在我可以将存储的数据从主窗口发送到打开的窗口,导入表格,编辑并在提交时将其发送回主窗口。

【讨论】:

以上是关于跨多个窗口访问项目和属性的主要内容,如果未能解决你的问题,请参考以下文章

WPF中窗口控件的跨线程调用

tomcat跑多个项目和不同端口访问项目

是否可以跨多个项目共享角度组件?

使用服务帐户进行跨项目管理

是否可以设置一个跨多个 ASP.NET MVC 项目使用的基础项目?

跨多个应用程序共享存储过程