Обновите QLabel, используя QPushButton в QDialog - PullRequest
0 голосов
/ 20 октября 2018

Я только начал использовать PyQt5 и пытаюсь обновить информацию метки через кнопку, которая находится внутри подкласса (QDialog).Когда я нажимаю кнопку, программа останавливается и показывает сообщение:

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

Идея состоит в том, что при нажатии кнопки Qlabel, который по умолчанию "Anonimous", становится именем пользователя.

Код:

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

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

У вас есть несколько ошибок:

  • Как вы указали, у General_Window есть атрибут name_window_label, поэтому можно ожидать, что New_Player_Window также будет иметь его, но name_window_label создается в initUI, но выперезаписали его в классе New_Player_Window, чтобы этот атрибут не существовал, но даже если бы он имел его, он не был бы name_window_label другого окна, так как это другой класс, имеющий другой объект, я рекомендую прочитать об ООП и особенно о наследованиии состав.

  • Наличие внутреннего класса другого класса считается плохой практикой (с такими исключениями, как 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_())
0 голосов
/ 20 октября 2018

Попробуйте:

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

enter image description here

...