单击一个按钮并更改 MainWindow
Click a button and change MainWindow
我正在学习 Qt,我对如何更改 MainWindow 的某些功能很感兴趣。
我正在尝试这段代码,但是当我点击第一个按钮时出现了一些错误:
Traceback (most recent call last):
File "\main.py", line 15, in run_the_first_button_was_clicked
the_first_button_was_clicked(self)
File "clickedButton.py", line 15, in the_first_button_was_clicked
self.button2.clicked.connect(self.the_second_button_was_clicked)
AttributeError: 'MainWindow' object has no attribute 'the_second_button_was_clicked'
我做错了什么(我怎么能做到'the_second_button_was_clicked'可调用)?
main.py
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton
import sys
from clickedButton import the_first_button_was_clicked, the_second_button_was_clicked
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("MainWindow")
self.button1 = QPushButton("button1")
self.button1.clicked.connect(self.run_the_first_button_was_clicked)
self.setCentralWidget(self.button1)
def run_the_first_button_was_clicked(self):
the_first_button_was_clicked(self)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
clickedButton.py
from PySide2.QtWidgets import QPushButton
from PySide2 import QtCore
def the_first_button_was_clicked(self):
self.setWindowTitle("the_first_button_was_clicked next will be the_second_button_was_clicked")
self.resize(800, 600)
self.button1.setText("the_first_button_was_clicked")
self.button1.setEnabled(False)
self.button2 = QPushButton("button2")
self.button2.setGeometry(QtCore.QRect(100, 100, 150, 150))
self.button2.setVisible(True)
self.button2.clicked.connect(self.the_second_button_was_clicked)
def the_second_button_was_clicked(self):
self.setWindowTitle("the_second_button_was_clicked")
self.resize(600, 800)
此问题与 PyQt 无关,但与 classes 和实例的工作方式有关。
实例方法的第一个参数总是引用class的实例,它被称为self
只是为了约定:它实际上可能是以任何方式命名,只要其语法有效,就像任何其他变量一样。
当使用在外部 a class声明的函数时,最好避免这种命名约定(主要是为了避免在阅读代码时造成混淆)。
发生的事情是 def the_first_button_was_clicked(self):
中的 self
引用 MainWindow
的实例,它没有 the_second_button_was_clicked
方法,因此出现 AttributeError 异常。
重点是你的两个函数只是函数,而不是方法(它们是实例或class): 他们 不是 class.
的成员
另请注意,创建与函数的直接连接将不起作用,因为 self
参数仅在函数是方法时才“创建”。
正如 Heike 在评论中指出的那样,一种可能性是使用 lambda
,它允许保留对实例的实际引用,同时直接调用将使用提供的 self
参数执行的函数,恰好正如您在 run_the_first_button_was_clicked
.
中所做的那样
在下面的示例中,我将 self
替换为 mainWinInstance
以使事情更清楚(这就是在这些情况下不应使用 self
的原因).
def the_first_button_was_clicked(mainWinInstance):
# we reference the function locally to this script, adding the "self" argument
mainWinInstance.button2.clicked.connect(lambda:
the_second_button_was_clicked(<b>mainWinInstance</b>))
def the_second_button_was_clicked(mainWinInstance):
# "self" (mainWinInstance) was manually added to the function arguments
mainWinInstance.setWindowTitle("the_second_button_was_clicked")
mainWinInstance.resize(600, 800)
另一种可能性是使第二个函数成为实例的成员:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# ...
<b>self.the_second_button_was_clicked = the_second_button_was_clicked</b>
或:
def the_first_button_was_clicked(mainWinInstance):
# ...
<b>mainWinInstance.the_second_button_was_clicked = the_second_button_was_clicked</b>
mainWinInstance.button2.clicked.connect(mainWinInstance.the_second_button_was_clicked)
在两种情况下,必须在连接之前创建实例属性(这也意味着在第一个调用第一个函数之前例)。
考虑到这种“猴子修补”方法只应在特殊情况下使用(主要是由于对象无法被子class编辑,因为是自主创建的),尤其是在 class 之外完成的情况下甚至脚本。
在大多数情况下,您所做的事情被认为是不好的做法,如果您使用自己创建的 class 进行此操作,则可能您的实施确实有问题:您最好重新考虑您的逻辑并在 class 本身内实施所有内容。
我正在学习 Qt,我对如何更改 MainWindow 的某些功能很感兴趣。
我正在尝试这段代码,但是当我点击第一个按钮时出现了一些错误:
Traceback (most recent call last):
File "\main.py", line 15, in run_the_first_button_was_clicked
the_first_button_was_clicked(self)
File "clickedButton.py", line 15, in the_first_button_was_clicked
self.button2.clicked.connect(self.the_second_button_was_clicked)
AttributeError: 'MainWindow' object has no attribute 'the_second_button_was_clicked'
我做错了什么(我怎么能做到'the_second_button_was_clicked'可调用)?
main.py
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton
import sys
from clickedButton import the_first_button_was_clicked, the_second_button_was_clicked
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("MainWindow")
self.button1 = QPushButton("button1")
self.button1.clicked.connect(self.run_the_first_button_was_clicked)
self.setCentralWidget(self.button1)
def run_the_first_button_was_clicked(self):
the_first_button_was_clicked(self)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
clickedButton.py
from PySide2.QtWidgets import QPushButton
from PySide2 import QtCore
def the_first_button_was_clicked(self):
self.setWindowTitle("the_first_button_was_clicked next will be the_second_button_was_clicked")
self.resize(800, 600)
self.button1.setText("the_first_button_was_clicked")
self.button1.setEnabled(False)
self.button2 = QPushButton("button2")
self.button2.setGeometry(QtCore.QRect(100, 100, 150, 150))
self.button2.setVisible(True)
self.button2.clicked.connect(self.the_second_button_was_clicked)
def the_second_button_was_clicked(self):
self.setWindowTitle("the_second_button_was_clicked")
self.resize(600, 800)
此问题与 PyQt 无关,但与 classes 和实例的工作方式有关。
实例方法的第一个参数总是引用class的实例,它被称为self
只是为了约定:它实际上可能是以任何方式命名,只要其语法有效,就像任何其他变量一样。
当使用在外部 a class声明的函数时,最好避免这种命名约定(主要是为了避免在阅读代码时造成混淆)。
发生的事情是 def the_first_button_was_clicked(self):
中的 self
引用 MainWindow
的实例,它没有 the_second_button_was_clicked
方法,因此出现 AttributeError 异常。
重点是你的两个函数只是函数,而不是方法(它们是实例或class): 他们 不是 class.
的成员另请注意,创建与函数的直接连接将不起作用,因为 self
参数仅在函数是方法时才“创建”。
正如 Heike 在评论中指出的那样,一种可能性是使用 lambda
,它允许保留对实例的实际引用,同时直接调用将使用提供的 self
参数执行的函数,恰好正如您在 run_the_first_button_was_clicked
.
在下面的示例中,我将 self
替换为 mainWinInstance
以使事情更清楚(这就是在这些情况下不应使用 self
的原因).
def the_first_button_was_clicked(mainWinInstance):
# we reference the function locally to this script, adding the "self" argument
mainWinInstance.button2.clicked.connect(lambda:
the_second_button_was_clicked(<b>mainWinInstance</b>))
def the_second_button_was_clicked(mainWinInstance):
# "self" (mainWinInstance) was manually added to the function arguments
mainWinInstance.setWindowTitle("the_second_button_was_clicked")
mainWinInstance.resize(600, 800)
另一种可能性是使第二个函数成为实例的成员:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# ...
<b>self.the_second_button_was_clicked = the_second_button_was_clicked</b>
或:
def the_first_button_was_clicked(mainWinInstance):
# ...
<b>mainWinInstance.the_second_button_was_clicked = the_second_button_was_clicked</b>
mainWinInstance.button2.clicked.connect(mainWinInstance.the_second_button_was_clicked)
在两种情况下,必须在连接之前创建实例属性(这也意味着在第一个调用第一个函数之前例)。
考虑到这种“猴子修补”方法只应在特殊情况下使用(主要是由于对象无法被子class编辑,因为是自主创建的),尤其是在 class 之外完成的情况下甚至脚本。
在大多数情况下,您所做的事情被认为是不好的做法,如果您使用自己创建的 class 进行此操作,则可能您的实施确实有问题:您最好重新考虑您的逻辑并在 class 本身内实施所有内容。