如何销毁一个 QApplication,然后在不退出 Python 脚本的情况下运行一个新的?

huangapple go评论126阅读模式
英文:

How to destroy a QApplication and then run a new one without exiting the python script?

问题

我想创建一个QApplication,然后使用键盘快捷键退出它。然后Python脚本应该调用另一个QApplication。

我的问题是当第二个QApplication即将运行时,我收到以下错误:

  1. app2 = QApplication()
  2. RuntimeError: 在创建新的QApplication实例之前,请销毁QApplication单例。

我有以下结构:

  1. | main.py
  2. | Q1.py
  3. | Q2.py

这是main.py:

  1. import Q1 as record
  2. import Q2 as display
  3. def main():
  4. record.main()
  5. display.main()
  6. if __name__ == "__main__":
  7. main()

这是Q1,它引起了问题:

  1. import sys
  2. from PySide2 import QtWidgets as qtw
  3. from PySide2 import QtGui as qtg
  4. from PySide2 import QtCore as qtc
  5. from PySide2 import QtMultimedia as qtmm
  6. class MainWindow(qtw.QMainWindow):
  7. def __init__(self):
  8. super().__init__()
  9. # 创建带有声音小部件的窗口布局
  10. soundboard = qtw.QWidget()
  11. soundboard.setLayout(qtw.QGridLayout())
  12. self.setCentralWidget(soundboard)
  13. sw = SoundWidget()
  14. soundboard.layout().addWidget(sw)
  15. # 窗口尺寸
  16. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
  17. # 代码结束
  18. self.show()
  19. class SendOrderButton(qtw.QPushButton):
  20. button_stylesheet = 'background-color: blue; color: white;'
  21. def __init__(self):
  22. super().__init__('Send Order')
  23. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
  24. self.setStyleSheet(self.button_stylesheet)
  25. def press_button(self):
  26. if self.isEnabled():
  27. self.setEnabled(False)
  28. self.setText('Send Order')
  29. else:
  30. self.setEnabled(True)
  31. self.setText('Sent')
  32. class SoundWidget(qtw.QWidget):
  33. def __init__(self):
  34. super().__init__()
  35. self.setLayout(qtw.QGridLayout())
  36. # 发送订单按钮
  37. self.sendorder_button = SendOrderButton()
  38. self.sendorder_button.setShortcut(qtg.QKeySequence('Tab'))
  39. self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
  40. self.sendorder_button.clicked.connect(qtc.QCoreApplication.instance().quit)
  41. def main():
  42. app = qtw.QApplication(sys.argv)
  43. window = MainWindow()
  44. window.show()
  45. app.exec_()
  46. if __name__ == '__main__':
  47. app = qtw.QApplication(sys.argv)
  48. window = MainWindow()
  49. window.show()
  50. sys.exit(app.exec_())

这是Q2.py,其中包含第二个QApplication:

  1. import sys
  2. from PySide2.QtCore import (QAbstractTableModel, Slot)
  3. from PySide2.QtWidgets import (QAction, QApplication, QMainWindow, QWidget)
  4. class MainWindow(QMainWindow):
  5. def __init__(self, widget):
  6. QMainWindow.__init__(self)
  7. # 退出QAction
  8. exit_action = QAction("Exit", self)
  9. exit_action.setShortcut("Ctrl+Q")
  10. exit_action.triggered.connect(self.exit_app)
  11. @Slot()
  12. def exit_app(self, checked):
  13. sys.exit()
  14. class CustomTableModel(QAbstractTableModel):
  15. def __init__(self, data=None):
  16. QAbstractTableModel.__init__(self)
  17. class Widget(QWidget):
  18. def __init__(self):
  19. QWidget.__init__(self)
  20. # 获取模型
  21. self.model = CustomTableModel()
  22. def main():
  23. app2 = QApplication()
  24. widget = Widget()
  25. window2 = MainWindow(widget)
  26. window2.show()
  27. sys.exit(app2.exec_())
  28. if __name__ == "__main__":
  29. app = QApplication()
  30. widget = Widget()
  31. window = MainWindow(widget)
  32. window.show()
  33. sys.exit(app.exec_())
