无法访问子 window 中的 "def" - "MainWindow object has no attribute 'updateTime' "

Unable to acces a "def" in a sub window - "MainWindow object has no attribute 'updateTime' "

我有一个主窗口,我在其中通过按钮调用子窗口(弹出窗口),但我无法访问 def updateTime(self),它给我一个属性错误:

AttributeError: 'MainWindow' object has no attribute 'updateTime'

如果我去掉 MainWindow 部分它工作正常所以我真的不明白问题是什么。任何帮助将不胜感激。

from PyQt4 import QtGui, QtCore
from PyQt4 import *
from PyQt4.QtCore import *
import sys

CurrentTime = 0

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.central = QtGui.QWidget(self)
        self.setCentralWidget(self.central)

        self.hboxPB = QtGui.QHBoxLayout()
        self.vboxPB = QtGui.QVBoxLayout()
        self.MyButton = QtGui.QPushButton(self.central)
        self.MyButton.setText("Push Me")
        self.hboxPB.addWidget(self.MyButton)
        self.vboxPB.addLayout(self.hboxPB)
        self.MyButton.resize(90,90)
        self.MyButton.clicked.connect(lambda: widgetWindow.start(self))

class widgetWindow(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self,parent)
        super(widgetWindow, self).__init__()
        widgetWindow.start(self)

    def start(self):
        window = QtGui.QMainWindow(self)
        window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        CentralWidget = QtGui.QWidget()
        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        CentralWidgetLayout = QtGui.QHBoxLayout()
        VBox = QtGui.QVBoxLayout()
        CentralWidgetLayout.addWidget(self.timeSlider)
        VBox.addLayout(CentralWidgetLayout)
        CentralWidget.setLayout(VBox)
        window.setCentralWidget(CentralWidget)
        window.show()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateTime)
        self.timer.start(1000)

    def updateTime(self):
        global CurrentTime
        CurrentTime = CurrentTime + 1
        self.timeSlider.setValue(CurrentTime)

def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    win.show()
    win.resize(800,450)
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

试试这个:

from PyQt4 import QtGui, QtCore
from PyQt4 import *
from PyQt4.QtCore import *
import sys

CurrentTime = 0
class widgetWindow(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self,parent)
        super(widgetWindow, self).__init__()
        widgetWindow.start(self)

    def start(self):
        window = QtGui.QMainWindow(self)
        window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        CentralWidget = QtGui.QWidget()
        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        CentralWidgetLayout = QtGui.QHBoxLayout()
        VBox = QtGui.QVBoxLayout()
        CentralWidgetLayout.addWidget(self.timeSlider)
        VBox.addLayout(CentralWidgetLayout)
        CentralWidget.setLayout(VBox)
        window.setCentralWidget(CentralWidget)
        window.show()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateTime)
        self.timer.start(1000)

    def updateTime(self):
        global CurrentTime
        CurrentTime = CurrentTime + 1
        self.timeSlider.setValue(CurrentTime)



class MainWindow(QtGui.QMainWindow,widgetWindow):#here add subclass
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.central = QtGui.QWidget(self)
        self.setCentralWidget(self.central)

        self.hboxPB = QtGui.QHBoxLayout()
        self.vboxPB = QtGui.QVBoxLayout()
        self.MyButton = QtGui.QPushButton(self.central)
        self.MyButton.setText("Push Me")
        self.hboxPB.addWidget(self.MyButton)
        self.vboxPB.addLayout(self.hboxPB)
        self.MyButton.resize(90,90)
        self.MyButton.clicked.connect(lambda: widgetWindow.start(self))



def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    win.show()
    win.resize(800,450)
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

您的命名空间有误。您必须确保使用正确的命名空间,否则解释器不知道在正确的位置查找 class.

您的问题始于行

self.MyButton.clicked.connect(lambda: widgetWindow.start(self))

让我们解构它在做什么。

  1. 您有一个按钮 self.MyButton,它存在于 class MainWindow 的实例中(您在 main()函数)

  2. 您正在连接到按钮的clicked信号。

  3. 您连接到此信号的函数是一个 lambda 函数,它 调用 class widgetWindow[=48= 中的一个函数].请注意,这与调用 class 实例的方法不同。您没有在此处实例化 class (您没有创建对象)。您是说,在 class widgetWindow 中使用方法定义 start 但使其作用于对象 self ,其中 self 是 class MainWindow.

希望您现在开始看到您所做的问题。您没有创建 widgetWindow class 的实例,而是尝试使用 widgetWindow 的方法,就好像它是 MainWindow 的方法一样。如果您仍然遇到问题(特别是如果您不清楚 class 和对象之间的区别)

因此,解决方案是创建 widgetWindow 的实例(而不是直接访问 class 的方法),并将您的按钮连接到该实例的方法。我已经修改了您的代码来执行此操作,已在下面发布。我已经评论了我已经更改的部分。如果您对我所做的有任何疑问,请告诉我。

from PyQt4 import QtGui, QtCore
from PyQt4 import *
from PyQt4.QtCore import *
import sys

CurrentTime = 0

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.central = QtGui.QWidget(self)
        self.setCentralWidget(self.central)

        self.hboxPB = QtGui.QHBoxLayout()
        self.vboxPB = QtGui.QVBoxLayout()
        self.MyButton = QtGui.QPushButton(self.central)
        self.MyButton.setText("Push Me")
        self.hboxPB.addWidget(self.MyButton)
        self.vboxPB.addLayout(self.hboxPB)
        self.MyButton.resize(90,90)

        # instantiate the widgetWindow (pass this window as the parent)
        self.widgetwindow = widgetWindow(self)
        # connect the button to the start method of this instance we created above
        self.MyButton.clicked.connect(self.widgetwindow.start)

# no need to subclass QWidget here. This is just a wrapper class to hold your main window
class widgetWindow(object):
    def __init__(self, parent = None):
        # Store the parent for use later
        self.parent = parent

    def start(self):
        # change the window parent to be the parent we stored in the __init__ method
        window = QtGui.QMainWindow(self.parent)
        window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        # Add a signal to stop the timer when the window is destroyed
        window.destroyed.connect(self.stopTimer)
        CentralWidget = QtGui.QWidget()
        # Change the parent to be the window we just created
        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal, window)
        CentralWidgetLayout = QtGui.QHBoxLayout()
        VBox = QtGui.QVBoxLayout()
        CentralWidgetLayout.addWidget(self.timeSlider)
        VBox.addLayout(CentralWidgetLayout)
        CentralWidget.setLayout(VBox)
        window.setCentralWidget(CentralWidget)
        window.show()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateTime)
        self.timer.start(1000)

    def updateTime(self):
        global CurrentTime
        CurrentTime = CurrentTime + 1
        self.timeSlider.setValue(CurrentTime)

    # Method to stop the timer once the window is destroyed
    def stopTimer(self):
        self.timer.stop()

def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    win.show()
    win.resize(800,450)
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()