mvc_5.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import random
  2. import sys
  3. from collections import UserDict
  4. from PyQt5.QtCore import QObject, pyqtSignal, Qt
  5. from PyQt5.QtWidgets import QMainWindow, QApplication, QFormLayout, QLineEdit, QSpinBox, QComboBox, QPushButton, \
  6. QCheckBox, QWidget
  7. class DataModelSignals(QObject):
  8. # Emit an "updated" signal when a property changes.
  9. updated = pyqtSignal()
  10. class DataModel(UserDict):
  11. def __init__(self, *args, **kwargs):
  12. self.signals = DataModelSignals()
  13. super().__init__(*args, **kwargs)
  14. def __setitem__(self, key, value):
  15. previous = self.get(key) # Get the existing value.
  16. super().__setitem__(key, value)
  17. if value != previous: # There is a change
  18. self.signals.updated.emit() # Emit the signal
  19. print(self) # Show the current state.
  20. model = DataModel(
  21. name="Johnina Smith",
  22. age=10,
  23. favorite_icecream="Vanilla",
  24. disable_details=False,
  25. )
  26. class Controller:
  27. """ Simple controller, which handles backups and other operations. """
  28. backups = []
  29. def capitalize(self):
  30. model["name"] = model["name"].upper()
  31. def store_backup(self):
  32. self.backups.append(model.copy())
  33. def restore_backup(self):
  34. if not self.backups:
  35. return
  36. random.shuffle(self.backups)
  37. backup = self.backups.pop()
  38. model.update(backup) # Overwrite the data in the model
  39. print("RESTORE:", model)
  40. print("BACKUPS:", len(self.backups))
  41. def apply_title_case(self):
  42. model["name"] = model["name"].title()
  43. controller = Controller()
  44. class MainWindow(QMainWindow):
  45. def __init__(self):
  46. super().__init__()
  47. self.setWindowTitle("MVC Example")
  48. layout = QFormLayout()
  49. # Dictionary to store the form data, with default data.
  50. self.name = QLineEdit()
  51. self.name.textChanged.connect(self.on_name_changed)
  52. self.age = QSpinBox()
  53. self.age.setRange(0, 200)
  54. self.age.valueChanged.connect(self.on_age_changed)
  55. self.icecream = QComboBox()
  56. self.icecream.addItems(["Vanilla", "Strawberry", "Chocolate"])
  57. self.icecream.currentTextChanged.connect(self.on_icecream_changed)
  58. self.title_btn = QPushButton("Set Title Case")
  59. self.title_btn.pressed.connect(controller.apply_title_case)
  60. # tag::connect[]
  61. self.save_btn = QPushButton("Save")
  62. self.save_btn.pressed.connect(controller.store_backup)
  63. self.restore_btn = QPushButton("Restore")
  64. self.restore_btn.pressed.connect(controller.restore_backup)
  65. # end::connect[]
  66. self.disable_details = QCheckBox("Disable Details?")
  67. self.disable_details.toggled.connect(self.on_disable_details_toggled)
  68. layout.addRow("Name", self.name)
  69. layout.addRow(self.title_btn)
  70. layout.addRow("Age", self.age)
  71. layout.addRow("Favorite Ice Cream", self.icecream)
  72. layout.addWidget(self.disable_details) # QCheckBox has its own label.
  73. layout.addRow(self.save_btn)
  74. layout.addRow(self.restore_btn)
  75. layout.setLabelAlignment(Qt.AlignLeft)
  76. widget = QWidget()
  77. widget.setLayout(layout)
  78. self.setCentralWidget(widget)
  79. self.update_ui()
  80. # Hook our UI sync into the model updated signal
  81. model.signals.updated.connect(self.update_ui)
  82. def update_ui(self):
  83. self.name.setText(model["name"])
  84. self.age.setValue(model["age"])
  85. self.icecream.setCurrentText(model["favorite_icecream"])
  86. self.disable_details.setChecked(model["disable_details"])
  87. self.age.setDisabled(model["disable_details"])
  88. self.icecream.setDisabled(model["disable_details"])
  89. def on_name_changed(self, name):
  90. model["name"] = name
  91. def on_age_changed(self, age):
  92. model["age"] = age
  93. def on_icecream_changed(self, icecream):
  94. model["favorite_icecream"] = icecream
  95. def on_disable_details_toggled(self, checked):
  96. model["disable_details"] = checked
  97. if __name__ == "__main__":
  98. app = QApplication(sys.argv)
  99. window = MainWindow()
  100. window.show()
  101. sys.exit(app.exec_())