英文:

I want to create a QApplication which is then exited using a keyboard shortcut. Then the python script should call another QApplication.

My issues currently is that I get this error when the second QApplication is about to run:

  1. app2 = QApplication()
  2. RuntimeError: Please destroy the QApplication singleton before creating a new QApplication instance.

I have the following structure:

  1. | main.py
  2. | Q1.py
  3. | Q2.py

This is main.py:

  1. import Q1 as record
  2. import Q2 as display
  3. def main():
  4. record.main()
  5. display.main()
  6. if __name__ == "__main__":
  7. main()

This is Q1 which creates the problem:

  1. import sys
  2. from PySide2 import QtWidgets as qtw
  3. from PySide2 import QtGui as qtg
  4. from PySide2 import QtCore as qtc
  5. from PySide2 import QtMultimedia as qtmm
  6. class MainWindow(qtw.QMainWindow):
  7. def __init__(self):
  8. super().__init__()
  9. #Create Window layout with a sound widget
  10. soundboard = qtw.QWidget()
  11. soundboard.setLayout(qtw.QGridLayout())
  12. self.setCentralWidget(soundboard)
  13. sw = SoundWidget()
  14. soundboard.layout().addWidget(sw)
  15. #Window Dimensions
  16. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
  17. # Code ends here
  18. self.show()
  19. class SendOrderButton(qtw.QPushButton):
  20. button_stylesheet = 'background-color: blue; color: white;'
  21. def __init__(self):
  22. super().__init__('Send Order')
  23. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
  24. self.setStyleSheet(self.button_stylesheet)
  25. #self.clicked.connect(qtc.QCoreApplication.instance().quit)
  26. def press_button(self):
  27. if self.isEnabled():
  28. self.setEnabled(False)
  29. self.setText('Send Order')
  30. else:
  31. self.setEnabled(True)
  32. self.setText('Sent')
  33. class SoundWidget(qtw.QWidget):
  34. def __init__(self):
  35. super().__init__()
  36. self.setLayout(qtw.QGridLayout())
  37. #Send Order Button
  38. self.sendorder_button = SendOrderButton()
  39. self.sendorder_button.setShortcut(qtg.QKeySequence('Tab'))
  40. self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
  41. self.sendorder_button.clicked.connect(qtc.QCoreApplication.instance().quit)
  42. def main():
  43. app = qtw.QApplication(sys.argv)
  44. window = MainWindow()
  45. window.show()
  46. app.exec_()
  47. if __name__ == '__main__':
  48. app = qtw.QApplication(sys.argv)
  49. window = MainWindow()
  50. window.show()
  51. sys.exit(app.exec_())

This is Q2.py which has the second QApplication:

  1. import sys
  2. from PySide2.QtCore import (QAbstractTableModel, Slot)
  3. from PySide2.QtWidgets import (QAction, QApplication, QMainWindow,QWidget)
  4. class MainWindow(QMainWindow):
  5. def __init__(self, widget):
  6. QMainWindow.__init__(self)
  7. # Exit QAction
  8. exit_action = QAction("Exit", self)
  9. exit_action.setShortcut("Ctrl+Q")
  10. exit_action.triggered.connect(self.exit_app)
  11. @Slot()
  12. def exit_app(self, checked):
  13. sys.exit()
  14. class CustomTableModel(QAbstractTableModel):
  15. def __init__(self, data=None):
  16. QAbstractTableModel.__init__(self)
  17. class Widget(QWidget):
  18. def __init__(self):
  19. QWidget.__init__(self)
  20. # Getting the Model
  21. self.model = CustomTableModel()
  22. def main():
  23. app2 = QApplication()
  24. widget = Widget()
  25. window2 = MainWindow(widget)
  26. window2.show()
  27. sys.exit(app2.exec_())
  28. if __name__ == "__main__":
  29. app = QApplication()
  30. widget = Widget()
  31. window = MainWindow(widget)
  32. window.show()
  33. sys.exit(app.exec_())

答案1

得分: 2

