跨多个 windows 访问项目和属性

Access items and attributes across multiple windows

我有一个主 GUI-Window,我通过单击按钮从中打开一个新的 Window(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()

在 Window 中,我有一个 QTable 可以填写,还有一个按钮可以提交数据并关闭 window:

    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]))

主要window中的接收函数如下所示:

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

现在我只想了解如何禁用主window 或打开第二个window 的按钮。在 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'

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

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

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

访问另一个实例的属性

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

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

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'

提供参考

简单的解决方案是创建第一个实例的引用 window for 第二个实例:

   def enter_fct_results(self):
        self.FCTpopup = FCT_Window(<b>self</b>)
        self.FCTpopup.show()

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

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

使用模态windows(又名,对话框)

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

   def enter_fct_results(self):
        self.FCTpopup = FCT_Window(<b>self</b>)
        <b>self.FCTpopup.exec_()</b>

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

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

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

我终于找到了我的错误:是信号连接的地方。它必须在第二个 window 打开之前:

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

现在我可以将存储的数据从 mainwindow 发送到打开的 window,导入到 table,对其进行编辑并将其发送回 mainwindow 提交。