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. Getting Row from ListWidget
QtWS25 Last Chance

Getting Row from ListWidget

Scheduled Pinned Locked Moved Solved Qt for Python
pyside2pythonqt for python
11 Posts 4 Posters 4.0k Views
  • 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.
  • B Offline
    B Offline
    BD4L
    wrote on last edited by
    #1

    I'm trying to figure out how to get the selected row from a list widget. Currently I have a method that will get me the text of the row but I need to find the actual position. (Basically I have a dictionary with duplicate values but unique keys the list widget is displaying the values but I need to know which unique key which is handled by position) Here's what I've got so far:

    import sys
    from PySide2 import QtCore, QtGui, QtWidgets
    
    # Create Test List/Dictionary
    list_dict = {1: "First Label", 2: "Second Label", 3: "First Label"}
    
    list_list = [1, 2, 3]
    
    #Create Widgets/Layout
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent = None):
            super(Widget, self).__init__(parent)
            self.listwidget = QtWidgets.QListWidget()
            self.lineedit = QtWidgets.QLineEdit("Nothing clicked")
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(self.listwidget)
            lay.addWidget(self.lineedit)
    
            # Populate List with Values from Dictionary
            for e in list_list:
                value = list_dict.get(e)
                it = QtWidgets.QListWidgetItem()
                it.setData(QtCore.Qt.DisplayRole, value)
                self.listwidget.addItem(it)
            
            self.listwidget.itemClicked.connect(self.on_item_clicked)
        
        @QtCore.Slot(QtWidgets.QListWidgetItem)
        def on_item_clicked(self, item):
            # This gets the text from the list box
            key = item.data(QtCore.Qt.DisplayRole)
            self.lineedit.setText(key)
            
    def main():
        app = QtWidgets.QApplication(sys.argv)
        window = Widget()
        window.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main()
    

    I've tried changing key = to be row.data, self.row, self.currentrow. I've also tried changing the def on_item_clicked to contain self and row instead of self and item, but I haven't figured out any way to get the row passed from the listwidget into my function.

    Note: Currently I'm using the lineedit box to report out what is passed into key just to help me check the code.

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      The currently selected rows can be retrieved through the selection model

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • B Offline
        B Offline
        BD4L
        wrote on last edited by
        #3

        That definitely got me closer. I was able to find this site that gives me the python syntax for the selection model: https://doc.qt.io/qtforpython/PySide2/QtCore/QItemSelectionModel.html, but I'm still having trouble getting it to work in the code.

        I edited the on_item_clicked(self,item) function to now have

                active_item = QtCore.QItemSelectionModel.selectedRows
                self.lineedit.setText(str(active_item))
        

        But the value returned by active item is:

        <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>
        

        How do I actually get the value? I tried wrapping it in item.data like I had previously with the display role but that gives me an error.

        JonBJ 1 Reply Last reply
        0
        • B BD4L

          That definitely got me closer. I was able to find this site that gives me the python syntax for the selection model: https://doc.qt.io/qtforpython/PySide2/QtCore/QItemSelectionModel.html, but I'm still having trouble getting it to work in the code.

          I edited the on_item_clicked(self,item) function to now have

                  active_item = QtCore.QItemSelectionModel.selectedRows
                  self.lineedit.setText(str(active_item))
          

          But the value returned by active item is:

          <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>
          

          How do I actually get the value? I tried wrapping it in item.data like I had previously with the display role but that gives me an error.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @BD4L
          You need to get the selection model of the QListWidget instance you have. So:

          self.listwidget.selectionModel().selectedRows()
          

          would give you a list of QModelIndexes into your model.

          Depending on what you want, see e.g. https://doc.qt.io/qt-5/qlistwidget.html#selectedItems which gives you a list of QListWidgetItems without going via indexes.

          Your "but I need to know which unique key which is handled by position" sounds a bit dodgy, but up to you. Another way of dealing with such an issue is to store the necessary discriminatory item (your unique key) in the list item data, so that the value you get back includes whatever is needed to distinguish, rather than relying on looking at row numbers. Which is then more flexible, e.g. if rows get reordered.

          1 Reply Last reply
          -1
          • B Offline
            B Offline
            BD4L
            wrote on last edited by
            #5

            @Denni-0 That code worked fine with Pyside2, but it ran into the same issue I had earlier where it gives me the text from the row but doesn't give me the row ID. I am grateful for a lot of your suggestions there, a lot of the code I'm using is pulled together from tutorials online etc. and I'm still trying to pick apart what it all means. So some clarification on when not to do things is great.

            @JonB I tried using that line of code but got the same value I did before of <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>. I'd be interested in learning another way to handle the keys but I need to give you a better description of the full data I'm dealing with. I have a dictionary with the following structure:

            countries_dict = {1 : {"name" :  "United Kingdom", "abbrev"  : "UK", "pop" :  66.44, "cities" : 
                                          { 1 : {"name" : "London", "pop" : 8.9}, 2 : {"name" : "York",  "pop" : 0.04}} , 
                              2 : {"name" :  "United States", "abbrev"  : "US", "pop" :  327.2, "cities" :
                                          { 1 : {"name" : "Springfield,", "pop" : 0.16, "state" : "MO"}, 2 : {"name" : "Springfield",  "pop" : 0.11, "state" : "IL"}}}
            

            Sorry I know the formatting isn't great. I also can't use the actual data from my dictionary and this was the closest idea I could come up with to replicate it. Basically I'm dealing with nested dictionaries that are identified by unique keys because the name for each item can be duplicated (see US example above where both cities are named Springfield.

            I'm still very new to QT so I've been trying to build up my document slowly but what I will need to have eventually is a list box containing all of the first level items (in this case it would be United Kingdom and United States). When one of those is selected from the list box I will need other fields to populate (in this example it would be a text box for population, and another list box for cities - including only the cities from that country). Then when they select a city from the second list box it would populate another text box (city population) and a combo box (state).

            Users will need to be able to add countries and cities dynamically so I can't really make each country its own dictionary, but the order that they are doesn't matter to the users so I have it as a fixed order based on when each item was added to the dictionary (the list boxes don't need to allow for items to be reordered). Which is why my current plan is to just extract the row index from the selected item match that to the list index used to populate the list and then look up the matching dictionary item by the ID stored in the list at that location.

            The current dictionary structure is working really well for the program from a command line standpoint (I can easily display, manipulate, add, delete and modify data) but now we need to make it accessible to users which means a GUI which is something I'm not very familiar with unfortunately.

            So if there's a way to store the unique id in the list element but have it not be visible to the user, that would be amazing and get me closer to how the command line version functions, but this is the closest idea I've had so far to dealing with the data structure I have.

            Thanks again to everyone for their help so far.

            JonBJ 1 Reply Last reply
            0
            • B Offline
              B Offline
              BD4L
              wrote on last edited by
              #6

              That would be awesome, thanks. Just so you're aware, my current plan was to figure out how to get the selected row from the listbox and then compare that to the the index of the list list that I'm using to drive loading the list box (ListList in the code). Which would then return the unique key which I can store and use to access the correct section of the dictionary both at that point and when a selection is made in the child listbox.

              The way I'm currently handling this is to print the unique id and name of each country to the command line and ask users to enter the ID key which I then use to retrieve the data. I was hoping, as part of moving to the gui version) to make those unique keys invisible so users just have to select the name of what they're looking for. I have gotten it to work by concatenating the key and value from the dictionary displaying that as a string in the list box, then getting the text from the list box removing the unique ID and accessing the dictionary directly, but that's not ideal.

              Thanks again for all your help.

              1 Reply Last reply
              0
              • B BD4L

                @Denni-0 That code worked fine with Pyside2, but it ran into the same issue I had earlier where it gives me the text from the row but doesn't give me the row ID. I am grateful for a lot of your suggestions there, a lot of the code I'm using is pulled together from tutorials online etc. and I'm still trying to pick apart what it all means. So some clarification on when not to do things is great.

                @JonB I tried using that line of code but got the same value I did before of <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>. I'd be interested in learning another way to handle the keys but I need to give you a better description of the full data I'm dealing with. I have a dictionary with the following structure:

                countries_dict = {1 : {"name" :  "United Kingdom", "abbrev"  : "UK", "pop" :  66.44, "cities" : 
                                              { 1 : {"name" : "London", "pop" : 8.9}, 2 : {"name" : "York",  "pop" : 0.04}} , 
                                  2 : {"name" :  "United States", "abbrev"  : "US", "pop" :  327.2, "cities" :
                                              { 1 : {"name" : "Springfield,", "pop" : 0.16, "state" : "MO"}, 2 : {"name" : "Springfield",  "pop" : 0.11, "state" : "IL"}}}
                

                Sorry I know the formatting isn't great. I also can't use the actual data from my dictionary and this was the closest idea I could come up with to replicate it. Basically I'm dealing with nested dictionaries that are identified by unique keys because the name for each item can be duplicated (see US example above where both cities are named Springfield.

                I'm still very new to QT so I've been trying to build up my document slowly but what I will need to have eventually is a list box containing all of the first level items (in this case it would be United Kingdom and United States). When one of those is selected from the list box I will need other fields to populate (in this example it would be a text box for population, and another list box for cities - including only the cities from that country). Then when they select a city from the second list box it would populate another text box (city population) and a combo box (state).

                Users will need to be able to add countries and cities dynamically so I can't really make each country its own dictionary, but the order that they are doesn't matter to the users so I have it as a fixed order based on when each item was added to the dictionary (the list boxes don't need to allow for items to be reordered). Which is why my current plan is to just extract the row index from the selected item match that to the list index used to populate the list and then look up the matching dictionary item by the ID stored in the list at that location.

                The current dictionary structure is working really well for the program from a command line standpoint (I can easily display, manipulate, add, delete and modify data) but now we need to make it accessible to users which means a GUI which is something I'm not very familiar with unfortunately.

                So if there's a way to store the unique id in the list element but have it not be visible to the user, that would be amazing and get me closer to how the command line version functions, but this is the closest idea I've had so far to dealing with the data structure I have.

                Thanks again to everyone for their help so far.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @BD4L said in Getting Row from ListWidget:

                @JonB I tried using that line of code but got the same value I did before of <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>.

                I don't understand, and you should show the actual code you tried. What I wrote should work. The message you quote should --- as in your original code --- result from trying to output

                self.listwidget.selectionModel().selectedRows
                

                rather than what I wrote, which is:

                self.listwidget.selectionModel().selectedRows()
                

                Did you copy what I wrote, or did you do your own thing as per the first example above instead of the second?

                1 Reply Last reply
                -1
                • B Offline
                  B Offline
                  BD4L
                  wrote on last edited by
                  #8

                  Hey friends, you guys are awesome thanks. Here's my replies

                  @JonB I copied the text directly into my slot so:

                  @QtCore.Slot(QtWidgets.QListWidgetItem)
                      def on_item_clicked(self, item):
                          active_item = QtCore.QItemSelectionModel.selectedIndexes
                          self.lineedit.setText(str(active_item))
                  

                  became:

                  @QtCore.Slot(QtWidgets.QListWidgetItem)
                      def on_item_clicked(self, item):
                          active_item = self.listwidget.selectionModel().selectedRows()
                          self.lineedit.setText(str(active_item))
                  

                  I'm not sure if I put that in the wrong spot or why it didn't work, but it still gave me the same error as before. However the code from @Denni-0 worked so I now have the info I need.

                  Denni-O, I just had a question about why you did something in your changes. I get adding the second line display to show the second piece of information but why did you put both of the line edit items into an HBox and then wrap that inside the VBox. Would it have worked just to add both of them into the VBox layout?

                  JonBJ 1 Reply Last reply
                  0
                  • B BD4L

                    Hey friends, you guys are awesome thanks. Here's my replies

                    @JonB I copied the text directly into my slot so:

                    @QtCore.Slot(QtWidgets.QListWidgetItem)
                        def on_item_clicked(self, item):
                            active_item = QtCore.QItemSelectionModel.selectedIndexes
                            self.lineedit.setText(str(active_item))
                    

                    became:

                    @QtCore.Slot(QtWidgets.QListWidgetItem)
                        def on_item_clicked(self, item):
                            active_item = self.listwidget.selectionModel().selectedRows()
                            self.lineedit.setText(str(active_item))
                    

                    I'm not sure if I put that in the wrong spot or why it didn't work, but it still gave me the same error as before. However the code from @Denni-0 worked so I now have the info I need.

                    Denni-O, I just had a question about why you did something in your changes. I get adding the second line display to show the second piece of information but why did you put both of the line edit items into an HBox and then wrap that inside the VBox. Would it have worked just to add both of them into the VBox layout?

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @BD4L

                    but it still gave me the same error as before

                    So to quote you from before:

                    active_item = QtCore.QItemSelectionModel.selectedRows
                    self.lineedit.setText(str(active_item))
                    But the value returned by active item is:

                    <method 'selectedRows' of 'PySide2.QtCore.QItemSelectionModel' objects>

                    You are saying that it shows the same string, with method 'selectedRows' in it, when you replace the first line with:

                    active_item = self.listwidget.selectionModel().selectedRows()
                    

                    You get the same str(active_item) result string with "method" in it in the second case, do you?

                    1 Reply Last reply
                    -1
                    • B Offline
                      B Offline
                      BD4L
                      wrote on last edited by
                      #10

                      @JonB Yeah I do. But if I use self.listwidget.currentRow() (from Denni-O's code) it works.

                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        BD4L
                        wrote on last edited by
                        #11

                        Awesome, thanks. I'll keep that in mind and put in some checks just to make sure.

                        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