以下是您要翻译的内容:

As noted in the comments a Qt application can only and should have a QApplication (you might not follow this rule but nothing guarantees that it works correctly) so you will have to restructure your code.

Assuming that you want the Q1 window to be first and when that window is closed then the Q2 window opens that does not imply at any time that you have to use several QApplication. The idea is to know when a window is closed and to be notified of it, to know when a window is closed then you must override the closeEvent method of the window and to make the notification you must send a signal.

Considering the above, the solution is:

  1. ├── main.py
  2. ├── Q1.py
  3. └── Q2.py

main.py

  1. import sys
  2. from PySide2 import QtWidgets as qtw
  3. import Q1 as record
  4. import Q2 as display
  5. def main():
  6. app = qtw.QApplication(sys.argv)
  7. w1 = record.get_mainwindow()
  8. w2 = display.get_mainwindow()
  9. w1.closed.connect(w2.show)
  10. w1.show()
  11. sys.exit(app.exec_())
  12. if __name__ == "__main__":
  13. main()

Q1.py

  1. from PySide2 import QtWidgets as qtw
  2. from PySide2 import QtGui as qtg
  3. from PySide2 import QtCore as qtc
  4. class MainWindow(qtw.QMainWindow):
  5. closed = qtc.Signal()
  6. def __init__(self):
  7. super().__init__()
  8. # Create Window layout with a sound widget
  9. soundboard = qtw.QWidget()
  10. soundboard.setLayout(qtw.QGridLayout())
  11. self.setCentralWidget(soundboard)
  12. sw = SoundWidget()
  13. soundboard.layout().addWidget(sw)
  14. # Window Dimensions
  15. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
  16. sw.sendorder_button.clicked.connect(self.close)
  17. def closeEvent(self, event):
  18. self.closed.emit()
  19. super().closeEvent(event)
  20. class SendOrderButton(qtw.QPushButton):
  21. button_stylesheet = "background-color: blue; color: white;"
  22. def __init__(self):
  23. super().__init__("Send Order")
  24. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
  25. self.setStyleSheet(self.button_stylesheet)
  26. def press_button(self):
  27. if self.isEnabled():
  28. self.setEnabled(False)
  29. self.setText("Send Order")
  30. else:
  31. self.setEnabled(True)
  32. self.setText("Sent")
  33. class SoundWidget(qtw.QWidget):
  34. def __init__(self):
  35. super().__init__()
  36. self.setLayout(qtw.QGridLayout())
  37. # Send Order Button
  38. self.sendorder_button = SendOrderButton()
  39. self.sendorder_button.setShortcut(qtg.QKeySequence("Tab"))
  40. self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
  41. def get_mainwindow():
  42. window = MainWindow()
  43. return window
  44. if __name__ == "__main__":
  45. import sys
  46. app = qtw.QApplication(sys.argv)
  47. window = MainWindow()
  48. window.show()
  49. sys.exit(app.exec_())

Q2.py

  1. from PySide2 import QtCore as qtc
  2. from PySide2 import QtWidgets as qtw
  3. class MainWindow(qtw.QMainWindow):
  4. def __init__(self, widget):
  5. super().__init__()
  6. file_menu = self.menuBar().addMenu("&File")
  7. # Exit QAction
  8. exit_action = qtw.QAction("Exit", self)
  9. exit_action.setShortcut("Ctrl+Q")
  10. exit_action.triggered.connect(self.close)
  11. file_menu.addAction(exit_action)
  12. class CustomTableModel(qtc.QAbstractTableModel):
  13. pass
  14. class Widget(qtw.QWidget):
  15. def __init__(self):
  16. super().__init__()
  17. # Getting the Model
  18. self.model = CustomTableModel()
  19. def get_mainwindow():
  20. widget = Widget()
  21. window2 = MainWindow(widget)
  22. return window2
  23. if __name__ == "__main__":
  24. import sys
  25. app = qtw.QApplication()
  26. widget = Widget()
  27. window = MainWindow(widget)
  28. window.show()
  29. sys.exit(app.exec_())
英文:

