Python PyQt5 pop up sub window to solve the problem of flash of sub window

  • 2021-10-13 08:04:01
  • OfStack

Mode 1: Create a child window object in the slot function and assign it to a common variable

Add buttons in the main window, associate button signals with slots, create child window objects in slot functions, assign values to common variables, and call its show method.


from PyQt5.QtWidgets import *
import sys
 
class Main(QMainWindow):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" Main window ")
    button = QPushButton(" Pop-up sub-window ", self)
    button.clicked.connect(self.show_child)
 
  def show_child(self):
    child_window = Child()
    child_window.show()
 
class Child(QWidget):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" I am a sub-window ")
 
#  Run the main window 
if __name__ == "__main__":
  app = QApplication(sys.argv)
 
  window = Main()
  window.show()
 
  sys.exit(app.exec_())

Running results: After the code runs, click the button in the main window, and the sub-window 1 flashes by.

Mode 2: Create a child window object in the slot function and assign it as an object attribute

Add buttons in the main window, associate button signals with slots, create sub-window objects in slot functions and assign them as object attributes, and call its show method.


from PyQt5.QtWidgets import *
import sys
 
class Main(QMainWindow):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" Main window ")
    button = QPushButton(" Pop-up sub-window ", self)
    button.clicked.connect(self.show_child)
 
  def show_child(self):
    self.child_window = Child()
    self.child_window.show()
 
class Child(QWidget):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" I am a sub-window ")
 
#  Run the main window 
if __name__ == "__main__":
  app = QApplication(sys.argv)
 
  window = Main()
  window.show()
 
  sys.exit(app.exec_())

Running results: After the code runs, click the button in the main window, the sub-window opens normally, click the button repeatedly, and the sub-window pops up repeatedly.

Mode 3: Create child windows in the main window __init__ method

In the main window __init__ method, a child window object is created and assigned as an object attribute, a button is added, and the button signal is associated with a slot, and the show method of the child window object is called in the slot function.


from PyQt5.QtWidgets import *
import sys
 
class Main(QMainWindow):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" Main window ")
    button = QPushButton(" Pop-up sub-window ", self)
    button.clicked.connect(self.show_child)
    self.child_window = Child()
 
  def show_child(self):
    self.child_window.show()
 
class Child(QWidget):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" I am a sub-window ")
 
#  Run the main window 
if __name__ == "__main__":
  app = QApplication(sys.argv)
 
  window = Main()
  window.show()
 
  sys.exit(app.exec_())

Running results: Click the button repeatedly, and the sub-window will not pop up repeatedly.

Mode 4: exec () method

Change the show () method of example 1 to exec () method


from PyQt5.QtWidgets import *
import sys
 
class Main(QMainWindow):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" Main window ")
    button = QPushButton(" Pop-up sub-window ", self)
    button.clicked.connect(self.show_child)
 
  def show_child(self):
    child_window = Child()
    child_window.exec()
 
class Child(QWidget):
  def __init__(self):
    super().__init__()
    self.setWindowTitle(" I am a sub-window ")
 
#  Run the main window 
if __name__ == "__main__":
  app = QApplication(sys.argv)
 
  window = Main()
  window.show()
 
  sys.exit(app.exec_())

Running result: The child window pops up smoothly, and the parent window cannot be re-selected

Conclusions:

This involves a conceptual modal dialog and a non-modal dialog (modeless dialog modal dialog)

Modal dialog box, that is, when the pop-up window, the whole program is locked and in a waiting state until the dialog box is closed. At this time, the return value of the dialog box is often needed for the following operations. For example, confirm the window (select Yes or No).
Non-modal dialog box, after calling the pop-up window, the call returns immediately and continues the following operation. This is just a call instruction issued, without waiting or doing anything. Example: Find box.

show() ------ modeless dialog

exec() ------- modal dialog

The sub-window in Mode 1 is displayed by show () method, which is a modeless window. Its instance is the local variable in the parent window show_child () method. When the window is displayed, the parent window show_child () method continues to execute. When the method runs, the recovery mechanism of python destroys the local variable, which is equivalent to the destruction of the sub-window instance, so the sub-window 1 flashes; Mode 2 sub-window instance is a variable of the main window class. When show_child () method is run, the main window object still exists and the sub-window instance also exists, so the sub-window is displayed normally, but every time the slot function is run, it will recreate the sub-window object; Mode 3 sub-window instance is a variable of the main window class. When the show_child () method runs, the main window object still exists and the sub-window instance also exists, so the sub-window is displayed normally. Every time the show_child () function is called again, the sub-window object show_child () method will not create a new window, and it can be switched between the parent and the sub-window at will; The sub-window in mode 4 is displayed by exec () method, which is a modal window. Although it is a local variable in the parent window show_child () method, due to the blocking mechanism, the parent window show_child () does not continue to execute, so it will not flash as in example 1, and cannot be switched between the parent and child windows;

Related articles: