0

I've been looking for a better way to work with frontends made using qtDesigner connected to a python backend. All the methods I have found have the following form:

  1. Make GUI in designer
  2. Output to python code using pyuic (usually with -x option)
  3. Write backend code inside this output file

This methodology is not simple to maintain or edit. Any time you change the UI, it completely breaks workflow: you have to reconvert, generate a new file, fix that file back up to where you were before, then finally get back on track. This requires a lot of manual copy-paste of code, which is an invitation to errors on multiple levels (newly generated file layout may not be the same, manually fixing name changes while pasting, etc.). You can also end up losing work if you aren't careful, since you could accidentally overwrite the file and destroy the backend code.

Also, this doesn't use any of the control in qtDesigner like the Signal/Slot and Action editors. These must be here for something, but I can't find a way to actually direct these to call backend functions.

Is there a better way to work with this, possibly using the features of qtDesigner?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Elliot
  • 5,211
  • 10
  • 42
  • 70

2 Answers2

0

You don't have to add your code in the output file :

If you take a 'home.py' generated by PYUIC, containing a QMainWindow which name set by QtDesigner/generated by Puic would be Ui_Home(), your main code could be :

from home import Ui_Home
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class window_home(QMainWindow):
   def __init__(self, parent=None):
       QMainWindow.__init__(self, parent)        
       #set up the user interface from Designer
       self.ui = Ui_Home()
       self.ui.setupUi(parent)
       #then do anything as if you were in your output file, for example setting an image for a QLabel named "label" (using QtDesigner) at the root QMainWindow :
       self.ui.label.setPixmap(QPixmap("./pictures/log.png"))

def Home():
    f=QMainWindow()
    c=window_home(f)
    f.show()
    r=qApp.exec_()
if __name__=="__main__":
    qApp=QApplication(sys.argv)
    Home()
tgrandje
  • 2,332
  • 11
  • 33
0

I found an even cleaner method for working with this, that does not require preemptive conversion after each edit at all. Instead it takes the .ui file itself, so all you need to do is restart the program itself to update the design.

import sys
import os
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import uic

path = os.path.dirname(__file__) #uic paths from itself, not the active dir, so path needed
qtCreatorFile = "XXXXX.ui" #Ui file name, from QtDesigner, assumes in same folder as this .py

Ui_MainWindow, QtBaseClass = uic.loadUiType(path + qtCreatorFile) #process through pyuic

class MyApp(QMainWindow, Ui_MainWindow): #gui class
    def __init__(self):
        #The following sets up the gui via Qt
        super(MyApp, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #set up callbacks
        self.ui.NAME OF CONTROL.ACTION.connect(self.test)

    def test(self):
        #Callback Function


if __name__ == "__main__":
    app = QApplication(sys.argv) #instantiate a QtGui (holder for the app)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Note that this is Qt5. Qt5 and Qt4 are not API compatible, so it will be a little different in Qt4 (and presumably earlier as well).

Elliot
  • 5,211
  • 10
  • 42
  • 70