Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QListWidget not updating
Forum Updated to NodeBB v4.3 + New Features

QListWidget not updating

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 2 Posters 1.9k 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.
  • I Offline
    I Offline
    Iliass
    wrote on last edited by
    #1

    Hi,
    I'm adding items to a QlistIdget by Iterating through a list, each element has certain info to display and a link to an image to download.
    It's working fine my only problem is that it takes too long.
    What happens is that all items are shown at once. Which means that depending on the size of the list and my data, it may take minutes to show everything.
    I already have an idea for the network issue but I still can't fix the everything shown at once issue.
    I'm using python and qt5.

    JonBJ 1 Reply Last reply
    0
    • I Iliass

      Hi,
      I'm adding items to a QlistIdget by Iterating through a list, each element has certain info to display and a link to an image to download.
      It's working fine my only problem is that it takes too long.
      What happens is that all items are shown at once. Which means that depending on the size of the list and my data, it may take minutes to show everything.
      I already have an idea for the network issue but I still can't fix the everything shown at once issue.
      I'm using python and qt5.

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Iliass
      Sounds like you are doing this in blocking loop if you mean "all items are shown at once [at the end]"? Do not do that. Either add each item to the list when it arrives (however you determine that) via a signal, or use a QTimer to add a certain number at a time from some list of pending items to add which you have created.

      I 1 Reply Last reply
      2
      • JonBJ JonB

        @Iliass
        Sounds like you are doing this in blocking loop if you mean "all items are shown at once [at the end]"? Do not do that. Either add each item to the list when it arrives (however you determine that) via a signal, or use a QTimer to add a certain number at a time from some list of pending items to add which you have created.

        I Offline
        I Offline
        Iliass
        wrote on last edited by
        #3

        @JonB Yeah, I'm using a loop.
        I'm quite new, could you link a few examples for each?
        Thanks a lot, it's driving me mad lol

        JonBJ 1 Reply Last reply
        0
        • I Iliass

          @JonB Yeah, I'm using a loop.
          I'm quite new, could you link a few examples for each?
          Thanks a lot, it's driving me mad lol

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

          @Iliass
          Show the fragment of (relevant!) code where you receive or accept these new items and where you add them to your list widget.

          I 1 Reply Last reply
          1
          • JonBJ JonB

            @Iliass
            Show the fragment of (relevant!) code where you receive or accept these new items and where you add them to your list widget.

            I Offline
            I Offline
            Iliass
            wrote on last edited by Iliass
            #5

            @JonB

            def search(self):
                    
                    // this is how I create my list
                    self.listWidget.clear()
                    self.gogo.keywordSetter(self.lineEdit.text())
                    self.gogo.linkSetter()
                    self.gogo.resultsGetter()
                    
                    // iterating through the list
                    for x in self.gogo.resultsContainer:
                        self.listWidget.update() // an attempt to update the list (doesn't work lol)
                        #print(x[2])
                        url = x[2] // unnecessary
                        print(url) // just to check
                        
            
            
                        // reuesting the image
                        req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
                        webpage = urlopen(req).read()
                        
                        pixmap = QPixmap()
                        pixmap.loadFromData(webpage)
                        icon = QIcon(pixmap)
                        //creating the item
                        item = QListWidgetItem(icon, x[1])
                        size = QSize()
                        size.setHeight(100)
                        size.setWidth(400)
                        item.setSizeHint(size)
                        #item.iconSize(QSize(100, 400))
                        self.listWidget.addItem(item)
            

            here it is
            Thanks in advance

            JonBJ 1 Reply Last reply
            0
            • I Iliass

              @JonB

              def search(self):
                      
                      // this is how I create my list
                      self.listWidget.clear()
                      self.gogo.keywordSetter(self.lineEdit.text())
                      self.gogo.linkSetter()
                      self.gogo.resultsGetter()
                      
                      // iterating through the list
                      for x in self.gogo.resultsContainer:
                          self.listWidget.update() // an attempt to update the list (doesn't work lol)
                          #print(x[2])
                          url = x[2] // unnecessary
                          print(url) // just to check
                          
              
              
                          // reuesting the image
                          req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
                          webpage = urlopen(req).read()
                          
                          pixmap = QPixmap()
                          pixmap.loadFromData(webpage)
                          icon = QIcon(pixmap)
                          //creating the item
                          item = QListWidgetItem(icon, x[1])
                          size = QSize()
                          size.setHeight(100)
                          size.setWidth(400)
                          item.setSizeHint(size)
                          #item.iconSize(QSize(100, 400))
                          self.listWidget.addItem(item)
              

              here it is
              Thanks in advance

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #6

              @Iliass
              So the slowness comes from requesting data from a web page, is that where the delay is? You must not write a Qt UI program this way. Do something like: create a repeating QTimer, each time it expires go get one new item and add that.

              Even that may be too slow, if one web request takes a while. I do not know what Request() or urlopen() are/do, maybe some synchronous Python routines? Use Qt's QNetworkAccessManager Class to do your web accesses, then you can use its asynchronous signals & slots to fetch data without blocking the UI.

              1 Reply Last reply
              1
              • I Offline
                I Offline
                Iliass
                wrote on last edited by
                #7

                Not just because of the slowness. Because even when removing the icon and the requests it still waits until the loop is finished to add everything.
                What's bothering is not how much it takes for each item but for everything.
                If I could display one item at a time the wait between each item wouldn't bother me.
                I'll give a try to QNetwork. I'll ask here while I can but can you add an Icon to an item after it was already added?

                JonBJ 1 Reply Last reply
                0
                • I Iliass

                  Not just because of the slowness. Because even when removing the icon and the requests it still waits until the loop is finished to add everything.
                  What's bothering is not how much it takes for each item but for everything.
                  If I could display one item at a time the wait between each item wouldn't bother me.
                  I'll give a try to QNetwork. I'll ask here while I can but can you add an Icon to an item after it was already added?

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Iliass
                  Yes you can/change an icon any time.

                  You must not write code which "waits" for anything to happen in an event-driven UI like Qt. It is a change in the approach required compared to traditional/sequential/synchronous coding. Your UI should normally be sitting doing "nothing", just in its event loop. When something happens --- like data arriving from somewhere --- you respond to it by updating the UI and then return to allowing the event loop to run. Any time you might have a while loop which fetches data and displays it that is not the best approach, you want the UI to respond to data arriving, not requesting and then waiting for it in any kind of loop.

                  I 1 Reply Last reply
                  2
                  • JonBJ JonB

                    @Iliass
                    Yes you can/change an icon any time.

                    You must not write code which "waits" for anything to happen in an event-driven UI like Qt. It is a change in the approach required compared to traditional/sequential/synchronous coding. Your UI should normally be sitting doing "nothing", just in its event loop. When something happens --- like data arriving from somewhere --- you respond to it by updating the UI and then return to allowing the event loop to run. Any time you might have a while loop which fetches data and displays it that is not the best approach, you want the UI to respond to data arriving, not requesting and then waiting for it in any kind of loop.

                    I Offline
                    I Offline
                    Iliass
                    wrote on last edited by Iliass
                    #9

                    @JonB
                    That's very instructive thanks. I have been messing around with qt for a few weeks and this is the first time I hear this (probably my fault lol)
                    So, If I understood it right I should first fetch all the relevant data before entering the loop.
                    Then using signals to add each element?
                    At the end of day what my program does is that it just displays search results with a thumbnail.

                    One way to do it would be to create the list, add all the items use addItems instead of addItem then go through the ListWidget again and use signals to add the thumbnails?

                    I can't post so I'll just edit

                    def resultsGetter4(self,window):
                            #self.resultsContainer = []
                            resultsContainerTemp = []
                            r = requests.get(self.resultsLink)
                            resultsContainerTemp = BeautifulSoup(r.content,'html.parser')
                            resultsContainerTemp = resultsContainerTemp.find("div", attrs = {"class" : "film_list-wrap"}).findAll("div", attrs = {"class" : "flw-item"})
                            for element in resultsContainerTemp:
                                
                                animeInfoContainer = element.find("img")
                                asnimeLinkContainer = element.find("a")
                                #anime = (asnimeLinkContainer['href'],animeInfoContainer['alt'],animeInfoContainer['data-src'])
                                
                                
                                url = animeInfoContainer['data-src']
                                
                                
                                req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
                                webpage = urlopen(req).read()
                                
                                pixmap = QPixmap()
                                pixmap.loadFromData(webpage)
                                icon = QIcon(pixmap)
                                item = QListWidgetItem(icon, animeInfoContainer['alt'])
                                size = QSize()
                                size.setHeight(100)
                                size.setWidth(400)
                                item.setSizeHint(size)
                                #item.iconSize(QSize(100, 400))
                                window.listWidget.addItem(item)
                                
                                
                                
                                #self.resultsContainer.append(anime)
                            #print(self.resultsContainer)
                    

                    This is an alternative way that I had tried yesterday.

                    JonBJ 1 Reply Last reply
                    0
                    • I Iliass

                      @JonB
                      That's very instructive thanks. I have been messing around with qt for a few weeks and this is the first time I hear this (probably my fault lol)
                      So, If I understood it right I should first fetch all the relevant data before entering the loop.
                      Then using signals to add each element?
                      At the end of day what my program does is that it just displays search results with a thumbnail.

                      One way to do it would be to create the list, add all the items use addItems instead of addItem then go through the ListWidget again and use signals to add the thumbnails?

                      I can't post so I'll just edit

                      def resultsGetter4(self,window):
                              #self.resultsContainer = []
                              resultsContainerTemp = []
                              r = requests.get(self.resultsLink)
                              resultsContainerTemp = BeautifulSoup(r.content,'html.parser')
                              resultsContainerTemp = resultsContainerTemp.find("div", attrs = {"class" : "film_list-wrap"}).findAll("div", attrs = {"class" : "flw-item"})
                              for element in resultsContainerTemp:
                                  
                                  animeInfoContainer = element.find("img")
                                  asnimeLinkContainer = element.find("a")
                                  #anime = (asnimeLinkContainer['href'],animeInfoContainer['alt'],animeInfoContainer['data-src'])
                                  
                                  
                                  url = animeInfoContainer['data-src']
                                  
                                  
                                  req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
                                  webpage = urlopen(req).read()
                                  
                                  pixmap = QPixmap()
                                  pixmap.loadFromData(webpage)
                                  icon = QIcon(pixmap)
                                  item = QListWidgetItem(icon, animeInfoContainer['alt'])
                                  size = QSize()
                                  size.setHeight(100)
                                  size.setWidth(400)
                                  item.setSizeHint(size)
                                  #item.iconSize(QSize(100, 400))
                                  window.listWidget.addItem(item)
                                  
                                  
                                  
                                  #self.resultsContainer.append(anime)
                              #print(self.resultsContainer)
                      

                      This is an alternative way that I had tried yesterday.

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by
                      #10

                      @Iliass said in QListWidget not updating:

                      So, If I understood it right I should first fetch all the relevant data before entering the loop.

                      Not really, because (from what you say) that may take a long time to fetch them all and you don't like waiting?

                      I suggested maybe one-at-a-time if you stick with your Python web functions, where each time is called from a QTimer. Or if you change over to QNetworkAccessManager for the web retrieval that can be left to fetch things and emit a signal each time one arrives.

                      I'm afraid this is all very fundamental to using Qt (or other event-driven approach), and I do not have time to write up a lecture course for you :) Maybe someone else wants to explain in more detail. I don't see that you have used a signal/slot in your code. If you have not done so already, take the time to study https://doc.qt.io/qt-5/signalsandslots.html in detail; you must grasp this concept to do anything useful in Qt.

                      I 1 Reply Last reply
                      1
                      • JonBJ JonB

                        @Iliass said in QListWidget not updating:

                        So, If I understood it right I should first fetch all the relevant data before entering the loop.

                        Not really, because (from what you say) that may take a long time to fetch them all and you don't like waiting?

                        I suggested maybe one-at-a-time if you stick with your Python web functions, where each time is called from a QTimer. Or if you change over to QNetworkAccessManager for the web retrieval that can be left to fetch things and emit a signal each time one arrives.

                        I'm afraid this is all very fundamental to using Qt (or other event-driven approach), and I do not have time to write up a lecture course for you :) Maybe someone else wants to explain in more detail. I don't see that you have used a signal/slot in your code. If you have not done so already, take the time to study https://doc.qt.io/qt-5/signalsandslots.html in detail; you must grasp this concept to do anything useful in Qt.

                        I Offline
                        I Offline
                        Iliass
                        wrote on last edited by
                        #11

                        @JonB You've done more than enough, thanks
                        Time to read I guess haha

                        1 Reply Last reply
                        1

                        • Login

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