跨多个 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 提交。
我有一个主 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 提交。