Accessing GUI elements from outside GUI class in PyQt

2.3k views Asked by At

Note : I've already read this post and I didn't understand it unfortunately. I've got a directory settings somewhat like this :

Main_Folder
|_ Base_Gui_File.py
|_ Child_directory (a directory inside Main_Folder)
  |_ __init__.py
  |_ some_other.py

I've got all the GUI code in the Base_Gui_File.py file, which was generated from designer(PyQt4). There's a Text Input Field QLineEdit, a Push Button QPushButtonand a Text Area QTextBrowser.

By default QTextBrowser is hidden. But, what I wanted to do was that, when some one types something in the QLineEdit and clicks the QPushButton, it'll send the string from QLineEdit to a method in some_other.py file in the Child_Directory. And after doing something with that string, the method in the some_other.py file will show the QTextBrowser in the Base_Gui_File.py and also print something in the QTextBrowser.

So far I've been able to send the string from Base_GUI_File.py to some_other.py file by taking input from the QLineEdit. Here's the code for both the files :

some_other.py:

import sys
sys.path.append("..")
from Base_Gui_File import Ui_MainWindow


class childone(object):
    """docstring for childone"""
    def __init__(self):
        super(childone, self).__init__()

    def somemethod(self, url):
        pass
        print 'Hey!'
        final_string = str(url) + "Just tying this!"
        print final_string

Base_Gui_file.py:

# -*- coding: utf-8 -*-

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 544)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.MyPushButton = QtGui.QPushButton(self.centralwidget)
        self.MyPushButton.setGeometry(QtCore.QRect(680, 40, 75, 23))
        self.MyPushButton.setObjectName(_fromUtf8("MyPushButton"))
        self.MyLabel = QtGui.QLabel(self.centralwidget)
        self.MyLabel.setGeometry(QtCore.QRect(30, 30, 46, 13))
        self.MyLabel.setObjectName(_fromUtf8("MyLabel"))
        self.MyTextArea = QtGui.QTextBrowser(self.centralwidget)
        self.MyTextArea.setGeometry(QtCore.QRect(20, 110, 721, 361))
        self.MyTextArea.setObjectName(_fromUtf8("MyTextArea"))
        self.MyTextField = QtGui.QLineEdit(self.centralwidget)
        self.MyTextField.setGeometry(QtCore.QRect(100, 30, 571, 41))
        self.MyTextField.setObjectName(_fromUtf8("MyTextField"))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuFIle = QtGui.QMenu(self.menubar)
        self.menuFIle.setObjectName(_fromUtf8("menuFIle"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menuFIle.menuAction())

        self.MyPushButton.clicked.connect(self.download_click)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.MyPushButton.setText(_translate("MainWindow", "PushButton", None))
        self.MyLabel.setText(_translate("MainWindow", "TextLabel", None))
        self.menuFIle.setTitle(_translate("MainWindow", "FIle", None))

    def download_click(self):
            self.MyTextArea.textCursor().insertHtml('Im HERE!') # This is working as it should
            url = str(self.MyTextField.text())

            from Child_directory.some_other import childone

            childone().somemethod(url)


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

How can I do so? I started GUI and OO programming (Python) 2 days ago so I'm pretty much new to it. So, even if it's just a guide in a right direction, that'd be great!

1

There are 1 answers

3
ekhumoro On BEST ANSWER

As I said in the answer you linked to: it is always a mistake to edit the module generated by pyuic. It is meant to be a static module that you import into your main program.

Also, the current structure of your program looks backwards. The main script should be at the top level, and all the modules should be in a package below it. This will ensure that you don't need to do any weird sys.path manipulations to import your own modules. Here is what the structure should look like:

program
    |_  main.py
    |_  package
        |_  __init__.py
        |_  app.py
        |_  gui.py
        |_  utils.py

Your main.py script should be very simple, and look like this:

if __name__ == '__main__':

    import sys
    from package import app

    sys.exit(app.run())

It is very important to do things this way, because the path of this script will become the first entry in sys.path. This means you can then do from package import xxx in any other module in your program, and the imports will always work correctly.

The app module should look like this:

import sys
from PyQt4 import QtCore, QtGui
from package.gui import Ui_MainWindow
from package import utils

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.MyPushButton.clicked.connect(self.download_click)

    def download_click(self):
        self.MyTextArea.textCursor().insertHtml('Hello World!')
        url = str(self.MyTextField.text())
        utils.some_func(url)

def run():    
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    return app.exec_()

Note that I've moved the edits you made to your gui module into the app module. The MainWindow class will pull in all the widgets you added in Qt Designer, and they will become attributes of the class instance. So once you've rearranged your program, you should re-generate the gui module using pyuic.