Код записи/закрытия всплывающего окна перестает работать при вызове добавленного окна, почему?

Первый пример программы работает нормально. Программа открывает NumPad, когда пользователь щелкает одну из ячеек массива QLineEdit, и когда пользователь с помощью мыши выбирает число и нажимает «Ввод», число помещается в выбранную ячейку QLineEdit, а NumPad закрывается. Однако, когда во второй программе добавляется вызывающий экран для открытия экрана "ss", строки "ss.lVal[(..." и "ss.numpad.close()" перестают работать.

Рабочий пример кода:

#!/usr/bin/env python

import sys
from pprint import pprint
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import pyqtSignal
from PyQt5 import QtCore, QtGui, QtWidgets

# Global variables
# Data Select - 3=3 Data Rows,4=4 Data Rows,5=5 DataRows
gvDataSel = 3
gvPickX = 0
gvPickY = 0

class extQLineEdit(QLineEdit):
    clicked=pyqtSignal()
    def __init__(self,parent):
        QLineEdit.__init__(self,parent)
    def mousePressEvent(self,QMouseEvent):
        self.clicked.emit()


class wdScoreSheet(QWidget):
    def __init__(self):
        super(wdScoreSheet, self).__init__()

        global gvDataSel

        self.resize(400, 300)

        self.numpad = NumPad(self)

        # Value array
        self.lVal = {}
        for i in range(gvDataSel):
            for j in range(2):
                k = 0
                self.lVal[i,j] = extQLineEdit(self)
                self.lVal[i,j].setGeometry(QtCore.QRect(((j*140)+10),((i*34)+50), 50, 28))
                self.lVal[i,j].clicked.connect(lambda i=i, j=j: self.show_NumPad(i,j))


    def show_NumPad(self, parm1, parm2):
        global gvPickX
        global gvPickY
        gvPickX = parm1
        gvPickY = parm2
        self.numpad.show()

    def close(self):
        self.numpad.close()
        super(wdScoreSheet, self).close()


class NumPad(QWidget):
    def __init__(self, parm1):
        super(NumPad, self).__init__()

        grid_layout = QGridLayout()
        self.setLayout(grid_layout)
        values = [
            '1', '2', '3',
            '4', '5', '6',
            '7', '8', '9',
            '-', '0', 'Enter'
        ]
        positions = [(i, j) for i in range(1,5) for j in range(3)]
        # position is an array of tuples
        for position, value in zip(positions, values):
            if value == '':
                continue
            button = QPushButton(value)
            grid_layout.addWidget(button, *position)
            button.clicked.connect(self.btnclick)

        self.setWindowTitle('Num Pad')

        verticalLayout = QVBoxLayout()
        self.lineEdit = QLineEdit()
        verticalLayout.addWidget(self.lineEdit)
        grid_layout.addLayout(verticalLayout, 0, 0, 1, 3)



    def btnclick(self):
        sender = self.sender()
        #pprint("You Pressed: " + sender.text())
        if sender.text() in ['0','1','2','3','4','5','6','7','8','9']:
            self.lineEdit.setText(self.lineEdit.text() + sender.text())

        if sender.text() in ['-']:
            if self.lineEdit.text()[:1] in ['-']:
                self.lineEdit.setText(self.lineEdit.text()[-(len(self.lineEdit.text())-1):])
            else:
                self.lineEdit.setText(sender.text() + self.lineEdit.text())

        if sender.text() in ["Enter"]:
            if self.lineEdit.text() not in [""]:
                ss.lVal[(gvPickX, gvPickY)].setText(self.lineEdit.text())
            self.lineEdit.clear()
            ss.numpad.close()



if __name__ == "__main__":
    app = QApplication(sys.argv)
    ss = wdScoreSheet()
    ss.show()
    sys.exit(app.exec_())

Тот же код с добавленным MainWindow, который не работает:

#!/usr/bin/env python

import sys
from pprint import pprint
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import pyqtSignal
from PyQt5 import QtCore, QtGui, QtWidgets

# Global variables
# Data Select - 3=3 Data Rows,4=4 Data Rows,5=5 DataRows
gvDataSel = 3
gvPickX = 0
gvPickY = 0

class extQLineEdit(QLineEdit):
    clicked=pyqtSignal()
    def __init__(self,parent):
        QLineEdit.__init__(self,parent)
    def mousePressEvent(self,QMouseEvent):
        self.clicked.emit()


