Programm Verbesserungen und Verständnis beim Klassen / Durchreichen von Klassen
Verfasst: Sonntag 9. Juni 2024, 11:48
Guten Tag
Ich habe ein Programm geschrieben mit GTK.Oberfläche und SQLite-Datenbank. Mich würden mal allgemeine Verbesserungsvorschläge interessieren, da ich, obwohl ich mich viel mit dem Thema beschäftige, ein paar Grundprinzipien noch nicht drin habe,
Das Programm ist ein Fenster mit einer (Haupt-)Box darin, oben ist ein Label und ein "Hinzufügen"-Knopf. In das Label schreibt man ein Datum, und es wird für diesen Tag, wenn er noch nicht existiert, ein neues Widget(Box) erstellt. Dieses wird dann zu Hauptbox hinzugefügt und ein Eintrag in der Datenbank wird angelegt.
Bei Änderungen am Text werden diese gespeichert,
Hier wusste ich noch nicht wie das besser umzusetzen ist, es ist ja nicht vorteilhaft, wenn ich 100 Buchstaben schreibe 100 Mal in der Datenbank gespeichert wird. Habe hier an einen Timer gedacht, der alle zwei Sekunden ausgeführt wird. Also das quasi die Speichern-Funktion eine Warteschleife bekommt. Schreibt man und klickt eine Sekunde später auf den Entferne-Knopf würde mein Widget und der Eintrag in der Datenbank dann entfernt, im Hintergrund wird der Datensatz dann jedoch wieder erstellt, was ja so nicht gewünscht ist.
Auch stellt sich mir hier die Frage, ob ich die Connection zu Datenbank nicht offen lassen sollte. Gerade wird diese 100 Mal geöffnet und geschlossen bei dem Beispiel oben.
Überprüfen von Werten und Formatierungen soll hier erstmal keine Rolle spielen (z.B. Datum-Format)

Hier der Code:
Ich habe ein Programm geschrieben mit GTK.Oberfläche und SQLite-Datenbank. Mich würden mal allgemeine Verbesserungsvorschläge interessieren, da ich, obwohl ich mich viel mit dem Thema beschäftige, ein paar Grundprinzipien noch nicht drin habe,
Das Programm ist ein Fenster mit einer (Haupt-)Box darin, oben ist ein Label und ein "Hinzufügen"-Knopf. In das Label schreibt man ein Datum, und es wird für diesen Tag, wenn er noch nicht existiert, ein neues Widget(Box) erstellt. Dieses wird dann zu Hauptbox hinzugefügt und ein Eintrag in der Datenbank wird angelegt.
Bei Änderungen am Text werden diese gespeichert,
Hier wusste ich noch nicht wie das besser umzusetzen ist, es ist ja nicht vorteilhaft, wenn ich 100 Buchstaben schreibe 100 Mal in der Datenbank gespeichert wird. Habe hier an einen Timer gedacht, der alle zwei Sekunden ausgeführt wird. Also das quasi die Speichern-Funktion eine Warteschleife bekommt. Schreibt man und klickt eine Sekunde später auf den Entferne-Knopf würde mein Widget und der Eintrag in der Datenbank dann entfernt, im Hintergrund wird der Datensatz dann jedoch wieder erstellt, was ja so nicht gewünscht ist.
Auch stellt sich mir hier die Frage, ob ich die Connection zu Datenbank nicht offen lassen sollte. Gerade wird diese 100 Mal geöffnet und geschlossen bei dem Beispiel oben.
Überprüfen von Werten und Formatierungen soll hier erstmal keine Rolle spielen (z.B. Datum-Format)

