Database output in Combobox aktualisieren

Fragen zu Tkinter.
Antworten
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

Schönen guten Tag,

ich lasse mir in einer Combobox Sachen aus einer Datenbank anzeigen und würde gerne, dass diese sich nach einer Änderung aktualisiert und das Geänderte auch sofort angezeigt wird, ohne dass ich das Fenster schließen und wieder öffnen muss.
Hab schon ein paar Sachen ausprobiert, aber wahrscheinlich was falsch gemacht^^
Bestimmt kann mir einer von euch helfen.
Danke im Voraus.
Hier der gekürzte Code:

Code: Alles auswählen

from tkinter import *
import os
from tkinter.ttk import Combobox
import tkinter as tk
import sqlite3
DB = 'test.db'

if (not os.path.isfile(DB)):
    conn = sqlite3.connect(DB)
    c = conn.cursor()
    c.execute('''CREATE TABLE test_db (
                id INT AUTO_INCREMENT GENERATED BY DEFAULT IDENTITY PRIMARY KEY,
                name    VARCHAR NOT NULL)
                ''')
    c.execute('''INSERT INTO test_db(id,name) VALUES
                (0,'test1'),
                (NULL,'test2'),
                (NULL,'test3'),
                (NULL,'test4')
                ''')
    conn.commit()
    conn.close()

def loesch_test():
    conn = sqlite3.connect(DB)
    c = conn.cursor()
    c.execute('DELETE FROM test_db WHERE name = (:test)',
    {
        'test' : test.get()
    })
    conn.commit()
    conn.close()

def combo_input_test():
    conn = sqlite3.connect(DB)
    c = conn.cursor()
    c.execute('SELECT name FROM test_db ORDER BY name COLLATE NOCASE')
    data = []
    for row in c.fetchall():
        data.append(row[0])
    return data
    conn.commit()
    conn.close()

Fenster = tk.Tk()
text=Label(Fenster, text='test-Typen')
text.grid()
test = Combobox(Fenster, state='readonly')
test['values'] = combo_input_test()
test.grid()
test.current(0)

Lösch = Button(Fenster, text='Löschen', command=loesch_test)
Lösch.grid()

Fenster.mainloop()
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Du meinst, wenn irgend ein anderer Prozess die Tabelle ändert, oder wenn Dein eigenes Programm die Tabelle ändert?
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

wenn ich über den Lösch btn das ausgewählte lösche, dann soll es alles den Rest anzeigen der noch drin ist.
Quasi ein refresh oder update machen
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann mußt Du doch nur beim Löschen die ComboBox aktualisieren, wie Du sie auch initialisierst.
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

Wenn es so einfach wäre, dann hätte ich ja nichts hier rein geschrieben.^^
Bekomme es nicht hin
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze diese Zeile:

Code: Alles auswählen

test['values'] = combo_input_test()
Anmerkungen zum Code: Du benutzt schon `import tkinter as tk` aber gleichzeitig noch den schlechten *-Import. Warum?
Die Klammern um die if-Bedingung sind überflüssig.
Variablen schreibt man komplett klein. Benutze keine Abkürzungen, conn -> connection, c -> cursor.
Eine Connection ist etwa langlebiges und sollte nur einmal am Anfang des Programms erstellt und immer wieder benutzt werden.
Alles was eine Funktion braucht, sollte sie über ihre Argumente bekommen und es sollte keine globalen Variablen geben, indem die Zuweisungen auf oberster Ebene in eine Funktion main wandern.
Alles was nach `return` kommt, wird nicht mehr errreicht, die Verbindung also nicht mehr geschlossen.

Code: Alles auswählen

import os
import sqlite3
import tkinter as tk
from tkinter.ttk import Combobox
from functools import partial

DATABASE_FILENAME = 'test.db'

def initialize_database():
    if not os.path.isfile(DATABASE_FILENAME):
        connection = sqlite3.connect(DATABASE_FILENAME)
        cursor = connection.cursor()
        cursor.execute('''CREATE TABLE test_db (
                    id INT PRIMARY KEY,
                    name    VARCHAR NOT NULL)
                    ''')
        cursor.execute('''INSERT INTO test_db(name) VALUES
                    ('test1'),
                    ('test2'),
                    ('test3'),
                    ('test4')
                    ''')
        connection.commit()
        connection.close()

def delete_test(connection, tests):
    cursor = connection.cursor()
    cursor.execute('DELETE FROM test_db WHERE name = (:test)',
        {'test' : tests.get()})
    connection.commit()
    cursor.close()

def get_tests(connection):
    cursor = connection.cursor()
    cursor.execute('SELECT name FROM test_db ORDER BY name COLLATE NOCASE')
    data = [row[0] for row in cursor]
    cursor.close()
    return data

def main():
    initialize_database()
    connection = sqlite3.connect(DATABASE_FILENAME)
    fenster = tk.Tk()
    tk.Label(fenster, text='test-Typen').pack()
    tests = Combobox(fenster, state='readonly')
    tests['values'] = get_tests(connection)
    tests.pack()
    tests.current(0)
    tk.Button(fenster, text='Löschen', command=partial(delete_test, connection, tests)).pack()
    fenster.mainloop()

if __name__ == '__main__':
    main()
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

Danke erst mal für deine Hinweise, werde versuchen sie zu beherzigen und bin dankbar für jeden Rat, lerne es ja noch.
Anmerkungen zum Code: Du benutzt schon `import tkinter as tk` aber gleichzeitig noch den schlechten *-Import. Warum?
Durch meine komische Schreibweise hat es immer rumgemeckert, wenn ich eins von beidem weggelassen habe^^

Code: Alles auswählen

test['values'] = combo_input_test()
hatte ich schon versucht mit reinzuschmuggeln, hat aber nicht das gemacht was ich wollte.
gibt es einen test.set() Befehl welcher auf das nächste in der Liste springt?
Zuletzt geändert von Count am Samstag 20. Juni 2020, 19:58, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann zeig doch, wie Du es versucht hast.
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

hatte meine Antwort noch mal konkretisiert

hatte es einfach bei meinem Code
ans Ende von def loesch_test() gesetzt

es löscht es aus der Liste ist aber noch ausgewählt
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, die Auswahl ist unabhängig von der Liste. Die mußt Du mit current noch ändern, wie Du es bei der Initialisierung ja auch gemacht hast.
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

Danke, du hast mir echt geholfen.
Hoffe ich kann mich in ferner Zukunft mal revanchieren :D
Antworten