Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Best practices for creating a UI in qt for python? QML, QuiLoadUI, or generate through python?
Forum Updated to NodeBB v4.3 + New Features

Best practices for creating a UI in qt for python? QML, QuiLoadUI, or generate through python?

Scheduled Pinned Locked Moved Unsolved Qt for Python
7 Posts 4 Posters 1.4k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    metalshreds
    wrote on 1 May 2019, 15:17 last edited by metalshreds 5 Feb 2019, 14:38
    #1

    I'm new to QT for python, trying to avoid digging myself into a hole. I want to separate the ui as much as possible from the logic. reading the documentation I would go with QML and python route but wanted to get others opinions who have more experience. Thanks in advance!

    1 Reply Last reply
    0
    • K Offline
      K Offline
      Kent-Dorfman
      wrote on 23 May 2019, 17:50 last edited by
      #2

      I don't do QML...but can generally make good use of the UI designer as a starting point.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Denni
        wrote on 4 Jun 2019, 21:10 last edited by Denni 6 Apr 2019, 21:12
        #3

        @metalshreds I am still fairly new to pyqt5 but a long time software engineer and the class system of python should be all that you need to use to divorce the UI code from the middle tier or back-end logic as it would be done in any other object oriented program

        I find that pyqt5 handles the GUI stuff quite nicely using code-wise implementation and that adding a designer actually adds a layer of complexity that can make the project a bit more difficult to troubleshoot later on. I say this because the code it seems to create is much more cryptic in nature while the code you can create using code-wise pyqt5 can be done fairly straight forward since you have full control of all that is being done

        Still to each their own if you are more comfortable using a designer then by all means use it just keep in mind if someone else has to pick up where you left off they might have trouble understanding what you did unless they too are already familiar with that specific designer

        madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

        1 Reply Last reply
        0
        • P Offline
          P Offline
          PyGrrl_FL
          wrote on 5 Jun 2019, 01:39 last edited by
          #4

          Hi,

          I am very new to python as well as GUI programming as well. Have you looked into converting your .ui file into a .py file with pyuic? That way you have the framework for the GUI and can add your python code to it.

          1 Reply Last reply
          0
          • D Offline
            D Offline
            Denni
            wrote on 5 Jun 2019, 13:45 last edited by Denni 6 May 2019, 13:46
            #5

            If either of you ( @PyGrrl_FL or @metalshreds ) need help in understanding how to implement your GUI using the code-wise approach as opposed to using a tool just ask. I think once you understand how easy that is to do using pyqt5 you might wonder why those designers are even being used (I know I wonder why sometimes).

            madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

            P 1 Reply Last reply 5 Jun 2019, 13:56
            0
            • D Denni
              5 Jun 2019, 13:45

              If either of you ( @PyGrrl_FL or @metalshreds ) need help in understanding how to implement your GUI using the code-wise approach as opposed to using a tool just ask. I think once you understand how easy that is to do using pyqt5 you might wonder why those designers are even being used (I know I wonder why sometimes).

              P Offline
              P Offline
              PyGrrl_FL
              wrote on 5 Jun 2019, 13:56 last edited by
              #6

              @Denni Hi, I for one would love to understand GUI implementation using the code-wise approach as opposed to using Qt Designer. I am reading all I can and trying many different things but sometimes getting lost in all of the information and different tools/techniques out there.

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Denni
                wrote on 5 Jun 2019, 15:30 last edited by Denni 6 Jun 2019, 16:24
                #7

                Okay well my first bit of advise is to chew on it a little bit at a time get something working save that, make a copy, and then play with it by tweaking it a little. Document each of these changes as you save them to help you remember what you added at each stage so that you can easily go back and remove or pull out the bits and pieces you might need later on for another project. To help you all get started here is a fairly basic program that gives you a bit more meat to play with than most of the standard examples I came across and used to build this one. Still this was built using what is already out there.

                Note wherever you end up saving this program create an images folder there and put your two images within that folder and either name them what I did or change the names I give to match your own.

                import sys
                import time
                import sqlite3
                
                from collections import deque
                
                # The following is down-and-dirty as one should only import what one actually needs
                # Still when playing around with stuff this makes it a lot easier
                from PyQt5.QtCore    import *
                from PyQt5.QtGui     import *
                from PyQt5.QtWidgets import *
                
                ############################## SQLite3 Database Class ##############################
                class sqlDatabase:
                  # This class would handle everything pertinenting to ones Database
                    def __init__(self,filename):
                        self.__dbaseName = filename
                        self.__SQLDef = ''
                
                    def GetCatGroups(self):
                      # This simulates what one would get back from a database Query
                        CatGrpRecSet = [
                            {'CatgryName':'All',           'GroupName':''} ,
                            {'CatgryName':'FirstCategory', 'GroupName':'Group-1'} ,
                            {'CatgryName':'FirstCategory', 'GroupName':'Group-2'} ,
                            {'CatgryName':'FirstCategory', 'GroupName':'Group-3'} ,
                            {'CatgryName':'SecndCategory', 'GroupName':'Group-4'} ,
                            {'CatgryName':'SecndCategory', 'GroupName':'Group-5'} ,
                            {'CatgryName':'SecndCategory', 'GroupName':'Group-6'} ,
                            {'CatgryName':'ThirdCategory', 'GroupName':'Group-7'} ,
                            {'CatgryName':'ThirdCategory', 'GroupName':'Group-8'} ,
                            {'CatgryName':'ThirdCategory', 'GroupName':'Group-9'} 
                            ]
                        return CatGrpRecSet
                
                    def GetItemData(self, CatGrpSlctd):
                      # This simulates what one would get back from a database Query
                        if CatGrpSlctd == 'All':
                            ItmRecSet = [
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-01'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-02'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-03'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-04'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-05'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-06'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-07'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-08'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-09'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-11'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-12'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-13'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-14'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-15'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-16'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-17'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-18'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-19'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-21'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-22'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-23'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-24'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-25'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-26'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-27'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-28'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-29'}
                                ]
                        elif CatGrpSlctd in (['FirstCategory', 'Group-1', 'Group-2', 'Group-3']):
                            ItmRecSet = [
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-01'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-02'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-1', 'ItemName':'Item-03'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-04'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-05'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-2', 'ItemName':'Item-06'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-07'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-08'},
                                {'CatgryName':'FirstCategory', 'GroupName':'Group-3', 'ItemName':'Item-09'}
                                ]
                        elif CatGrpSlctd in (['SecndCategory', 'Group-4', 'Group-5', 'Group-6']):
                            ItmRecSet = [
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-11'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-12'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-4', 'ItemName':'Item-13'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-14'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-15'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-5', 'ItemName':'Item-16'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-17'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-18'},
                                {'CatgryName':'SecndCategory', 'GroupName':'Group-6', 'ItemName':'Item-19'}
                                ]
                        elif CatGrpSlctd in (['ThirdCategory', 'Group-7', 'Group-8', 'Group-9']):
                            ItmRecSet = [
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-21'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-22'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-7', 'ItemName':'Item-23'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-24'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-25'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-8', 'ItemName':'Item-26'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-27'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-28'},
                                {'CatgryName':'ThirdCategory', 'GroupName':'Group-9', 'ItemName':'Item-29'}
                                ]
                        return ItmRecSet
                
                ############################## Category Groups Tree List ##############################
                class CatGroupTree(QTreeView):
                    def __init__(self, parent):
                        QTreeView.__init__(self, parent)
                        self.CntrPane = parent
                
                        self.model = QStandardItemModel()
                        self.model.setHorizontalHeaderLabels(['Category/Group'])
                        self.setModel(self.model)
                
                        self.clicked.connect(self.__itemSingleClicked)
                        self.setEditTriggers(QAbstractItemView.NoEditTriggers)
                
                    @property
                    def CntrPane(self):
                        return self.__parent
                
                    @CntrPane.setter
                    def CntrPane(self, value):
                        self.__parent = value
                 
                    def SetContent(self, tmpCatGrpList):
                        self.model.setRowCount(0)
                        TreeRoot = self.model.invisibleRootItem()
                        SeenCat = {}
                        QuedData = deque(tmpCatGrpList)
                
                        while QuedData:
                            Itm = QuedData.popleft()
                            CurNode = TreeRoot
                            CatNam = Itm['CatgryName']
                            GrpNam = Itm['GroupName']
                
                            if CatNam in SeenCat:
                                CurNode = SeenCat[CatNam]
                                CurNode.appendRow([QStandardItem(GrpNam)])
                            else:
                                CurNode.appendRow([QStandardItem(CatNam)])
                                if len(GrpNam) > 0:
                                    CurNode = CurNode.child(CurNode.rowCount() - 1)
                                    CurNode.appendRow([QStandardItem(GrpNam)])
                
                                SeenCat[CatNam] = CurNode
                        
                        # Initialize Selection to First Row 'All'
                        self.setCurrentIndex(self.model.index(0, 0))
                
                    def __itemSingleClicked(self, index):
                        Item = self.selectedIndexes()[0]
                        ItemVal = Item.model().itemFromIndex(index).text()
                        self.CntrPane.RefrshTreeSelctd(ItemVal)
                
                ############################## Item Data List ##############################
                class ItemDsplyr(QTreeView):
                    def __init__(self, parent):
                        QTreeView.__init__(self, parent)
                        self.CntrPane = parent
                
                        self.model = QStandardItemModel(0, 3)
                        self.model.setHorizontalHeaderLabels(['CatgryName', 'GroupName', 'ItemName'])
                
                        self.setModel(self.model)
                        self.clicked.connect(self.__itemSingleClicked)
                
                    @property
                    def CntrPane(self):
                        return self.__parent
                
                    @CntrPane.setter
                    def CntrPane(self, value):
                        self.__parent = value
                
                    def SetContent(self, tmpItmList):
                        self.model.setRowCount(0)
                
                        for Item in tmpItmList:
                            if Item['CatgryName'] != 'All':
                                ItmNam = QStandardItem(Item['ItemName'])
                                CatNam = QStandardItem(Item['CatgryName'])
                                GrpNam = QStandardItem(Item['GroupName'])
                
                                self.model.appendRow([CatNam, GrpNam, ItmNam])
                
                    def __itemSingleClicked(self, index):
                        Item = self.selectedIndexes()[0]
                        ItemVal = Item.model().itemFromIndex(index).text()
                        self.CntrPane.RefrshListSelctd(ItemVal)
                
                class CenterPane(QWidget):
                    def __init__(self, parent, dbase):
                        QWidget.__init__(self)
                    # The Parent (MainWindow) handle is being passed in just in case the CenterPane needs to communicate back up to the MainWindow
                    # Other things can be passed in as well if needed such as a handle to the database
                        self.MainWin = parent
                        self.Dbase = dbase
                        
                        self.TreeItem = 'All'
                        self.ListItem = ''
                
                        CatGrpList = self.Dbase.GetCatGroups()
                        ItemList   = self.Dbase.GetItemData(self.TreeItem)
                
                        self.CatGrpTree = CatGroupTree(self)
                        self.CatGrpTree.SetContent(CatGrpList)
                
                        self.ItemDsply = ItemDsplyr(self)
                        self.ItemDsply.SetContent(ItemList)
                
                        CntrPane = QSplitter(Qt.Horizontal, self)
                        CntrPane.addWidget(self.CatGrpTree)
                        CntrPane.addWidget(self.ItemDsply)
                        CntrPane.setSizes([75,200])
                
                        hbox = QHBoxLayout(self)
                        hbox.addWidget(CntrPane)
                
                        self.setLayout(hbox)
                
                    @property
                    def MainWin(self):
                        return self.__parent
                
                    @MainWin.setter
                    def MainWin(self, value):
                        self.__parent = value
                
                    # Local Handle to the Database
                    @property
                    def Dbase(self):
                        return self.__Database
                
                    @Dbase.setter
                    def Dbase(self, value):
                        self.__Database = value
                
                    @property
                    def TreeItem(self):
                        return self.__treeItmSelctd
                
                    @TreeItem.setter
                    def TreeItem(self, value):
                        self.__treeItmSelctd = value
                
                    @property
                    def ListItem(self):
                        return self.__listItmSelctd
                
                    @ListItem.setter
                    def ListItem(self, value):
                        self.__listItmSelctd = value
                
                    def RefrshTreeSelctd(self, TreeItmSlctd):
                        print("Tree Item Clicked:",TreeItmSlctd)
                        if TreeItmSlctd != self.TreeItem:
                            self.TreeItem = TreeItmSlctd
                            #Retrieve new data and repopulate List
                            ItmList = self.Dbase.GetItemData(self.TreeItem)
                            self.ItemDsply.SetContent(ItmList)
                            self.ListItem = ''
                
                    def RefrshListSelctd(self, LstItmSlctd):
                        print("List Item Clicked:",LstItmSlctd)
                        if LstItmSlctd != self.ListItem:
                            self.ListItem = LstItmSlctd
                
                            print("******* New Item")
                
                class MenuToolBar(QDockWidget):
                    def __init__(self, parent):
                        QDockWidget.__init__(self)
                        self.MainMenu = parent.menuBar()
                        
                        # ******* File Menu Items *******
                        self.FileMenu  = self.MainMenu.addMenu('File')
                
                        self.OpenFileAct = QAction(QIcon('images/open.ico'), 'Open File', self)
                        self.OpenFileAct.setShortcut("Ctrl+O")
                        self.OpenFileAct.setStatusTip('Open an Existing File')
                        self.OpenFileAct.triggered.connect(self.__windowMenuFile)
                        self.FileMenu.addAction(self.OpenFileAct)
                        
                        self.InitToolBar(parent)
                
                    def InitToolBar(self, parent):
                      # Add Menu item to the Toolbar
                        self.mainToolBar = parent.addToolBar("Quick Access")
                        self.mainToolBar.addAction(self.OpenFileAct)
                
                    def __windowMenuFile(self):
                      # Stub function just to give something to play with
                        (value, choice) = QInputDialog.getText(
                            self, "Retrieve File","Please provide a file to retrieve",
                            QLineEdit.Normal, "FilePath/FileName.ext")
                        if choice:
                            print("Choice :",choice)
                
                
                class Window(QMainWindow):
                    def __init__(self, DatabaseFilePath, parent=None):
                        super(Window, self).__init__(parent)
                
                        self.dbase = sqlDatabase(DatabaseFilePath)
                 
                        LeftCorner   = 100   # Distance in from the left edge of the screen
                        TopCorner    = 100   # Distance down from the top edge of the screen
                        WindowWidth  = 800
                        WindowHeight = 600
                        MinWndowWdth = 425
                        WindowIcon = 'images/favicon.png'   # Locate the images folder where this program is run from
                
                        self.setWindowTitle('Main Window')
                        self.setGeometry(LeftCorner, TopCorner, WindowWidth, WindowHeight)
                        self.setWindowIcon(QIcon(WindowIcon))
                        self.setMinimumWidth(MinWndowWdth)
                
                        # A Window is made of of these regions from top to bottom: Menu Bar, Toolbar, Center Pane, and Status Bar
                        # A class should be created to handle each one of these as separate units 2 examples are given
                        self.setCentralWidget(CenterPane(self, self.dbase))
                        # Note the Toolbar is simply an extension of the Menu system and are dealt with as one unit
                        self.MenuToolBar = MenuToolBar(self)
                        self.SetStatusBar()
                
                        self.setStyle(QStyleFactory.create('Cleanlooks'))
                
                    def SetStatusBar(self):
                      # Basically a stub for augmentation later on
                        StatusMsg = ''
                        self.StatBar = self.statusBar()
                
                        if len(StatusMsg) < 1:
                            StatusMsg = 'Ready'
                
                        self.StatBar.showMessage(StatusMsg)
                
                if __name__ == "__main__":
                  # This uses/receives no command line arguements
                    baseThread = QApplication([])
                    
                    DbaseToUse = 'FullDatabasePathAndName'
                    
                    baseGUI = Window(DbaseToUse)   #----- This defines and implements the GUI interface
                    baseGUI.show()
                
                    sys.exit(baseThread.exec_())   #----- This launches the baseThread within which the baseGUI is contained
                
                

                madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved