Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QtWebEngine
  4. Tab title goes in the wrong tab
Forum Updated to NodeBB v4.3 + New Features

Tab title goes in the wrong tab

Scheduled Pinned Locked Moved Unsolved QtWebEngine
6 Posts 2 Posters 848 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.
  • H Offline
    H Offline
    Harborman
    wrote on last edited by
    #1

    Tab titles work just fine until you close a tab (any tab). After that, when you load a page, the title jumps to the wrong tab.
    I've been scratching my head over this for a while. Every tutorial online seems to have this same bug.
    Something messes up the indexing when you close a tab. I tried adding setCurrentIndex(index) to the close tab function, but it doesn't do anything.
    Is there any simple fix to this?

    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtWebEngineWidgets import *
    import sys
    
    
    class Page(QWebEnginePage):
        def __init__(self):
            super(QWebEnginePage, self).__init__()
    
    class Browser(QWebEngineView):
        def contextMenuEvent(self, event):
            self.menus = QMenu()
            action1 = QAction("Copy text", self)
            self.menus.addAction(action1)
    
    class Urlbar(QLineEdit):
        def contextMenuEvent(self, event):
            self.menus = QMenu()
            action1 = QAction("Copy", self)
            self.menus.addAction(action1)
    
    class MainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super(MainWindow, self).__init__(*args, **kwargs)
            self.setMinimumHeight(450)
            self.setMinimumWidth(900)
    
            self.tabs = QTabWidget()
            self.setCentralWidget(self.tabs)
            self.tabs.currentChanged.connect(self.current_tab_changed)
            self.tabs.setTabsClosable(True)
            self.tabs.tabCloseRequested.connect(self.close_tab)
    
            toolbar = QToolBar()
            QToolBar.setContextMenuPolicy(self, Qt.NoContextMenu)
            toolbar.setIconSize(QSize(50, 44))
            toolbar.setMovable(False)
            self.addToolBar(toolbar)
    
            #add new tab button
            cornerw = QPushButton(self.tabs)
            self.tabs.setCornerWidget(cornerw, Qt.TopLeftCorner)
            cornerw.clicked.connect(self.add_new_tab)
    
            #address bar
            self.urlbar = Urlbar()
            toolbar.addWidget(self.urlbar)
            self.urlbar.returnPressed.connect(self.go_to_url)
    
            self.add_new_tab()
            self.show()
    
        def add_new_tab(self):
            index = self.tabs.count()
            browser = Browser()
            title = "New tab"
            self.tabs.addTab(browser, title)
            self.tabs.setCurrentIndex(index)
            page = Page()
            browser.setPage(page)
    
            browser.loadFinished.connect(lambda tabtitle, index=index, browser=browser:self.onLoadFinished(index, browser))
            browser.loadFinished.connect(lambda windowtitle, browser=browser:self.setWindowTitle(browser.page().title()))
            browser.urlChanged.connect(lambda url, browser=browser:self.update_urlbar_and_window(url, browser))
    
        def onLoadFinished(self, index, browser):
            self.tabs.setTabText(index, browser.page().title())
    
        def close_tab(self, index):
            if self.tabs.count() > 1:
                self.tabs.removeTab(index)
            return
    
        def go_to_url(self):
            url = QUrl.fromUserInput(self.urlbar.text()).toString()
            self.tabs.currentWidget().load(QUrl(url))
    
        def update_urlbar_and_window(self, url, browser):
            if browser != self.tabs.currentWidget():
                return
            self.setWindowTitle(self.tabs.currentWidget().page().title())
            self.urlbar.setText(url.toString())
            self.urlbar.setCursorPosition(0)
    
        def current_tab_changed(self, index):
            url = self.tabs.currentWidget().url()
            self.update_urlbar_and_window(url, index)
    
    
    app = QApplication(sys.argv)
    app.setApplicationName("Extreme Tabbing Action")
    window = MainWindow()
    app.exec_()
    
    JonBJ 1 Reply Last reply
    0
    • H Harborman

      Tab titles work just fine until you close a tab (any tab). After that, when you load a page, the title jumps to the wrong tab.
      I've been scratching my head over this for a while. Every tutorial online seems to have this same bug.
      Something messes up the indexing when you close a tab. I tried adding setCurrentIndex(index) to the close tab function, but it doesn't do anything.
      Is there any simple fix to this?

      from PyQt5.QtCore import *
      from PyQt5.QtWidgets import *
      from PyQt5.QtGui import *
      from PyQt5.QtWebEngineWidgets import *
      import sys
      
      
      class Page(QWebEnginePage):
          def __init__(self):
              super(QWebEnginePage, self).__init__()
      
      class Browser(QWebEngineView):
          def contextMenuEvent(self, event):
              self.menus = QMenu()
              action1 = QAction("Copy text", self)
              self.menus.addAction(action1)
      
      class Urlbar(QLineEdit):
          def contextMenuEvent(self, event):
              self.menus = QMenu()
              action1 = QAction("Copy", self)
              self.menus.addAction(action1)
      
      class MainWindow(QMainWindow):
          def __init__(self, *args, **kwargs):
              super(MainWindow, self).__init__(*args, **kwargs)
              self.setMinimumHeight(450)
              self.setMinimumWidth(900)
      
              self.tabs = QTabWidget()
              self.setCentralWidget(self.tabs)
              self.tabs.currentChanged.connect(self.current_tab_changed)
              self.tabs.setTabsClosable(True)
              self.tabs.tabCloseRequested.connect(self.close_tab)
      
              toolbar = QToolBar()
              QToolBar.setContextMenuPolicy(self, Qt.NoContextMenu)
              toolbar.setIconSize(QSize(50, 44))
              toolbar.setMovable(False)
              self.addToolBar(toolbar)
      
              #add new tab button
              cornerw = QPushButton(self.tabs)
              self.tabs.setCornerWidget(cornerw, Qt.TopLeftCorner)
              cornerw.clicked.connect(self.add_new_tab)
      
              #address bar
              self.urlbar = Urlbar()
              toolbar.addWidget(self.urlbar)
              self.urlbar.returnPressed.connect(self.go_to_url)
      
              self.add_new_tab()
              self.show()
      
          def add_new_tab(self):
              index = self.tabs.count()
              browser = Browser()
              title = "New tab"
              self.tabs.addTab(browser, title)
              self.tabs.setCurrentIndex(index)
              page = Page()
              browser.setPage(page)
      
              browser.loadFinished.connect(lambda tabtitle, index=index, browser=browser:self.onLoadFinished(index, browser))
              browser.loadFinished.connect(lambda windowtitle, browser=browser:self.setWindowTitle(browser.page().title()))
              browser.urlChanged.connect(lambda url, browser=browser:self.update_urlbar_and_window(url, browser))
      
          def onLoadFinished(self, index, browser):
              self.tabs.setTabText(index, browser.page().title())
      
          def close_tab(self, index):
              if self.tabs.count() > 1:
                  self.tabs.removeTab(index)
              return
      
          def go_to_url(self):
              url = QUrl.fromUserInput(self.urlbar.text()).toString()
              self.tabs.currentWidget().load(QUrl(url))
      
          def update_urlbar_and_window(self, url, browser):
              if browser != self.tabs.currentWidget():
                  return
              self.setWindowTitle(self.tabs.currentWidget().page().title())
              self.urlbar.setText(url.toString())
              self.urlbar.setCursorPosition(0)
      
          def current_tab_changed(self, index):
              url = self.tabs.currentWidget().url()
              self.update_urlbar_and_window(url, index)
      
      
      app = QApplication(sys.argv)
      app.setApplicationName("Extreme Tabbing Action")
      window = MainWindow()
      app.exec_()
      
      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Harborman said in Tab title goes in the wrong tab:

      browser.loadFinished.connect(lambda tabtitle, index=index, browser=browser:self.onLoadFinished(index, browser))

      If I'm not mistaken. You connect here with a lambda passing index. That is index during add_new_tab(). If later on you change tabs like remove or insert the original index at add time will be incorrect for passing to lambda slot.

      1 Reply Last reply
      3
      • H Offline
        H Offline
        Harborman
        wrote on last edited by Harborman
        #3

        I already started trying to create some kind of dict that collects information about used indexes and the amount of opened pages, for loops, etc...
        But could it really be this simple:

                browser.loadFinished.connect(lambda tabtitle:self.onLoadFinished(browser))
        
           def onLoadFinished(self, browser):
                current = self.tabs.currentWidget()
                i = self.tabs.indexOf(current)
                self.tabs.setTabText(i, browser.page().title())
        

        Yeah the lambda is still there but instead of passing the index and coming up with clever ways to update it, or keeping track of what's been opened and what's been closed I just refer to the index of the current widget when setting the tab title. So far it seems to have worked.

        EDIT: Seemed too simple to be truly functional. If the page loads for a long time and you change the current tab during the loading, the title will land in the tab you're on, not the tab where the signal came from. I overlooked this because I only used sample pages that loaded instantly.
        I can halfway fix this with something like

                if browser != self.tabs.currentWidget():
                    return
        

        but in this case there's no title in any tab. How do I just force the title into the tab where the signal came from?

        JonBJ 1 Reply Last reply
        0
        • H Harborman

          I already started trying to create some kind of dict that collects information about used indexes and the amount of opened pages, for loops, etc...
          But could it really be this simple:

                  browser.loadFinished.connect(lambda tabtitle:self.onLoadFinished(browser))
          
             def onLoadFinished(self, browser):
                  current = self.tabs.currentWidget()
                  i = self.tabs.indexOf(current)
                  self.tabs.setTabText(i, browser.page().title())
          

          Yeah the lambda is still there but instead of passing the index and coming up with clever ways to update it, or keeping track of what's been opened and what's been closed I just refer to the index of the current widget when setting the tab title. So far it seems to have worked.

          EDIT: Seemed too simple to be truly functional. If the page loads for a long time and you change the current tab during the loading, the title will land in the tab you're on, not the tab where the signal came from. I overlooked this because I only used sample pages that loaded instantly.
          I can halfway fix this with something like

                  if browser != self.tabs.currentWidget():
                      return
          

          but in this case there's no title in any tab. How do I just force the title into the tab where the signal came from?

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

          @Harborman
          Sorry, I don't understand all that you are saying. If I understand, all you need to do is pass the page-widget where the page has loaded or you want to set the title as a parameter in the signal -> slot, or find the page-widget in the slot if that works for you. The important thing is not to pass a tab index in the signal, where that index was fixed at tab creation time but is now incorrect due to tab deletion/insertion.

          1 Reply Last reply
          0
          • H Offline
            H Offline
            Harborman
            wrote on last edited by
            #5

            Here's my latest attempt, this seems to work:

               def add_new_tab(self):
                    index = self.tabs.count()
                    browser = Browser()
                    title = "Empty tab"
                    self.tabs.addTab(browser, title)
                    self.tabs.setCurrentIndex(index)
            
                    browser.loadFinished.connect(lambda tabtitle:self.on_load_finished(browser))
            
                def on_load_finished(self, browser):
                    loadedpage = browser
                    i = self.tabs.indexOf(loadedpage)
                    self.tabs.setTabText(i, browser.page().title())
            
            JonBJ 1 Reply Last reply
            1
            • H Harborman

              Here's my latest attempt, this seems to work:

                 def add_new_tab(self):
                      index = self.tabs.count()
                      browser = Browser()
                      title = "Empty tab"
                      self.tabs.addTab(browser, title)
                      self.tabs.setCurrentIndex(index)
              
                      browser.loadFinished.connect(lambda tabtitle:self.on_load_finished(browser))
              
                  def on_load_finished(self, browser):
                      loadedpage = browser
                      i = self.tabs.indexOf(loadedpage)
                      self.tabs.setTabText(i, browser.page().title())
              
              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #6

              @Harborman
              This looks much better! Your lambda now passes the page as a parameter, and unlike your original index that does not change as you insert/delete other pages. Then you look up the page in the tabs during the slot to find it at that time.

              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