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. Closing all window instances when MainWindow() is closed
Forum Updated to NodeBB v4.3 + New Features

Closing all window instances when MainWindow() is closed

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

    How can I get the program to completely shut down and close all window instances when MainWindow() is closed?
    I used to have a separate close button which did the job but I don't any longer. For reference, here's my code if you want to see what I mean.
    By right clicking anywhere on the webpage, you can open a new window. This new window is the NewWindow() class.

    from PyQt5.QtCore import QUrl, QSize, Qt
    from PyQt5.QtWidgets import QAction, QMenu, \
                                QPushButton, QToolBar, QApplication, QMainWindow, QTabWidget, QLineEdit
    from PyQt5.QtGui import QFont
    from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineSettings
    import sys
    
    currenturl = None
    emptytab = QUrl("http://duckduckgo.com")
    
    class WebEnginePage(QWebEnginePage):
        print("ree")
    
    class Tabs(QTabWidget):
        def __init__(self):
            super().__init__()
    
    class Browser(QWebEngineView):
        def __init__(self, MainWindow):
            super().__init__()
            self.MainWindow = MainWindow
            settings = QWebEngineSettings.globalSettings()
            settings.setAttribute(QWebEngineSettings.ErrorPageEnabled, False)  #disable chromium error pages
    
        def contextMenuEvent(self, event):
            self.menus2 = QMenu()
            self.menus2.setStyleSheet("background-color:rgb(209,222,235); QMenu::item::hover {text-color:rgb(30,30,30);}")
            action2 = QAction("OPEN NEW WINDOW", self)
            self.menus2.addAction(action2)
            self.menus2.popup(event.globalPos())
            action2.triggered.connect(self.open_new_window)
    
        def open_new_window(self):
            self.new_window = NewWindow()  #this must have "self", otherwise the new window instance is destroyed immediately
    
    class Urlbar(QLineEdit):
        def __init__(self, MainWindow):
            super().__init__()
            self.MainWindow = MainWindow
    
    class NewWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.resize(400, 300)
            self.setMaximumHeight(300)
            self.setMaximumWidth(400)
            self.browser = QWebEngineView()
            self.browser.load(QUrl("http://duckduckgo.com"))
            self.setCentralWidget(self.browser)
            self.show()
    
    class MainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super(MainWindow, self).__init__(*args, **kwargs)
            self.setMinimumHeight(680)
            self.setMinimumWidth(800)
    
            self.tabs = Tabs()
            self.setCentralWidget(self.tabs)  #setting tabs as the central widget of the window
            self.tabs.setTabsClosable(True)
            self.tabs.currentChanged.connect(self.current_tab_changed)
            self.tabs.tabCloseRequested.connect(self.close_tab)
            toolbar = QToolBar()  #toolbar, we'll disable the context menu it has by default
            QToolBar.setContextMenuPolicy(self, Qt.NoContextMenu)
            toolbar.setIconSize(QSize(50, 44))
            toolbar.setMovable(False)
            self.addToolBar(toolbar)
    
            cornerwidget = QPushButton(self.tabs)  #new tab button
            self.tabs.setCornerWidget(cornerwidget, Qt.TopLeftCorner)
            backbtn = QPushButton()  #back button
            toolbar.addWidget(backbtn)
            forwardbtn = QPushButton()  #forward button
            toolbar.addWidget(forwardbtn)
            refreshbtn = QPushButton()  #refresh button
            toolbar.addWidget(refreshbtn)
            self.urlbar = Urlbar(self)  #address bar
            font = QFont()
            font.setFamily("Arial")
            font.setPointSize(11)
            font.setBold(False)
            self.urlbar.setFont(font)
            toolbar.addWidget(self.urlbar)
            self.urlbar.returnPressed.connect(self.go_to_url)  #press enter to load url
    
            cornerwidget.clicked.connect(self.add_new_tab)  #button signals
            backbtn.clicked.connect(self.back)
            forwardbtn.clicked.connect(self.forward)
            refreshbtn.clicked.connect(self.refresh)
    
            browser = Browser(self)  #start by adding a new tab
            self.add_new_tab(browser, emptytab)
            self.show()
    
        def add_new_tab(self, browser, urli=None):
            index = self.tabs.count()
            browser = Browser(self)
            browser.setPage(WebEnginePage(self))  #make a custom webenginepage
            self.tabs.addTab(browser, "")  #2nd argument is title
            self.tabs.setCurrentIndex(index)
            if urli == None:
                browser.setUrl(emptytab)
            else:
                browser.setUrl(QUrl(urli))
            browser.loadFinished.connect(lambda tabtitle: self.on_load_finished(browser))
            browser.loadFinished.connect(lambda windowtitle: self.setWindowTitle(browser.page().title()))
            browser.urlChanged.connect(lambda url: self.update_urlbar_and_window(url, browser))
    
        def on_load_finished(self, browser):
            loadedpage = browser
            i = self.tabs.indexOf(loadedpage)
            title = browser.page().title()
            self.tabs.setTabText(i, title)  #handles tab titles
    
        def go_to_url(self):
            url = QUrl(self.urlbar.text()).toString()
            self.tabs.currentWidget().load(QUrl(url))
    
        def update_urlbar_and_window(self, url, browser):
            if browser != self.tabs.currentWidget():
                return
            windowtitle = self.tabs.currentWidget().page().title()
            self.setWindowTitle(windowtitle)
    
        def current_tab_changed(self):
            url = self.tabs.currentWidget().url()
            self.update_urlbar_and_window(url, self.tabs.currentWidget())
    
        def close_tab(self, index):
            if self.tabs.count() > 1:
                self.tabs.removeTab(index)
            return
    
        def back(self):  #button events start here
            self.tabs.currentWidget().back()
        def forward(self):
            self.tabs.currentWidget().forward()
        def refresh(self):
            self.tabs.currentWidget().reload()
    
    app = QApplication(sys.argv)
    app.setApplicationName("Extreme Browser")
    window = MainWindow()
    app.exec_()```
    JonBJ 1 Reply Last reply
    0
    • H Harborman

      How can I get the program to completely shut down and close all window instances when MainWindow() is closed?
      I used to have a separate close button which did the job but I don't any longer. For reference, here's my code if you want to see what I mean.
      By right clicking anywhere on the webpage, you can open a new window. This new window is the NewWindow() class.

      from PyQt5.QtCore import QUrl, QSize, Qt
      from PyQt5.QtWidgets import QAction, QMenu, \
                                  QPushButton, QToolBar, QApplication, QMainWindow, QTabWidget, QLineEdit
      from PyQt5.QtGui import QFont
      from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineSettings
      import sys
      
      currenturl = None
      emptytab = QUrl("http://duckduckgo.com")
      
      class WebEnginePage(QWebEnginePage):
          print("ree")
      
      class Tabs(QTabWidget):
          def __init__(self):
              super().__init__()
      
      class Browser(QWebEngineView):
          def __init__(self, MainWindow):
              super().__init__()
              self.MainWindow = MainWindow
              settings = QWebEngineSettings.globalSettings()
              settings.setAttribute(QWebEngineSettings.ErrorPageEnabled, False)  #disable chromium error pages
      
          def contextMenuEvent(self, event):
              self.menus2 = QMenu()
              self.menus2.setStyleSheet("background-color:rgb(209,222,235); QMenu::item::hover {text-color:rgb(30,30,30);}")
              action2 = QAction("OPEN NEW WINDOW", self)
              self.menus2.addAction(action2)
              self.menus2.popup(event.globalPos())
              action2.triggered.connect(self.open_new_window)
      
          def open_new_window(self):
              self.new_window = NewWindow()  #this must have "self", otherwise the new window instance is destroyed immediately
      
      class Urlbar(QLineEdit):
          def __init__(self, MainWindow):
              super().__init__()
              self.MainWindow = MainWindow
      
      class NewWindow(QMainWindow):
          def __init__(self):
              super().__init__()
              self.resize(400, 300)
              self.setMaximumHeight(300)
              self.setMaximumWidth(400)
              self.browser = QWebEngineView()
              self.browser.load(QUrl("http://duckduckgo.com"))
              self.setCentralWidget(self.browser)
              self.show()
      
      class MainWindow(QMainWindow):
          def __init__(self, *args, **kwargs):
              super(MainWindow, self).__init__(*args, **kwargs)
              self.setMinimumHeight(680)
              self.setMinimumWidth(800)
      
              self.tabs = Tabs()
              self.setCentralWidget(self.tabs)  #setting tabs as the central widget of the window
              self.tabs.setTabsClosable(True)
              self.tabs.currentChanged.connect(self.current_tab_changed)
              self.tabs.tabCloseRequested.connect(self.close_tab)
              toolbar = QToolBar()  #toolbar, we'll disable the context menu it has by default
              QToolBar.setContextMenuPolicy(self, Qt.NoContextMenu)
              toolbar.setIconSize(QSize(50, 44))
              toolbar.setMovable(False)
              self.addToolBar(toolbar)
      
              cornerwidget = QPushButton(self.tabs)  #new tab button
              self.tabs.setCornerWidget(cornerwidget, Qt.TopLeftCorner)
              backbtn = QPushButton()  #back button
              toolbar.addWidget(backbtn)
              forwardbtn = QPushButton()  #forward button
              toolbar.addWidget(forwardbtn)
              refreshbtn = QPushButton()  #refresh button
              toolbar.addWidget(refreshbtn)
              self.urlbar = Urlbar(self)  #address bar
              font = QFont()
              font.setFamily("Arial")
              font.setPointSize(11)
              font.setBold(False)
              self.urlbar.setFont(font)
              toolbar.addWidget(self.urlbar)
              self.urlbar.returnPressed.connect(self.go_to_url)  #press enter to load url
      
              cornerwidget.clicked.connect(self.add_new_tab)  #button signals
              backbtn.clicked.connect(self.back)
              forwardbtn.clicked.connect(self.forward)
              refreshbtn.clicked.connect(self.refresh)
      
              browser = Browser(self)  #start by adding a new tab
              self.add_new_tab(browser, emptytab)
              self.show()
      
          def add_new_tab(self, browser, urli=None):
              index = self.tabs.count()
              browser = Browser(self)
              browser.setPage(WebEnginePage(self))  #make a custom webenginepage
              self.tabs.addTab(browser, "")  #2nd argument is title
              self.tabs.setCurrentIndex(index)
              if urli == None:
                  browser.setUrl(emptytab)
              else:
                  browser.setUrl(QUrl(urli))
              browser.loadFinished.connect(lambda tabtitle: self.on_load_finished(browser))
              browser.loadFinished.connect(lambda windowtitle: self.setWindowTitle(browser.page().title()))
              browser.urlChanged.connect(lambda url: self.update_urlbar_and_window(url, browser))
      
          def on_load_finished(self, browser):
              loadedpage = browser
              i = self.tabs.indexOf(loadedpage)
              title = browser.page().title()
              self.tabs.setTabText(i, title)  #handles tab titles
      
          def go_to_url(self):
              url = QUrl(self.urlbar.text()).toString()
              self.tabs.currentWidget().load(QUrl(url))
      
          def update_urlbar_and_window(self, url, browser):
              if browser != self.tabs.currentWidget():
                  return
              windowtitle = self.tabs.currentWidget().page().title()
              self.setWindowTitle(windowtitle)
      
          def current_tab_changed(self):
              url = self.tabs.currentWidget().url()
              self.update_urlbar_and_window(url, self.tabs.currentWidget())
      
          def close_tab(self, index):
              if self.tabs.count() > 1:
                  self.tabs.removeTab(index)
              return
      
          def back(self):  #button events start here
              self.tabs.currentWidget().back()
          def forward(self):
              self.tabs.currentWidget().forward()
          def refresh(self):
              self.tabs.currentWidget().reload()
      
      app = QApplication(sys.argv)
      app.setApplicationName("Extreme Browser")
      window = MainWindow()
      app.exec_()```
      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Harborman
      Do you mean calling QApplication::closeAllWindows() or QApplication::quit() or qApp->exit()?

      H 1 Reply Last reply
      0
      • JonBJ JonB

        @Harborman
        Do you mean calling QApplication::closeAllWindows() or QApplication::quit() or qApp->exit()?

        H Offline
        H Offline
        Harborman
        wrote on last edited by
        #3

        @JonB
        When I had a frameless browser, there was no titlebar or a close button, so I made the button like this

            closebtn.clicked.connect(self.quit)
        
            def quit(self):
                QApplication.quit()
        

        But I decided to go back to the default titlebar with default Windows buttons (minimize, maximize, close)
        and need the close button to have the same functionality.
        Apparently by default the close button only closes MainWindow() and nothing else.
        I think both QApplication.quit() and QApplication.closeAllWindows() would get the job done, I just don't know how to tie them to the default close button.
        When using closeAllWindows(), I understand the application quits when all windows have closed.

        JonBJ 1 Reply Last reply
        0
        • H Harborman

          @JonB
          When I had a frameless browser, there was no titlebar or a close button, so I made the button like this

              closebtn.clicked.connect(self.quit)
          
              def quit(self):
                  QApplication.quit()
          

          But I decided to go back to the default titlebar with default Windows buttons (minimize, maximize, close)
          and need the close button to have the same functionality.
          Apparently by default the close button only closes MainWindow() and nothing else.
          I think both QApplication.quit() and QApplication.closeAllWindows() would get the job done, I just don't know how to tie them to the default close button.
          When using closeAllWindows(), I understand the application quits when all windows have closed.

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

          @Harborman said in Closing all window instances when MainWindow() is closed:

          I just don't know how to tie them to the default close button.

          I think:

          • In your MainWondow subclass QMainWindow and you should get (be able to override) closeEvent().
          • Or use application/main window eventFilter.
          1 Reply Last reply
          0
          • H Offline
            H Offline
            Harborman
            wrote on last edited by
            #5

            I just slapped this inside the MainWindow class and it seems to do the trick:

               def closeEvent(self):
                    sys.exit(0)
            

            Not sure if this is a good way to do it.

            JonBJ 1 Reply Last reply
            0
            • H Harborman

              I just slapped this inside the MainWindow class and it seems to do the trick:

                 def closeEvent(self):
                      sys.exit(0)
              

              Not sure if this is a good way to do it.

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

              @Harborman
              It's a bit abrupt! "Slapped" is indeed the word.

              The closeEvent() override you have defined is fine. You ought let Qt things close down gracefully, e.g.

              @JonB said in Closing all window instances when MainWindow() is closed:

              @Harborman
              Do you mean calling QApplication::closeAllWindows() or QApplication::quit() or qApp->exit()?

              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