TigerJython | xx für Gymnasien |
Im professionellen Umgang mit Datenbanken werden meisten GUI-Dialogfenster verwendet, in welchen der Benutzer die wichtigsten Datenbankmanipulationen durchführen kann:
Mit TigerJython lassen sich solche GUI-Dialoge verhältnismässig einfach erstellen. Das Programm DBManager.py verwendet die Datenbank demo.db und die Tabelle person. Die Tabelle person sollte zu Beginn bereits die 6 Datensätze enthalten, die man mit dem Programm im vorhergehenden Kapitel erzeugt hat. Beim Start wird folgendes Dialogfenster angezeigt:
Das Programm DbManager.py ist etwas länger, ist aber gut verständlich und lässt sich einfach an andere Datenbankanwendungen anpassen. Es ist vollumfänglich unten angezeigt, kann aber auch von download/DbManager.zip herunterladen und in den TigerJython-Editor kopiert werden. |
Auch für die Verwaltung eines Sporttages lässt sich ein GUI-Dialogfenster entwickeln. Verwendet werden hier die Datenbank demo.db mit den Tabellen person und sport. Es ist vorteilhaft, wenn die Tabelle person zu Beginn bereits einige Datensätze enthält, z. B. die 6 Datensätze, die man mit dem Programm InsertPersonEx1.py erzeugt. Die Tabelle sport kann die Datensätze mit den Sportergebnissen dieser 6 Personen enthalten oder auch leer sein, da man die Sportergebnisse mit der neuen Benutzeroberfläche problemlos eingeben kann. Die beiden Tabellen sind über das Schlüsselfeld id miteinander verknüpft. Beim Start wird folgendes Dialogfenster angezeigt: Zuerst sind alle Leistungsfelder leer und kann man die Leistungsdaten aller Personen eingeben. Bei solchen, die eine Sportart nicht ausüben, belässt man das leere Eingabefeld. Beim Klicken von Save werden die Leistungsdaten in die Tabelle geschrieben. Das kann auch unter download/SporManager.zip heruntergeladen und in den TigerJython Editor eingefügt werden. Die Resultate und Ranglisten können wie unter Menüpunkt Tabellen verknüpfen zusammengestellt werden. |
|
# DbManager.py from sqlite3 import * from entrydialog import * database = "demo.db" def doFirst(): global currentIndex currentIndex = 0 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doLast(): global currentIndex currentIndex = len(resultSet) - 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doNext(): global currentIndex if currentIndex == len(resultSet) - 1: status.setValue("Ende der Datenbank erreicht.") return currentIndex += 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doPrevious(): global currentIndex if currentIndex == 0: status.setValue("Beginn der Datenbank erreicht.") return currentIndex -= 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def setInsertMode(enable): global isInsertMode if enable: isInsertMode = True firstBtn.setEnabled(False) lastBtn.setEnabled(False) prevBtn.setEnabled(False) nextBtn.setEnabled(False) insertBtn.setEnabled(False) searchBtn.setEnabled(False) deleteBtn.setEnabled(False) saveBtn.setEnabled(True) cancelBtn.setEnabled(True) initDialog() else: isInsertMode = False firstBtn.setEnabled(True) lastBtn.setEnabled(True) prevBtn.setEnabled(True) nextBtn.setEnabled(True) insertBtn.setEnabled(True) searchBtn.setEnabled(True) deleteBtn.setEnabled(True) saveBtn.setEnabled(True) cancelBtn.setEnabled(False) def initDialog(): vText.setValue("") fText.setValue("") jText.setValue(None) wText.setValue("") gText.setValue("") jText.setValue(None) def initSearchDialog(): fSearch.setValue("") vSearch.setValue("") def showPerson(person): fText.setValue(person[1]) vText.setValue(person[2]) wText.setValue(person[3]) gText.setValue(person[4]) jText.setValue(person[5]) # -------------- Validierung der Eingaben ---------------- def validate(name, vorname, wohnort, geschlecht, jahrgang): illegal = "Illegale Eingabe. " if not isLegal(name): status.setValue(illegal + "Name illegal.") return False if not isLegal(vorname): status.setValue(illegal + "Vorname illegal.") return False if not isLegal(wohnort): status.setValue(illegal + "Wohnort illegal.") return False if geschlecht not in ['m', 'w']: status.setValue(illegal + "Geschlecht muss 'm' oder 'w' sein.") return False if jahrgang == None: status.setValue(illegal + "Jahrgang muss eine Zahl sein.") return False return True def isLegal(text): if text == "": return False forbidden = [] for i in range(65): if i != 32 and i != 46 and i != 45: # space, ., - forbidden.append(chr(i)) for c in text: if c in forbidden: return False return True def setCurrentIndex(): global currentIndex name = fText.getValue().strip() vorname = vText.getValue().strip() person = find(name, vorname) if person == None: return False personid = person[0] indexList = [item[0] for item in resultSet] currentIndex = indexList.index(personid) return True def search(): global currentIndex name = fSearch.getValue().strip() vorname = vSearch.getValue().strip() person = find(name, vorname) if person == None: status.setValue("Suche misslungen. Person nicht in Datenbank gefunden.") return personid = person[0] indexList = [item[0] for item in resultSet] currentIndex = indexList.index(personid) showPerson(resultSet[currentIndex]) status.setValue("Suche erfolgreich. Person in Datenbank gefunden.") initSearchDialog() # ---------------- Datenbank-Operationen ---------------- def getAllRecords(): global resultSet with connect(database) as con: cursor = con.cursor() sql = "SELECT * FROM person ORDER BY name, vorname" cursor.execute(sql) resultSet = cursor.fetchall() def find(name, vorname): with connect(database) as con: cursor = con.cursor() sql = "SELECT * FROM person WHERE name LIKE '%s' AND vorname LIKE '%s'" %(name, vorname) cursor.execute(sql) person = cursor.fetchone() return person # None, if not found def insert(): a = fText.getValue().strip() b = vText.getValue().strip() c = wText.getValue().strip() d = gText.getValue().strip().lower() e = jText.getValue() if not validate(a, b, c, d, e): return if find(a, b) != None: status.setValue("Person bereits in Datenbank enthalten.") return with connect(database) as con: cursor = con.cursor() sql = """INSERT INTO person (name, vorname, wohnort, geschlecht, jahrgang) VALUES ('%s', '%s', '%s', '%s', %d)""" %(a, b, c, d, e) cursor.execute(sql) status.setValue("Person erfolgreich in Datenbank aufgenommen.") setInsertMode(False) getAllRecords() setCurrentIndex() showPerson(resultSet[currentIndex]) def update(): name = fText.getValue().strip() vorname = vText.getValue().strip() wohnort = wText.getValue().strip() geschlecht = gText.getValue().strip() jahrgang = jText.getValue() nameOld = resultSet[currentIndex][1] vornameOld = resultSet[currentIndex][2] if not validate(name, vorname, wohnort, geschlecht, jahrgang): return with connect(database) as con: cursor = con.cursor() sql = """UPDATE person SET name = '%s', vorname = '%s', wohnort = '%s', geschlecht = '%s', jahrgang = '%s' WHERE name = '%s' AND vorname = '%s'""" \ %(name, vorname, wohnort, geschlecht, jahrgang, nameOld, vornameOld) # use global name, vorname cursor.execute(sql) status.setValue("Person erfolgreich mutiert.") getAllRecords() setCurrentIndex() def delete(): name = fText.getValue() vorname = vText.getValue() if not find(name, vorname): status.setValue("Löschen misslungen. Person nicht in Datenbank") return with connect(database) as con: cursor = con.cursor() sql = "DELETE FROM person WHERE name = '%s' AND vorname = '%s'" %(name, vorname) cursor.execute(sql) getAllRecords() if resultSet == []: # Datenbank leer setInsertMode(True) status.setValue("Person erfolgreich aus Datenbank entfernt. Datenbank leer.") else: doFirst() status.setValue("Person erfolgreich aus Datenbank entfernt. Zeige ersten Datensatz an.") # ================== Hauptprogramm =================== # --------------- Dialog aufbauen ------------- fText = StringEntry("Name: ") vText = StringEntry("Vorname: ") wText = StringEntry("Wohnort: ") gText = StringEntry("Geschlecht: (m/w)): ") jText = IntEntry("Jahrgang (Zahl): ") pane1 = EntryPane("Information", fText, vText, wText, gText, jText) firstBtn = ButtonEntry("First") lastBtn = ButtonEntry("Last") nextBtn = ButtonEntry("Next") prevBtn = ButtonEntry("Prev") pane2 = EntryPane("Navigation", firstBtn, prevBtn, nextBtn, lastBtn) deleteBtn = ButtonEntry("Delete") insertBtn = ButtonEntry("Insert") saveBtn = ButtonEntry("Save") cancelBtn = ButtonEntry("Cancel") pane3 = EntryPane("Mutation", deleteBtn, insertBtn, saveBtn, cancelBtn) fSearch = StringEntry("Name: ") vSearch = StringEntry("Vorname: ") pane4 = EntryPane("Suche", fSearch, vSearch) searchBtn = ButtonEntry("Search") pane5 = EntryPane(searchBtn) status = StringEntry("") status.setEditable(False) pane6 = EntryPane("Status", status) dlg = EntryDialog(pane1, pane2, pane3, pane4, pane5, pane6) dlg.setTitle("Databank-Manager") # --------------- ResultSet für ganze Datenbank holen ------------- resultSet = [] getAllRecords() if resultSet == []: # database empty setInsertMode(True) status.setValue("Datenbank leer.") else: doFirst() setInsertMode(False) # --------------- Ereignisschleife ------------- while not dlg.isDisposed(): if firstBtn.isTouched(): doFirst() setInsertMode(False) if lastBtn.isTouched(): doLast() setInsertMode(False) if nextBtn.isTouched(): doNext() if prevBtn.isTouched(): doPrevious() elif searchBtn.isTouched(): search() elif saveBtn.isTouched(): if isInsertMode: insert() else: update() elif cancelBtn.isTouched(): if resultSet != []: # not empty database setInsertMode(False) doFirst() else: status.setValue("Bitte Personendaten eintragen und Save klicken oder Fenster schliessen.") elif deleteBtn.isTouched(): delete() elif insertBtn.isTouched(): if not isInsertMode: setInsertMode(True) initDialog() status.setValue("Bitte Personendaten eintragen und Save oder Cancel klicken.") else: insert() finishBtn.setEnabled(True) |
Programmcode markieren
|
|
Das Programm SportManager.py:
# SportManager.py from sqlite3 import * from entrydialog import * from prettytable import * database = "demo.db" def doFirst(): global currentIndex currentIndex = 0 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doLast(): global currentIndex currentIndex = len(resultSet) - 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doNext(): global currentIndex if currentIndex == len(resultSet) - 1: status.setValue("Ende der Datenbank erreicht.") return currentIndex += 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def doPrevious(): global currentIndex if currentIndex == 0: status.setValue("Beginn der Datenbank erreicht.") return currentIndex -= 1 showPerson(resultSet[currentIndex]) status.setValue("Person " + str(currentIndex + 1) + " von " + str(len(resultSet))) def validate(lValue, hValue, wValue): return True def showPerson(person): fText.setValue(person[1]) vText.setValue(person[2]) personid = person[0] with connect(database) as con: cursor = con.cursor() sql = "SELECT * FROM sport where id = " + str(personid) cursor.execute(sql) leistungen = cursor.fetchone() if leistungen == None: # Person not yet in table; should not happen lEntry.setValue(None) wEntry.setValue(None) hEntry.setValue(None) else: # if NULL in table, leistungen[i] = None -> empty entry lEntry.setValue(leistungen[1]) wEntry.setValue(leistungen[2]) hEntry.setValue(leistungen[3]) def setCurrentIndex(): global currentIndex name = fText.getValue().strip() vorname = vText.getValue().strip() person = find(name, vorname) if person == None: return False personid = person[0] indexList = [item[0] for item in resultSet] currentIndex = indexList.index(personid) return True def search(): global currentIndex name = fText.getValue().strip() vorname = vText.getValue().strip() person = find(name, vorname) if person == None: status.setValue("Suche misslungen. Person nicht in Datenbank gefunden.") return personid = person[0] indexList = [item[0] for item in resultSet] currentIndex = indexList.index(personid) showPerson(resultSet[currentIndex]) status.setValue("Suche erfolgreich. Person in Datenbank gefunden.") # ---------------- Datenbank-Operationen ---------------- def getAllRecords(): global resultSet with connect(database) as con: cursor = con.cursor() sql = "SELECT * FROM person ORDER BY name, vorname" cursor.execute(sql) resultSet = cursor.fetchall() def find(name, vorname): with connect(database) as con: cursor = con.cursor() sql = "SELECT * FROM person WHERE name LIKE '%s' AND vorname LIKE '%s'" %(name, vorname) cursor.execute(sql) person = cursor.fetchone() return person # None, if not found def insert(): lValue = lEntry.getValue() if lValue == None: lValue = 'NULL' hValue = hEntry.getValue() if hValue == None: hValue = 'NULL' wValue = wEntry.getValue() if wValue == None: wValue = 'NULL' if not validate(lValue, hValue, wValue): return personid = resultSet[currentIndex][0] with connect(database) as con: cursor = con.cursor() sql = "DELETE FROM sport WHERE personid = " + str(personid) cursor.execute(sql) sql = "INSERT INTO sport VALUES (%s, %s, %s, %s)" %(personid, lValue, hValue, wValue) cursor.execute(sql) status.setValue("Leistungen erfolgreich in Datenbank übernommen.") def report(discipline): with connect(database) as con: cursor = con.cursor() if discipline == "all": sql = """SELECT name, vorname, lauf, hochsprung, weitsprung FROM person JOIN sport ON person.id == sport.id ORDER BY name, vorname""" elif discipline == "lauf": sql = """SELECT name, vorname, lauf FROM person JOIN sport ON person.id == sport.id ORDER BY lauf ASC""" elif discipline == "hoch": sql = """SELECT name, vorname, hochsprung FROM person JOIN sport ON person.id == sport.id ORDER BY hochsprung DESC""" elif discipline == "weit": sql = """SELECT name, vorname, weitsprung FROM person JOIN sport ON person.id == sport.id ORDER BY weitsprung DESC""" cursor.execute(sql) printTable(cursor) status.setValue("Report ausgeschrieben.") # ================== Hauptprogramm =================== # --------------- Dialog aufbauen ------------- fText = StringEntry("name: ") vText = StringEntry("Vorname: ") pane1 = EntryPane("Sportler/Sportlerin", fText, vText) firstBtn = ButtonEntry("First") lastBtn = ButtonEntry("Last") nextBtn = ButtonEntry("Next") prevBtn = ButtonEntry("Prev") searchBtn = ButtonEntry("Search") pane2 = EntryPane(firstBtn, prevBtn, nextBtn, lastBtn, searchBtn) lEntry = FloatEntry("Laufzeit: ") wEntry = FloatEntry("Weitsprung: ") hEntry = FloatEntry("Hochsprung: ") pane3 = EntryPane("Leistungen", lEntry, wEntry, hEntry) deleteBtn = ButtonEntry("Delete") insertBtn = ButtonEntry("Insert") saveBtn = ButtonEntry("Save") pane4 = EntryPane(saveBtn) allBtn = ButtonEntry("Alle") laufBtn = ButtonEntry("Lauf") hochBtn = ButtonEntry("Hoch") weitBtn = ButtonEntry("Weit") pane5 = EntryPane("Reports/Ranglisten", allBtn, laufBtn, weitBtn, hochBtn) status = StringEntry("") status.setEditable(False) pane6 = EntryPane("Status", status) dlg = EntryDialog(pane1, pane2, pane3, pane4, pane5, pane6) dlg.setTitle("Sport-Manager") # --------------- ResultSet für ganze Datenbank holen ------------- resultSet = [] getAllRecords() if resultSet == []: # database empty status.setValue("Datenbank leer. Zuerst Persondaten eingeben.") else: doFirst() # --------------- Ereignisschleife ------------- while not dlg.isDisposed(): if firstBtn.isTouched(): doFirst() if lastBtn.isTouched(): doLast() if nextBtn.isTouched(): doNext() if prevBtn.isTouched(): doPrevious() elif searchBtn.isTouched(): search() elif saveBtn.isTouched(): insert() elif allBtn.isTouched(): report("all") elif laufBtn.isTouched(): report("lauf") elif hochBtn.isTouched(): report("weit") elif weitBtn.isTouched(): report("hoch") |
Programmcode markieren
|