Python 在PyQT中,为什么有些小部件需要;“自我”;参数,而其他参数不调用';T

Python 在PyQT中,为什么有些小部件需要;“自我”;参数,而其他参数不调用';T,python,class,oop,pyqt,self,Python,Class,Oop,Pyqt,Self,我对一些小部件使用“self”参数有点困惑,比如(QLineEdit),事实上,在学习使用QLabel小部件时,我曾经在没有self参数的情况下调用类,或者在使用QLineEdit小部件时,如果没有“self”参数,小部件将无法工作,下面是我正在处理的代码: # Import necessary modules import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton

我对一些小部件使用“self”参数有点困惑,比如(QLineEdit),事实上,在学习使用QLabel小部件时,我曾经在没有self参数的情况下调用类,或者在使用QLineEdit小部件时,如果没有“self”参数,小部件将无法工作,下面是我正在处理的代码:

# Import necessary modules
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton
from PyQt5.QtCore import Qt

class EntryWindow(QWidget): # Inherits QWidget

def __init__(self): # Constructor
    super().__init__() # Initializer which calls constructor for QWidget

    self.initializeUI() # Call function used to set up window

def initializeUI(self):
    """
    Initialize the window and display its contents to the screen
    """
    self.setGeometry(400, 300, 400, 200)
    self.setWindowTitle('QLineEdit Widget')
    self.displayWidgets()

    self.show() # Show everything

def displayWidgets(self):
    '''
    Setup the QLineEdit and other widgets.
    '''
    # Create name label and line edit widgets
    QLabel("Please enter your name below.", self).move(100, 20)
    name_label = QLabel("Name:", self)
    name_label.move(55, 70)

    self.name_entry = QLineEdit(self)
    self.name_entry.move(120, 68)
    self.name_entry.resize(200, 25) # Change size of entry field

    self.name_entry.setAlignment(Qt.AlignLeft) # The default alignment

    
    text_font = self.name_entry.font() # Get font option from the Qlineedit
    text_font.setPointSize(12)         # Modify font size
    #text_font.setBold(True)           # Bold
    self.name_entry.setFont(text_font) # Apply font
    

    self.clear_button = QPushButton('Clear text', self)
    self.clear_button.clicked.connect(self.clearEntries)
    self.clear_button.move(120, 130)

    self.exit_button = QPushButton("Exit", self)
    self.exit_button.clicked.connect(self.exitApplication)
    self.exit_button.move(240, 130)

def clearEntries(self):
    
    sender = self.sender()
    if sender.text() == 'Clear text':
        self.name_entry.clear()

def exitApplication(self):

    sender = self.sender()
    if sender.text() == "Exit":
        self.close() # Close the window

   # Run program
   if __name__ == '__main__':
       app = QApplication(sys.argv)
       window = EntryWindow()
       sys.exit(app.exec_())
所以这里是我困惑的地方,当使用QLabel时,我不必在前面输入“self”参数,或者当使用QLineEdit时,我必须输入“self”,否则我的代码将无法工作:

QLabel("Please enter your name below.", self).move(100, 20)
self.name_entry = QLineEdit(self)

注意顶部的导入语句

from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton
QLabel和QLineEdit可以在文档中看到


两者都将
QWidget
作为参数。作为第二个参数传递的
self
表示当前的
QWidget
类型。对于类中的其他方法,
self
用于调用实例方法。

self名称是一种Python约定,用于指示对象的实例。当在对象构造函数中设置为参数时,它通常用于为新对象提供对创建它的对象的引用,这通常称为“父对象”。请注意,虽然
self
通常用作父参数,但您可以将任何QWidget实例设置为父参数