class wdScoreSheet(QWidget):
    def __init__(self):
        super(wdScoreSheet, self).__init__()

        global gvDataSel

        self.resize(400, 300)

        self.numpad = NumPad(self)

        # Value array
        self.lVal = {}
        for i in range(gvDataSel):
            for j in range(2):
                k = 0
                self.lVal[i,j] = extQLineEdit(self)
                self.lVal[i,j].setGeometry(QtCore.QRect(((j*140)+10),((i*34)+50), 50, 28))
                self.lVal[i,j].clicked.connect(lambda i=i, j=j: self.show_NumPad(i,j))


    def show_NumPad(self, parm1, parm2):
        global gvPickX
        global gvPickY
        gvPickX = parm1
        gvPickY = parm2
        self.numpad.show()

    def close(self):
        self.numpad.close()
        super(wdScoreSheet, self).close()


class NumPad(QWidget):
    def __init__(self, parm1):
        super(NumPad, self).__init__()

        grid_layout = QGridLayout()
        self.setLayout(grid_layout)
        values = [
            '1', '2', '3',
            '4', '5', '6',
            '7', '8', '9',
            '-', '0', 'Enter'
        ]
        positions = [(i, j) for i in range(1,5) for j in range(3)]
        # position is an array of tuples
        for position, value in zip(positions, values):
            if value == '':
                continue
            button = QPushButton(value)
            grid_layout.addWidget(button, *position)
            button.clicked.connect(self.btnclick)

        self.setWindowTitle('Num Pad')

        verticalLayout = QVBoxLayout()
        self.lineEdit = QLineEdit()
        verticalLayout.addWidget(self.lineEdit)
        grid_layout.addLayout(verticalLayout, 0, 0, 1, 3)



    def btnclick(self):
        sender = self.sender()
        #pprint("You Pressed: " + sender.text())
        if sender.text() in ['0','1','2','3','4','5','6','7','8','9']:
            self.lineEdit.setText(self.lineEdit.text() + sender.text())

        if sender.text() in ['-']:
            if self.lineEdit.text()[:1] in ['-']:
                self.lineEdit.setText(self.lineEdit.text()[-(len(self.lineEdit.text())-1):])
            else:
                self.lineEdit.setText(sender.text() + self.lineEdit.text())

        if sender.text() in ["Enter"]:
            if self.lineEdit.text() not in [""]:
                ss.lVal[(gvPickX, gvPickY)].setText(self.lineEdit.text())
            self.lineEdit.clear()
            ss.numpad.close()

class wdMainWindow(QMainWindow):
    def __init__(self):
        super(wdMainWindow, self).__init__()
        self.resize(400, 300)

        self.pbSHR = QPushButton(self)
        self.pbSHR.setText("Open Data Screen")
        self.pbSHR.setGeometry(QtCore.QRect(20, 20, 200, 30))
        self.pbSHR.clicked.connect(self.pbSHR_clicked)

    def pbSHR_clicked(self):
        global gvDataSel
        gvDataSel = 4
        ss = wdScoreSheet()
        ss.show()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = wdMainWindow()
    mw.show()
    sys.exit(app.exec_())

Добавление MainWindow для вызова ss (открытый экземпляр wdScoreSheet) приводит к тому, что "ss.lVal[(..." и "ss.numpad.close()" теперь не работают, почему? Что нужно изменить, чтобы NumPad работал как первая программа ? Заранее спасибо за вашу помощь.


person Michael H    schedule 20.12.2018    source источник
comment
Я вижу ваш ответ о том, что на этот вопрос был дан ответ, и я просмотрел эти ответы, как ответ области, так и использование глобальных переменных. Я рассмотрю глобальную проблему позже ниже, но я чувствую, что моя проблема связана с масштабом. Закрытие NumPad работает, я думаю, в первом коде, потому что его экземпляр находится в области действия ss, и этот дочерний элемент может быть закрыт, почему он все еще не находится в области действия ss, когда он запускается mw. Это мой главный вопрос, который я пытаюсь решить. Что касается глобальных переменных, это не был мой желаемый метод, но передача параметров не сработала, когда я пытался.   -  person Michael H    schedule 20.12.2018
comment
Если вы правильно прочитали ответы, вы поняли, что переменная должна существовать столько, сколько необходимо, например, если вы хотите, чтобы переменная была доступна внутри класса, сделайте ее членом класса, если вы только хотите быть необходимым внутри функции, тогда это должна быть только локальная переменная. Если вы хотите получить доступ к переменной, определенной в другом классе, обращайтесь через объект этого класса. С другой стороны, если вы не будете брать его за основу, у вас всегда будут проблемы, а отладка будет сложной и запутанной.   -  person eyllanesc    schedule 21.12.2018