Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. Model/View mapping to dynamically-generated widgets?
Forum Updated to NodeBB v4.3 + New Features

Model/View mapping to dynamically-generated widgets?

Scheduled Pinned Locked Moved Language Bindings
6 Posts 3 Posters 2.4k Views 1 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.
  • A Offline
    A Offline
    Alabaster
    wrote on last edited by
    #1

    Hello,

    The model/view concept is fairly new to me and I'm trying to understand it. Most of the examples I can find online involve the QListView, QTableView, QTreeView, etc., but for my application I would prefer to map to labels & buttons. The labels & buttons are dynamically generated so there is no fixed layout.

    From some initial research it looks like I need to work with QDataWidgetMapper, but I'm having trouble finding helpful examples.

    Below is an example of some of the convoluted steps I often take (without model/view approach). My impression is that a model/view approach will greatly simplify this.

    If someone could either a.) point me in the direction of some clear examples/tutorials for mapping model data to (non Q?View) widgets, and/or b.) give me some suggestions for re-writing the code below in a model/view paradigm, I wouild appreciate it.

    Thanks

    @from PySide.QtGui import *
    from PySide.QtCore import *
    from random import choice
    import sys

    class MainWindow(QMainWindow):
    def init(self, thingList):
    super(MainWindow, self).init()
    self.initUI(thingList)

    def initUI(self, thingList):
        cw = centralWidget(thingList)
        self.setCentralWidget(cw)
        self.setWindowTitle("How can I do the same with model/view (& QDataWidgetMapper?)")
        self.show()
    

    class centralWidget(QWidget):
    def init(self, thingList):
    super(centralWidget, self).init()
    self.initUI()
    self.thingList = thingList

    def initUI(self):
        self.vbox = QVBoxLayout()
        self.actionLabel = QLabel("No Buttons have been Clicked")
        self.vbox.addWidget(self.actionLabel)
    
        self.g = QGridLayout()
    
        col=0
        row=0
        columnBreak = len(thingList) / 2
        for index, thing in enumerate(thingList):
            newHBox = QHBoxLayout()
    
    
            newLabel = thing[4]
    
            newHBox.addWidget(newLabel)
            for button in thing[2]:
                newHBox.addWidget(button)
                button.clicked.connect(self.somethingChanged)
    
            newComboBox = thing[3]
            newComboBox.currentIndexChanged.connect(self.somethingChanged)
            newHBox.addWidget(newComboBox)
            newHBox.addStretch(1)
            self.g.addLayout(newHBox, row, col)
            row += 1
            if row >= columnBreak:
                row = 0
                col += 1
    
        self.setMinimumWidth(500)
        self.vbox.addLayout(self.g)
        self.setLayout(self.vbox)
        self.show()
        
    ###########################################
    # Needlessly complicated series of methods
    # used for translating user input into 
    # property changes of "thing."
    # I assume that model/view will simplify this?
    ############################################
    
    def changeValue(self, sender, thing, index):
        bools = thing[1]
        comboBox = thing[3]
        thingLabel = thing[4]
        originalThingName = thing[5]
    
        if comboBox.currentText() == "":
            thingName = originalThingName
        else:
            thingName = "{0}_{1}".format(thing[0], comboBox.currentText().replace(" ", ""))
    
        thingLabel.setText(thingName)
    
    
        if type(sender) == QPushButton:
            if sender.isChecked():
                bools[index] = True
            else:
                bools[index] = False
    
        message = "{0}: New Values: {1} - {2} - {3} - {4}.  New Name: {5}".format(thing[0], bools[0], bools[1], bools[2], bools[3], thingName)
        self.actionLabel.setText(message)
        newData = [thingName, [bools[0], bools[1], bools[2], bools[3]], originalThingName]
        self.setThingValues(newData)
    
    
    def findSenderThing(self, sender):
        for thing in self.thingList:
            if sender == thing[3]:
                index = None
                return thing, index
            if sender in thing[2]:
                index = thing[2].index(sender)
                return thing, index
    
    
    def setThingValues(self, newData):
        print("\n\nADJUSTED THINGLIST:\n")
        for thing in thingList:
            newThingName = newData[0]
            newBoolsList = newData[1]
            originalThingName = newData[2]
    
            if thing[5] == originalThingName:
                thing[0] = newThingName
                thing[1] = newBoolsList
    
            print("\t{0}\t{1}\t(Originally: {2})".format(thing[0], thing[1], thing[5]))
    
    
    def somethingChanged(self):
        sender = self.sender()
        thing, index = self.findSenderThing(sender)
        self.changeValue(sender, thing, index)
    

    def generateDummyData():
    rnd = choice(range(15, 40))
    thingList = []

    for x in range(rnd):
        thingName = "Thing {0}".format(str(x))
        originalThingName = thingName
    
        newLabel = QLabel(thingName)
        newLabel.setFixedWidth(80)
    
        boolList = []
        buttonList = []
        while len(boolList) < 4:
            randBool = choice([True, False])
            boolList.append(randBool)
            newButton = QPushButton(str(len(boolList)))
            newButton.setCheckable(True)
            newButton.setFixedSize(20,20)
            buttonList.append(newButton)
    
            newComboBox = QComboBox()
            newComboBox.addItems(['', 'ABC', 'DEF', 'GHI', ' OCD', 'MNO'])
    
        newThing = [thingName, boolList, buttonList, newComboBox, newLabel, originalThingName]
        for bool in boolList:
            if bool:
                buttonList[boolList.index(bool)].setChecked(True)
        thingList.append(newThing)
    return thingList
    

    if name == 'main':
    app = QApplication(sys.argv)
    thingList = generateDummyData()
    win = MainWindow(thingList)
    sys.exit(app.exec_())@

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      It is not completely clear on what is required here. Do you want to use your own widgets to display the data present in model ? If that is the case, please try to use the Delegates for this. You need to write custom delegates for this. I'm not familiar with pyqt. I have examples to share using Qt C++ for custom delegates.

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • A Offline
        A Offline
        Alabaster
        wrote on last edited by
        #3

        Thanks for your response. To clarify my question:

        Basically I'm looking to make the jump into the model/view paradigm, but the only useful information I can find is on using QListView, QTableView, and QTreeView. None of which exactly fit my needs (I'm looking to create more of a button/combobox GUI).

        My research has pointed me in the direction of QDataWidgetMapper but any information I've found has been over my head, and I wondered if someone could explain, show some examples, or point me in the direction of some decent tutorials.

        The sample code I provided is an example of how I often find myself doing things (sans model/view) -- which, I believe, is convoluted and error-prone. I suspect that I could eliminate a lot of my "middle-man" methods/functions if I used a model/view approach. I figure someone who knows what they're doing might be able to suggest how I could accomplish the same (in fewer lines of code) .

        Thanks

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

          ok. My suggestion is not get into ModelView directly. If your intent is to create simple UI with button and combo box, just create the UI using buttons/combobox and layouts. This will help you.

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          0
          • A Offline
            A Offline
            Alabaster
            wrote on last edited by
            #5

            That is what I have been doing so far, but my code seems very inefficient. Notice all of the methods of my centralWidget class. (My actual application is much more complex than the example I posted).

            Is there any way to set "thingList" as a model and map each item's True/False values directly to the buttons?

            I think your first response (to use custom delegates) may be what I'm looking for but I don't understand it -- can you point me in the direction of some simple examples?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Search for "Simple Widget Mapper Example" in Qt's documentation. It should give you the basics to start your code the right way.

              Hope it helps

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              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