在Qt术语中,它不仅表示对象结构的“父关系”中的角色,而且还导致两个重要方面:

  • 在QObject(QWidget继承自QObject)的世界中,这有助于内存管理:当父对象被删除时,其所有子对象也被删除。查找子对象(使用
    findChild()
    findChildren()
    )也很有用,这些子对象是另一个对象的直系子对象或[曾孙])
  • 当使用QWidget父项创建小部件时,该小部件也仅“绘制在”它的内部:它只能在父项的边界内可见,而不能在父项的外部可见;请注意,这通常是可选的,因为大多数情况下,您会将小部件添加到布局管理器(但您没有),布局管理器会自动将小部件重新分配到由该布局管理的小部件:如果它是另一个小部件的子部件,则会将其从该小部件中删除并添加到新的小部件中。还可以考虑,如果一个控件没有父类,并且没有被添加到一个布局中,它被认为是一个“顶级小部件”(一个独立的窗口),并且如果“代码>显示())<代码>或“代码> SETABLE(true)被称为它将拥有它自己的窗口。” 这意味着,如果小部件有父部件,并且父部件变为可见,则子部件也将自动可见(除非显式调用了
    hide()
    setVisible()
请注意,虽然没有父窗口的QWidget始终是顶级窗口,但有父窗口的widger可以是顶级窗口,如果它设置了
QtCore.Qt.window
标志(使用构造函数中的
f
关键字,或使用
setWindowFlags()
),则会发生这种情况。当小部件必须是顶级窗口时,这非常有用,但父级关系仍然必须保留,不仅用于内存管理(当父级窗口关闭并删除时,任何子级也应删除),而且用于交互目的:例如,对于QDialogs(独立窗口),设置父级很重要,因此,它们可以是该父级的模态,这意味着在对话框关闭之前,不能在父级上进行键盘/鼠标交互

最后,重要的是要记住,在python中“动态”创建小部件有一个结果(有时被认为是不连贯的):如果没有python引用小部件,但小部件有一个父级,它将不会被垃圾收集

考虑以下几点:

def test1(self):
    someDialog = QtWidgets.QDialog()
    someDialog.show()
这可能会在一瞬间显示一个窗口,然后它会立即消失

def test2(self):
    someDialog = QtWidgets.QDialog(self)
    someDialog.show()
在这种情况下,对话框不会消失,这是因为它有一个父级,PyQt知道它,并且它不会尝试删除它

即使这实际上也是有效的(但是,不,不要这样做):

类似的结果,但只是表面上:

def test3(self):
    self.someDialog = QtWidgets.QDialog()
    self.someDialog.show()
在上述情况下,可视化结果可能与
test2
相同,但是如果在对话框仍然可见时再次调用
test3
,它将删除当前对话框并创建一个新对话框:这是因为该对话框没有父对话框,用一个新实例覆盖self.someDialog将导致python释放上一个实例,这将告诉Qt它可以安全地删除它,因为它没有父实例

最后,无需将父窗口小部件设置为窗口小部件,只要它们被添加到布局中(这是首选方法,因为不鼓励使用固定几何体),因为一旦在实际父窗口上设置了父窗口小部件,布局就会自动设置父窗口小部件


请注意,QDialog通常显示为
exec_u389;()
,以便正确地将其显示为父级的模态,并按其应该的方式使用它。

首先,问题或差异与“self”无关,但它的用途是Qt设计中预先建立的规则

在Qt中,在QoObject之间有一个层次结构树,其中确定父QoObject管理内存(其子QoObject的生命周期),因此如果父QoObject删除了子QoObject,它们也将被删除。这可以避免内存泄漏,因为许多应用程序通常使用许多QObject

另一方面,亲属关系的概念也被传递给QWidget,因为它们也是QObject,但还有另一个特点:QWidget通常会在其父对象之上绘制。因此,如果希望QLineEdit和QLabel成为窗口的一部分,那么它们必须是窗口的子对象,因此有必要将“self”窗口对象作为父对象传递

因此,当您进入窗口(在本例中为“self”)时,可以避免两个问题:

def test3(self): self.someDialog = QtWidgets.QDialog() self.someDialog.show()