Kapitel 29
Multimediaanwendungen mit Qt
812
Abb. 29.2: Das digitale Tagebuch im Schreibmodus
Das ist der Schreibmodus. Klickt man auf die Schaltfläche SPEICHERN, wird das geänderte
Tagebuch in einer Datei gespeichert. Es erscheint eine Messagebox wie in Abbildung 29.2.
Klickt man in der Messagebox auf OK, wechselt die Anwendung wieder in den Lesemodus
und die beiden zusätzlichen Schaltflächen verschwinden. Wenn man rechts auf A
BBRECHEN
klickt, wird nichts gespeichert und die Anwendung geht in den Lesemodus.
29.1.1 Programmierung
Die Anwendung besteht aus zwei Klassen:
Die Klasse Notebook modelliert das Tagebuch. Ein Notebook-Objekt hat Methoden zum
Lesen und Schreiben von Tagebucheinträgen und sorgt dafür, dass die Daten in einem
Dictionary gespeichert werden. Bei jedem Tagebucheintrag ist das Datum der Schlüssel
und der Text der Wert.
Die Klasse CalendarNotes ist von QWidget abgeleitet und stellt die Benutzungsoberflä-
che dar. Das
CalenderNotes-Objekt verwendet ein Notebook-Objekt, um die Tagebuch-
einträge zu speichern.
Abb. 29.3: UML-Klassendiagramm des digitalen Tagebuchs
Die Daten des Tagebuchs werden in einem Dictionary gespeichert.
Skript:
# notebook.py
import sys, pickle
from PyQt5.QtWidgets import (QApplication,
QCalendarWidget, QHBoxLayout, QMessageBox,
813
29.1
Kalender und Textfeld – ein digitales Tagebuch
QPushButton, QTextEdit, QVBoxLayout, QWidget)
PATH = "notes.dat" #1
class Notebook ():
def __init__(self):
try:
f = open(PATH, "rb") #2
self.notes = pickle.load(f)
f.close()
except:
f = open(PATH, "wb")
self.notes = dict()
f.close()
def addNote(self, note, d): #3
self.notes[d] = note
f = open(PATH, "wb")
pickle.dump(self.notes, f)
f.close()
def getNote(self, d): #4
if d in self.notes.keys():
return self.notes[d]
else: return ""
class CalendarNotes(QWidget):
def __init__(self):
super().__init__() #5
self.notes = Notebook() #6
# Widgets
self.setWindowTitle("Tagebuch")
self.cal = QCalendarWidget(self) #7
self.cal.setGridVisible(True)
self.editor = QTextEdit(self) #8
self.editor.setReadOnly(True)
self.bEdit = QPushButton("Edit")
self.bCancel = QPushButton("Abbrechen", self)
self.bSave = QPushButton("Speichern", self)
# Layout
vBox1 = QVBoxLayout() #9
Kapitel 29
Multimediaanwendungen mit Qt
814
vBox1.addWidget(self.cal)
vBox1.addWidget(self.editor)
vBox2 = QVBoxLayout()
vBox2.addWidget(self.bEdit)
vBox2.addWidget(self.bCancel)
vBox2.addWidget(self.bSave)
vBox2.addStretch() #10
hBox = QHBoxLayout()
hBox.addLayout(vBox1)
hBox.addLayout(vBox2)
self.setLayout(hBox)
# Connections
self.bEdit.clicked.connect(self.editNote) #11
self.bCancel.clicked.connect(self.display)
self.bSave.clicked.connect(self.save)
self.cal.selectionChanged.connect(self.display)
self.display() #12
self.show()
def save(self): #13
d = self.cal.selectedDate().toString()
self.notes.addNote(self.editor.toPlainText(), d)
QMessageBox.information(self, "Tagebuch",
"Änderung gespeichert")
self.display()
def editNote(self): #14
self.bSave.show()
self.bCancel.show()
self.editor.setReadOnly(False)
def display(self):
self.bSave.hide()
self.bCancel.hide()
d = self.cal.selectedDate().toString()
self.editor.setText(self.notes.getNote(d))
self.editor.setReadOnly(True)
app = QApplication(sys.argv)
notes = CalendarNotes()
sys.exit(app.exec_())
815
29.1
Kalender und Textfeld – ein digitales Tagebuch
Erläuterung:
#1: Pfad zu der Datei, in der das Tagebuch gespeichert wird.
#2: Bei der Initialisierung eines Notebook-Objektes wird zuerst versucht unter dem Pfad
eine Datei im binären Lesemodus (
"rb") zu öffnen. Anschließend wird mit pickle ein Dic-
tionary geladen. Jedes Item des Dictionarys besteht aus einem Datum (Schlüssel) und dem
Text des Eintrags (Wert).
Wenn unter dem Pfad keine Datei existiert und deshalb die Ausführung der
try-Klausel
abgebrochen werden muss, wird in der
except-Klausel eine neue Datei mit diesem Namen
erstellt.
#3: Die Methode sorgt dafür, dass ein neuer Eintrag in das Dictionary self.notes eingefügt
wird. Die Parameter
d (Datum) und note (Text des Eintrags) sind Strings. Anschließend
wird das geänderte Dictionary mit
pickle gespeichert.
#4: Der Parameter d ist ein String, der ein Datum darstellt. Solche Strings sind Schlüssel des
Dictionarys
self.notes. Wenn zu dem angegebenen Datum ein Text im Dictionary gespei-
chert ist, wird dieser Text zurückgegeben. Anderenfalls wird ein leerer String zurückge-
geben.
#5: Da die Klasse CalendarNotes von QWidgets abgeleitet ist, wird zuerst die Initialisie-
rungsmethode der Basisklasse aufgerufen.
#6: Hier wird ein Objekt der Klasse Notebook erzeugt. Es modelliert den Inhalt des Tage-
buchs.
#7: Hier wird das Kalender-Widget erzeugt. Voreingestellt ist, dass das aktuelle Datum
(»heute«) ausgewählt ist.
#8: Hier wird ein Texteditorfeld in der voreingestellten Größe erzeugt. Darin können meh-
rere Textzeilen eingegeben und editiert werden.
#9: In diesem Abschnitt wird die Anordnung der Widgets mit vertikalen und horizontalen
Box-Layouts festgelegt. Abbildung 29.4 illustriert die Idee. Eine Besonderheit ist das
Stretch-Element, das in Zeile
#10 unter die Schaltflächen gesetzt wird. Man kann es sich wie
eine Spiralfeder vorstellen. Es »drückt« die darüber liegenden Widgets an den oberen Rand
der Box.
Abb. 29.4: Aufbau des Layouts aus einem horizontalen und zwei vertikalen Box-Layouts

Get Python 3 - Lernen und professionell anwenden now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.