As noted in the comments a Qt application can only and should have a QApplication (you might not follow this rule but nothing guarantees that it works correctly) so you will have to restructure your code.

Assuming that you want the Q1 window to be first and when that window is closed then the Q2 window opens that does not imply at any time that you have to use several QApplication. The idea is to know when a window is closed and to be notified of it, to know when a window is closed then you must override the closeEvent method of the window and to make the notification you must send a signal.

Considering the above, the solution is:

  1. ├── main.py
  2. ├── Q1.py
  3. └── Q2.py

main.py

  1. import sys
  2. from PySide2 import QtWidgets as qtw
  3. import Q1 as record
  4. import Q2 as display
  5. def main():
  6. app = qtw.QApplication(sys.argv)
  7. w1 = record.get_mainwindow()
  8. w2 = display.get_mainwindow()
  9. w1.closed.connect(w2.show)
  10. w1.show()
  11. sys.exit(app.exec_())
  12. if __name__ == "__main__":
  13. main()

Q1.py

  1. from PySide2 import QtWidgets as qtw
  2. from PySide2 import QtGui as qtg
  3. from PySide2 import QtCore as qtc
  4. class MainWindow(qtw.QMainWindow):
  5. closed = qtc.Signal()
  6. def __init__(self):
  7. super().__init__()
  8. # Create Window layout with a sound widget
  9. soundboard = qtw.QWidget()
  10. soundboard.setLayout(qtw.QGridLayout())
  11. self.setCentralWidget(soundboard)
  12. sw = SoundWidget()
  13. soundboard.layout().addWidget(sw)
  14. # Window Dimensions
  15. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
  16. sw.sendorder_button.clicked.connect(self.close)
  17. def closeEvent(self, event):
  18. self.closed.emit()
  19. super().closeEvent(event)
  20. class SendOrderButton(qtw.QPushButton):
  21. button_stylesheet = "background-color: blue; color: white;"
  22. def __init__(self):
  23. super().__init__("Send Order")
  24. self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
  25. self.setStyleSheet(self.button_stylesheet)
  26. def press_button(self):
  27. if self.isEnabled():
  28. self.setEnabled(False)
  29. self.setText("Send Order")
  30. else:
  31. self.setEnabled(True)
  32. self.setText("Sent")
  33. class SoundWidget(qtw.QWidget):
  34. def __init__(self):
  35. super().__init__()
  36. self.setLayout(qtw.QGridLayout())
  37. # Send Order Button
  38. self.sendorder_button = SendOrderButton()
  39. self.sendorder_button.setShortcut(qtg.QKeySequence("Tab"))
  40. self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
  41. def get_mainwindow():
  42. window = MainWindow()
  43. return window
  44. if __name__ == "__main__":
  45. import sys
  46. app = qtw.QApplication(sys.argv)
  47. window = MainWindow()
  48. window.show()
  49. sys.exit(app.exec_())

Q2.py

  1. from PySide2 import QtCore as qtc
  2. from PySide2 import QtWidgets as qtw
  3. class MainWindow(qtw.QMainWindow):
  4. def __init__(self, widget):
  5. super().__init__()
  6. file_menu = self.menuBar().addMenu("&File")
  7. # Exit QAction
  8. exit_action = qtw.QAction("Exit", self)
  9. exit_action.setShortcut("Ctrl+Q")
  10. exit_action.triggered.connect(self.close)
  11. file_menu.addAction(exit_action)
  12. class CustomTableModel(qtc.QAbstractTableModel):
  13. pass
  14. class Widget(qtw.QWidget):
  15. def __init__(self):
  16. super().__init__()
  17. # Getting the Model
  18. self.model = CustomTableModel()
  19. def get_mainwindow():
  20. widget = Widget()
  21. window2 = MainWindow(widget)
  22. return window2
  23. if __name__ == "__main__":
  24. import sys
  25. app = qtw.QApplication()
  26. widget = Widget()
  27. window = MainWindow(widget)
  28. window.show()
  29. sys.exit(app.exec_())

huangapple
  • 本文由 发表于 2020年1月4日 00:04:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581668.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定