无法访问" def"在子窗口中 - " MainWindow对象没有属性' updateTime' "

时间:2015-08-23 08:22:57

标签: python pyqt qmainwindow qtimer

我有一个MainWindow,我从按钮调用子窗口(弹出窗口),我无法访问def updateTime(self),它给了我一个属性错误:

  

AttributeError:' MainWindow'对象没有属性' 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()

2 个答案:

答案 0 :(得分:2)

您的问题从第

行开始
self.MyButton.clicked.connect(lambda: widgetWindow.start(self))

让我们解构这是在做什么。

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

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

  3. 您连接到此信号的功能是lambda函数,调用类widgetWindow 中的函数。请注意,这与调用类实例的方法不同。你没有在这里实例化一个类(你没有创建一个对象)。您是说,使用类start中的方法定义widgetWindow,但要使其对self对象进行操作,其中self是类MainWindow的实例

  4. 希望您现在开始看到您所做的事情的问题。您尝试使用widgetWindow中的方法,而不是创建widgetWindow类的实例,就好像它是MainWindow的方法一样。我建议在Python中阅读更多关于面向对象编程的内容,以便在遇到麻烦时(尤其是如果您不清楚类和对象之间的区别)来了解这个问题。

    因此,解决方案是创建widgetWindow的实例(而不是直接访问类的方法),并将按钮连接到该实例的方法。我已修改您的代码以执行此操作,如下所示。我已经评论了我改变的部分。如果您对我所做的事情有疑问,请与我联系。

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

答案 1 :(得分:-2)

试试这个:

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

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