【问题标题】:Update a QLabel , using a QPushButton in a QDialog更新 QLabel ,在 QDialog 中使用 QPushButton
【发布时间】:2018-10-19 22:06:30
【问题描述】:

我刚开始使用 PyQt5,我正在尝试通过子类 (QDialog) 中的按钮更新标签的信息。当我按下按钮时,程序停止并显示消息:

"AttributeError: 'New_Player_Window' object has no attribute 'name_window_label'

这个想法是,当按下按钮时,默认为“匿名”的 Qlabel 成为用户的名称。

代码是:

from PyQt5 import QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, 
QLineEdit, QLabel, QWidget, QPushButton, QMessageBox, QAction, QMenu, 
QDialog
import sys

class General_Window(QMainWindow):
  def __init__(self):
    super().__init__()
    self.initUI()
  def initUI(self):
    self.resize(500, 500)
    self.move(300, 100)
    self.setWindowTitle('Black Jack')
    #MENUBAR
    menubar = self.menuBar()
    fileMenu = menubar.addMenu('File')
    newAct = QAction('New Player', self)
    newAct.triggered.connect(General_Window.new_player)
    fileMenu.addAction(newAct)
    #LABEL
    self.name_window_label = QLabel('Anonimous', self)
    self.name_window_label.move(245, 15)
    self.show()

  def update_window(self, value):
    print(str(value))
    self.name_window_label.setText(str(value))

  def new_player(self):
    class New_Player_Window(QDialog, General_Window):
        def __init__(self):
            super().__init__()
            self.initUI()

        def create(self):
            try:
                int(self.money.text()) + 2
            except:
                QMessageBox.question(self, 'PyQt5 message', "You need to 
                insert a Number", QMessageBox.Ok , QMessageBox.Ok) 
            else:
                global value
                value = self.name.text()
                print(value)
                self.update_window(value)

        def initUI(self):                   
            self.setGeometry(300, 230, 250, 120)
            self.setWindowTitle('User Information')    
            #TEXTBOX1
            self.name = QLineEdit(self)
            self.name.move(110, 5)
            self.name.resize(110,20)
            #TEXTBOX2
            self.money = QLineEdit(self)
            self.money.move(110, 40)
            self.money.resize(110,20)
            #BUTTON1
            self.button = QPushButton('Create', self)
            self.button.move(5,80)
            self.button.clicked.connect(self.create)
            #BUTTON2
            self.button2 = QPushButton('Cancel', self)
            self.button2.move(120,80)
            #LABELNAME
            self.name_label = QLabel('SHORT NAME', self)
            self.name_label.move(20,10)
            #LABELNAME
            self.money_label = QLabel('MONEY AVAILABLE', self)
            self.money_label.move(10,45)

            self.show()
            self.exec_()


    if __name__=="__main__":
        New_Player_Window()

if __name__=="__main__":
 app = QApplication(sys.argv)
 ag = General_Window()  
 sys.exit(app.exec_())

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qdialog


    【解决方案1】:

    你有几个错误:

    • 正如您所指出的,General_Window 具有 name_window_label 属性,因此预计 New_Player_Window 也会拥有它,但 name_window_label 是在 initUI 中创建的,但您已在 New_Player_Window 类中覆盖它,因此该属性不存在但即使有它,它也不会是另一个窗口的 name_window_label,因为它是另一个具有另一个对象的类,我建议阅读 OOP,尤其是继承和组合。

    • 拥有另一个类的内部类被认为是一种不好的做法(django 等例外情况除外),因为您每时每刻都在创建该类,不必要地花费资源。

    • 这本身不是错误,而是一种不好的做法,不要使用全局变量,因为调试全局变量很复杂,因为它的生命周期很困难,可以隐藏其他类型的问题。

    • 最后考虑使用适当的小部件让用户输入适当的数据类型,例如使用 QSpinBox 输入整数值,以避免不必要的检查。我还将建议添加到布局的使用中,正如我将在我的回答中展示的那样。

    转到解决方案的设计,当您创建一个小部件时,将其视为一个接收输入并生成输出的黑匣子,如果输出是同步的,它使用一种您可以检索该信息的方法,如果它是异步的使用信号,另一方面 QDialog 是一个专门用于请求信息的类,因此您不应该更新 New_Player_Window 中的信息,但在 General_Window 中,您必须传递信息。如果用户接受或拒绝请求,QDialog 使用exec_() 返回,但为此您必须调用接受或拒绝。

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class New_Player_Window(QtWidgets.QDialog):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def get_values(self):
            return self.name.text(), self.money.value()
    
        def initUI(self):
            self.setWindowTitle('User Information')   
            #TEXTBOX1
            self.name = QtWidgets.QLineEdit()
            #TEXTBOX2
            self.money = QtWidgets.QSpinBox(maximum=2147483647)
            #BUTTON1
            self.button = QtWidgets.QPushButton('Create')
            self.button.clicked.connect(self.accept)
            #BUTTON2
            self.button2 = QtWidgets.QPushButton('Cancel')
            self.button2.clicked.connect(self.reject)
    
            lay = QtWidgets.QVBoxLayout(self)
            flay = QtWidgets.QFormLayout()
            flay.addRow("SHORT NAME", self.name)
            flay.addRow("MONEY AVAILABLE", self.money)
            lay.addLayout(flay)
            hlay = QtWidgets.QHBoxLayout()
            hlay.addWidget(self.button)
            hlay.addWidget(self.button2)
            lay.addLayout(hlay)
            self.setFixedSize(self.sizeHint())
    
    
    class General_Window(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.setWindowTitle('Black Jack')
            #MENUBAR
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('File')
            newAct = QtWidgets.QAction('New Player', self)
            newAct.triggered.connect(self.new_player)
            fileMenu.addAction(newAct)
            #LABEL
            self.name_window_label = QtWidgets.QLabel('Anonimous', alignment=QtCore.Qt.AlignCenter)
            widget = QtWidgets.QWidget()
            self.setCentralWidget(widget)
            lay = QtWidgets.QVBoxLayout(widget)
            lay.addWidget(self.name_window_label, alignment=QtCore.Qt.AlignTop)
    
        def update_window(self, value):
            self.name_window_label.setText(value)
    
        def new_player(self):
            w = New_Player_Window()
            if w.exec_() == QtWidgets.QDialog.Accepted:
                name, value = w.get_values()
                print(name, value)
                self.update_window(name)
    
    
    if __name__=="__main__":
         app = QtWidgets.QApplication(sys.argv)
         ag = General_Window()  
         ag.show()
         sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您抽出宝贵时间向我解释,并清楚我的错误。我完全同意你关于更多地学习该主题的建议,你知道一本学习 OOP 的好书的名字吗?
    【解决方案2】:

    试试看:

    import sys
    from PyQt5 import QtGui, QtWidgets
    from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, 
                                 QLineEdit, QLabel, QWidget, QPushButton, 
                                 QMessageBox, QAction, QMenu, QDialog, QSpinBox)
    
    class General_Window(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.resize(500, 500)
            self.move(300, 100)
            self.setWindowTitle('Black Jack')
            #MENUBAR
            menubar  = self.menuBar()
            fileMenu = menubar.addMenu('File')
            newAct   = QAction('New Player', self)
            newAct.triggered.connect(self.new_player)
            fileMenu.addAction(newAct)
            #LABEL
            self.name_window_label = QLabel('Anonimous', self)
            self.name_window_label.move(245, 15)
    
        def update_window(self, value):
            print(str(value))
            self.name_window_label.setText(str(value))
    
        def new_player(self):
            self.newPlayerWindow = New_Player_Window(self)
    
    
    class New_Player_Window(QDialog): 
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.parent = parent  
            self.value  = 12
    
            self.initUI()
    
        def create(self):
            value = "{} - {}".format(self.name.text(), self.value)
            print(value)
            self.parent.update_window(value)
            self.close()    
    
        def initUI(self):                   
            self.setGeometry(300, 230, 250, 120)
            self.setWindowTitle('User Information')    
            #TEXTBOX1
            self.name = QLineEdit(self)
            self.name.move(110, 5)
            self.name.resize(110,20)
            #TEXTBOX2
            self.money = QSpinBox(self) #QLineEdit(self)
            self.money.setRange(1, 99)
            self.money.setValue(12)
            self.money.valueChanged.connect(self.moneyValueChanged)
            self.money.move(110, 40)
            self.money.resize(110,20)
            #BUTTON1
            self.button = QPushButton('Create', self)
            self.button.move(5,80)
            self.button.clicked.connect(self.create)
            #BUTTON2
            self.button2 = QPushButton('Cancel', self)
            self.button2.move(120,80)
            #LABELNAME
            self.name_label = QLabel('SHORT NAME', self)
            self.name_label.move(20,10)
            #LABELNAME
            self.money_label = QLabel('MONEY AVAILABLE', self)
            self.money_label.move(10,45)
            self.exec_()
    
        def moneyValueChanged(self, value): 
            self.value = value   
    
    
    if __name__=="__main__":
        app = QApplication(sys.argv)
        ag = General_Window() 
        ag.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的宝贵时间和建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 2021-05-25
    • 2018-04-25
    • 1970-01-01
    相关资源
    最近更新 更多