Hier der Code:
Code: Alles auswählen
#!/usr/bin/env python3
import sqlite3
import datetime
import sys
from gi.repository import Gtk
import gi
gi.require_version("Gtk", "3.0")
class MyWindow(Gtk.Window):
database_name = "test.db"
widgets = {}
def __init__(self):
super().__init__(title="MyWindow", border_width=5)
self.set_default_size(500, 300)
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(
Gtk.PolicyType.ALWAYS,
Gtk.PolicyType.ALWAYS)
self.add(scrolled_window)
self.box = Gtk.VBox(spacing=10, border_width=15)
scrolled_window.add(self.box)
add_button = Gtk.Button(label="Add")
self.box.pack_start(add_button, False, True, 0)
add_button.connect("clicked", self.on_add_button_clicked)
self.date_entry = Gtk.Entry(text="22.02.2024")
self.box.pack_start(self.date_entry, False, True, 0)
self.database = Database(database_name=self.database_name)
self.create_database()
self.load_from_database()
def run(self):
self.show_all()
Gtk.main()
def create_database(self):
self.database.create()
def load_from_database(self):
data = self.database.get_data()
for d in data:
self.create_new_widget(date=d[0], text=d[1])
def save_to_database(self, widget, update=False):
self.database.save_or_update(
[widget.get_date(), widget.get_text()],
update=update)
def remove_from_database(self, widget):
self.database.remove_row(date=widget.get_date())
def on_add_button_clicked(self, widget):
date = self.date_entry.get_text()
self.create_new_widget(date=date, save=True)
def on_remove_button_clicked(self, button, new_widget):
self.remove_from_database(new_widget)
new_widget.destroy()
def create_new_widget(self, date, text="", save=False):
if date in self.widgets.keys():
self.widgets[date].textview.grab_focus()
return
new_widget = DayEntry(date=date, text=text)
# connect methodes from class DayEntry
new_widget.textbuffer.connect(
"changed", self.on_entry_changed, new_widget)
new_widget.remove_button.connect(
"clicked", self.on_remove_button_clicked, new_widget)
self.box.pack_start(new_widget, True, True, 0)
self.widgets[date] = new_widget
new_widget.show_all()
if save:
self.save_to_database(new_widget)
def on_entry_changed(self, textbuffer, new_widget):
self.save_to_database(new_widget, update=True)
class Database():
def __init__(self, database_name):
self.database_name = database_name
def create(self):
con = sqlite3.connect(self.database_name)
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS days(date UNIQUE, text)")
cur.execute(
"INSERT OR IGNORE INTO days VALUES(?, ?)", [
"01.02.2003", "Sample Text"])
cur.execute(
"INSERT OR IGNORE INTO days VALUES(?, ?)", [
"15.04.2007", "Another Text"])
con.commit()
con.close()
def remove_row(self, date):
con = sqlite3.connect(self.database_name)
cur = con.cursor()
cur.execute('DELETE FROM days WHERE date=?', [date])
con.commit()
con.close()
def save_or_update(self, data, update=False):
date = data[0]
text = data[1]
con = sqlite3.connect(self.database_name)
cur = con.cursor()
if update:
cur.execute('UPDATE days SET text=? WHERE date=?',
[text, date])
else:
cur.execute("INSERT OR IGNORE INTO days VALUES(?, ?)",
[date, text])
con.commit()
con.close()
def get_data(self,):
con = sqlite3.connect(self.database_name)
cur = con.cursor()
res = cur.execute("SELECT * FROM days")
data = res.fetchall()
con.close()
return data
class DayEntry(Gtk.HBox):
def __init__(self, date="", text=""):
super().__init__(spacing=10, border_width=10)
self.label = Gtk.Label(label=date)
self.pack_start(self.label, False, True, 0)
self.textview = Gtk.TextView(border_width=10)
self.pack_start(self.textview, True, True, 0)
self.textbuffer = self.textview.get_buffer()
self.textbuffer.set_text(text, len(text))
self.remove_button = Gtk.Button(label="Remove")
self.pack_start(self.remove_button, False, True, 0)
def get_text(self):
start_iter = self.textbuffer.get_start_iter()
end_iter = self.textbuffer.get_end_iter()
return self.textbuffer.get_text(start_iter, end_iter, True)
def set_text(self, text):
self.textbuffer.set_text(text, len(text))
def get_date(self):
return self.label.get_label()
if __name__ == "__main__":
app = MyWindow()
app.run()