How to return value from the QWidget

Refresh

November 2018

Views

45 time

2

I have a widget that ends with pressing OK button. I want that the widget returns a value to the main program (which is in simple example below the obtained value increased by 1). How can I do this?

Also, is there any more elegant way to show the same QWidget with the different title?

MWE:

import sys
from PyQt5 import QtGui, QtCore, QtWidgets

class MainWindow(QtWidgets.QWidget):
    def __init__(self,val):
        self.val=val
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self):
        self.End= QtWidgets.QPushButton('OK', self)
        self.End.clicked.connect(self.end)

        MainLayout = QtWidgets.QVBoxLayout()
        MainLayout.addWidget(self.End)
        self.setLayout(MainLayout)
        self.setWindowTitle(str(self.val))
        self.show()

    def end(self):
        # return self.val+1
        self.close()

def main(): 
    app = QtWidgets.QApplication(sys.argv)

    for i in range(10):
        ex = MainWindow(i)
        ex.show()
        res = app.exec_()
        print(res)
    sys.exit()

if __name__ == '__main__':
    main()

2 answers

0

Пока неясно , что именно ваши намерения с этим кодом. Если valпредполагается, что счетчик для количества MainWindowэкземпляров, то вы должны объявить его как статический:

class MainWindow(QtWidgets.QWidget):
    val = 0
    def __init__(self):
        super(MainWindow, self).__init__()
        MainWindow.val += 1
        self.initUI()

    def initUI(self):
        # ...
        self.setWindowTitle(str(MainWindow.val))
        # ...

def main():
    # ...
    for i in range(10):
        ex = MainWindow()
        # ...
    # ...

Там нет ничего плохого в призыве , QWidget::setWindowTitle()так что я не вижу здесь проблемы.

Если вы действительно хотите , чтобы иметь его в качестве члена нестатического класса и каждый MainWindowиспользует его в качестве своего рода ID, вы можете легко вызвать право значения после ex.show():

def main(): 
    app = QtWidgets.QApplication(sys.argv)

    for i in range(10):
        ex = MainWindow()
        ex.show()
        print(MainWindow.val)
        res = app.exec_()
        print(res)
    sys.exit()

Просто потому, что вы закрываете виджет не означает, что вы разрушили его так вызова значения, хранящиеся внутри объекта не является проблемой.

Однако в этом случае вы не знакомы , что QApplication::exec()предназначен для. Она проходит основной цикл данного приложения и возвращает статус выхода (вы можете установить его при вызове в exit()качестве параметра , переданного этой функции). Если вы просто хотите , чтобы получить значение valпри закрытии виджета вы можете просто переопределить closeEventобработчик и выдаст сигнал. Создание QObjectэкземпляра и подключения каждого MainWindowпользовательского сигнала близко экземпляра к слоту и делать со значением все , что вы хотите.

1

Если вы хотите использовать виджет , чтобы получить какое - то значение после некоторой обработки, правильная вещь заключается в использовании QDialog, что предотвращает любое другое окно с открытия , если вы используете exec_():

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Dialog(QtWidgets.QDialog):
    def __init__(self, val, parent=None):
        super(Dialog, self).__init__(parent)
        self.val = val
        self.initUI()

    def initUI(self):
        endButton = QtWidgets.QPushButton('OK')
        endButton.clicked.connect(self.on_clicked)
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(endButton)
        self.setWindowTitle(str(self.val))

    @QtCore.pyqtSlot()
    def on_clicked(self):
        self.val += 1
        self.accept()

def main(): 
    app = QtWidgets.QApplication(sys.argv)
    for i in range(10):
        ex = Dialog(i)
        ex.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        if ex.exec_() == QtWidgets.QDialog.Accepted:
            print(ex.val)

if __name__ == '__main__':
    main()