Search code examples
pythonpyqt4qtgui

How to use QtGui in PyQt4 to collect input variables to a python program?


Instead of input flags on the command line, using sys.argv, I want to change my python program so that a GUI with dialog boxes lets users provide answers to some questions. After the "apply" button is pushed I want the dialog GUI to dissapear and then the code to run normally with the variables provided in dialog boxes. I have tried many different ways using QtGui. Either it crashes, or, the answers are not known for the main program. Below I show one of my many attempts. In this example the answer is not known after the apply button is pressed. The output is

after widget answer1 = <blank no matter what I write in the dialog box>

I would very much appreciate help on how to change this code so that the variable "a1" is filled with the string given in the dialog box. Thank you!

import sys
from PyQt4 import QtGui

class Widget(QtGui.QWidget):

    def __init__(self):
        super(Widget, self).__init__()

        self.answer1 = QtGui.QLabel()
        q1Edit = QtGui.QLineEdit()
        q1Edit.textChanged[str].connect(self.q1Changed)

        grid = QtGui.QGridLayout()
        grid.setSpacing(20)

        grid.addWidget(QtGui.QLabel('Question 1'), 1, 0)
        grid.addWidget(q1Edit, 1, 1)
        grid.addWidget(self.answer1, 1, 2)

        applyBtn = QtGui.QPushButton('Apply', self)
        applyBtn.clicked.connect(self.close)

        self.answer1Text = self.answer1.text()

        grid.addWidget(applyBtn,4,3)

        self.setLayout(grid)     

        self.setGeometry(300, 300, 350, 300)
        self.show()


    def q1Changed(self, text):
        self.answer1.setText(text)

    def returnAnswer1(self):
        return self.answer1Text


def main():    
    app = QtGui.QApplication(sys.argv)
    w = Widget() 
    a1 = w.returnAnswer1()
    print("after widget answer1 = " + a1)    
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Thanks to JRazor, this was in the end the solution:

import sys
from PyQt4 import QtGui

class Widget(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.answer1 = QtGui.QLabel()
        q1Edit = QtGui.QLineEdit()
        q1Edit.textChanged.connect(self.q1Changed)

        self.answer2 = QtGui.QLabel()
        q2Edit = QtGui.QLineEdit()
        q2Edit.textChanged.connect(self.q2Changed)

        grid = QtGui.QGridLayout()
        grid.setSpacing(20)

        grid.addWidget(QtGui.QLabel('Question 1'), 1, 0)
        grid.addWidget(q1Edit, 1, 1)

        grid.addWidget(QtGui.QLabel('Question 2'), 2, 0)
        grid.addWidget(q2Edit, 2, 1)

        applyBtn = QtGui.QPushButton('Apply', self)
        applyBtn.clicked.connect(self.close)

        grid.addWidget(applyBtn,3,2)
        self.setLayout(grid)
        self.setGeometry(300, 300, 350, 300)

    def q1Changed(self, text):
        self.answer1.setText(text)

    def q2Changed(self, text):
        self.answer2.setText(text)

    def returnAnswer1(self):
        return self.answer1.text()

    def returnAnswer2(self):
        return self.answer2.text()

    @staticmethod
    def getData(parent=None):
        dialog = Widget(parent)
        dialog.exec_()
        return [dialog.returnAnswer1(), dialog.returnAnswer2()]

def main():
    app = QtGui.QApplication([])
    window = Widget()
    data = window.getData()
    print data[0]
    print data[1]


if __name__ == '__main__':
    main()

Solution

  • You need change QWidget to QDialog:

    class Widget(QtGui.QDialog):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    

    Then create a function for class Widget with a static method. Function will get parent to dialog window and return text from edit field:

    @staticmethod
    def getData(parent = None):
        dialog = Widget(parent)
        dialog.exec_()
        return dialog.returnAnswer1()
    

    Then call the window with passing a value:

    def main():
        app = QtGui.QApplication([])
        window = Widget()
        print window.getData()  # window is value from edit field
    

    Also, you need delete self.show() from class.

    Full code: https://gist.github.com/gitex/83b06e8ceaac18ad5dec2d332ed6cbaa