Anfänger benötigt Hilfe.

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Streifenfrei
User
Beiträge: 1
Registriert: Montag 31. Juli 2023, 21:03

Irgendwie bekomme ich es nicht hin das im detailframe alle Details angezeigt werden. Es werden nur die ersten drei Details angezeigt beim Rest steht N/A, obwohl die Liste (aus der die Daten gezogen werden) mit allen Daten gefüllt ist. ich verstehe es nicht mehr.

Code: Alles auswählen

import tkinter as tk
import json
import tkinter.ttk as ttk

# Funktion zur Aktualisierung des Treeviews basierend auf der Eingabe in der Suchleiste
def update_treeview(*args):
    eingabe = search_var.get()
    if eingabe:
        filtered_ersatzteile = [ersatzteil for ersatzteil in ersatzteile if eingabe in ersatzteil["Teilenummer"]]
    else:
        filtered_ersatzteile = ersatzteile

    ersatzteil_tree.delete(*ersatzteil_tree.get_children())
    for ersatzteil in filtered_ersatzteile:
        ersatzteil_tree.insert("", tk.END, values=(ersatzteil["Teilenummer"], ersatzteil["Ersatzteilname"], ersatzteil["Stückzahl"]))


# Funktion zum Speichern der Daten in einer JSON-Datei
def save_to_file():
    with open("ersatzteile.json", "w") as file:
        json.dump(ersatzteile, file)

# Funktion zur Anzeige des Fensters zum Hinzufügen eines neuen Ersatzteils
add_frame = None  # Globale Variable für das Frame zum Hinzufügen von Ersatzteilen

def add_ersatzteil():
    global add_frame
    add_button.grid_forget()
    ersatzteil_tree.grid_forget()
    search_entry.grid_forget()
    search_button.grid_forget()

    def save_ersatzteil():
        ersatzteil = {
            "Teilenummer": teilenummer_entry.get(),
            "Ersatzteilname": ersatzteilname_entry.get(),
            "Stückzahl": stueckzahl_entry.get(),
            "Lagerort": lagerort_entry.get(),
            "Einkaufspreis": einkaufspreis_entry.get(),
            "Notiz": notiz_entry.get()
        }
        ersatzteile.append(ersatzteil)
        update_treeview()
        save_to_file()
        back_to_main()

    # Neues Frame für die Eingabe der Ersatzteildaten erstellen
    add_frame = tk.Frame(root)  # Erstelle ein neues Frame für das Untermenü
    add_frame.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")  # Frame in Zelle ausdehnen

    teilenummer_label = tk.Label(add_frame, text="Teilenummer:")
    teilenummer_label.grid(row=0, column=0)
    teilenummer_entry = tk.Entry(add_frame)
    teilenummer_entry.grid(row=0, column=1)

    ersatzteilname_label = tk.Label(add_frame, text="Ersatzteilname:")
    ersatzteilname_label.grid(row=1, column=0)
    ersatzteilname_entry = tk.Entry(add_frame)
    ersatzteilname_entry.grid(row=1, column=1)

    stueckzahl_label = tk.Label(add_frame, text="Stückzahl:")
    stueckzahl_label.grid(row=2, column=0)
    stueckzahl_entry = tk.Entry(add_frame)
    stueckzahl_entry.grid(row=2, column=1)

    lagerort_label = tk.Label(add_frame, text="Lagerort:")
    lagerort_label.grid(row=3, column=0)
    lagerort_entry = tk.Entry(add_frame)
    lagerort_entry.grid(row=3, column=1)

    einkaufspreis_label = tk.Label(add_frame, text="Einkaufspreis:")
    einkaufspreis_label.grid(row=4, column=0)
    einkaufspreis_entry = tk.Entry(add_frame)
    einkaufspreis_entry.grid(row=4, column=1)

    notiz_label = tk.Label(add_frame, text="Notiz:")
    notiz_label.grid(row=5, column=0)
    notiz_entry = tk.Entry(add_frame)
    notiz_entry.grid(row=5, column=1)

    save_button = tk.Button(add_frame, text="Hinzufügen", command=save_ersatzteil)
    save_button.grid(row=6, column=0, columnspan=2)

    # Zurück-Button zur Hauptansicht
    back_button = tk.Button(add_frame, text="Zurück", command=back_to_main)
    back_button.grid(row=7, column=0, columnspan=2)

# Funktion zum Wechseln zum Hauptfenster
def back_to_main():
    global add_frame, detail_frame  # Zugriff auf das aktuelle Detail-Fenster
    if add_frame:
        add_frame.grid_forget()  # Entfernen des aktuellen Detail-Fensters
    if detail_frame:
        detail_frame.grid_forget()  # Entfernen des aktuellen Detail-Fensters

    # Frame wechseln
    search_button.grid(row=0, column=1, padx=5, pady=5, sticky="e")  # Suchen-Button rechtsbündig
    search_entry.grid(row=0, column=0, padx=5, pady=5, sticky="w")  # Suchleiste linksbündig
    ersatzteil_tree.grid(row=1, column=0, columnspan=2, padx=5, pady=5)
    add_button.grid(row=2, column=0, columnspan=2, padx=5, pady=5)

# Funktion zur Anzeige der Details eines ausgewählten Ersatzteils
detail_frame = None  # Globale Variable für das Frame der Detailansicht

# ...

def show_ersatzteil_details(event):
    global detail_frame
    selection = ersatzteil_tree.selection()
    if selection:
        item = ersatzteil_tree.item(selection[0])
        ersatzteil = item['values']

        # Verstecke die Liste und den "Neues Ersatzteil hinzufügen"-Button
        ersatzteil_tree.grid_forget()
        add_button.grid_forget()

        # Verstecke die Suchleiste und den Suchen-Button
        search_entry.grid_forget()
        search_button.grid_forget()

        # Entferne die vertikale Scrollbar aus dem detail_frame
        scrollbar_y.grid_forget()

        # Erstelle ein neues Frame für die Detailansicht
        detail_frame = tk.Frame(root)
        detail_frame.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")

        # Labels für die Details erstellen
        details_labels = [
            "Teilenummer", "Ersatzteilname", "Stückzahl", "Lagerort", "Einkaufspreis", "Notiz"
        ]

        for row, detail_label in enumerate(details_labels):
            label = tk.Label(detail_frame, text=f"{detail_label}:")
            label.grid(row=row, column=0, sticky="w", padx=5, pady=2)

            # Wenn der Index in der Liste ersatzteil vorhanden ist, zeige den Wert an, sonst zeige "N/A" an
            value = ersatzteil[row] if row < len(ersatzteil) else "N/A"
            value_label = tk.Label(detail_frame, text=value)
            value_label.grid(row=row, column=1, sticky="w", padx=5, pady=2)

        # Erstelle ein neues Frame für den Zurück-Button
        back_button_frame = tk.Frame(detail_frame)
        back_button_frame.grid(row=len(details_labels) + 1, column=0, columnspan=2, pady=10)

        # Zurück-Button zur Hauptansicht vom Detail-Fenster
        back_button = tk.Button(back_button_frame, text="Zurück", command=back_to_main_detail)
        back_button.pack()

        # Zeige das detail_frame an
        detail_frame.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")  # Fehlende Zeile

# ...



# Funktion zum Wechseln zur Hauptansicht vom Detail-Fenster
def back_to_main_detail():
    global detail_frame
    if detail_frame:
        detail_frame.grid_forget()

    # Frame wechseln
    search_button.grid(row=0, column=1, padx=5, pady=5, sticky="e")  # Suchen-Button rechtsbündig
    search_entry.grid(row=0, column=0, padx=5, pady=5, sticky="w")  # Suchleiste linksbündig
    ersatzteil_tree.grid(row=1, column=0, columnspan=2, padx=5, pady=5)
    add_button.grid(row=2, column=0, columnspan=2, padx=5, pady=5)

# Tkinter GUI erstellen
root = tk.Tk()
root.title("Ersatzteillagerprogramm")

# Ersatzteil-Daten (temporär für dieses Beispiel)
ersatzteile = []

# Versuche die Daten aus der JSON-Datei zu laden
try:
    with open("ersatzteile.json", "r") as file:
        ersatzteile = json.load(file)
except FileNotFoundError:
    pass

# GUI-Elemente erstellen
search_var = tk.StringVar()
search_var.trace("w", update_treeview)  # "w" bedeutet, dass die Funktion update_treeview aufgerufen wird, wenn sich der Wert ändert
search_entry = tk.Entry(root, textvariable=search_var)
search_entry.grid(row=0, column=0, padx=5, pady=5, sticky="w")  # Suchleiste linksbündig

search_button = tk.Button(root, text="Suchen", command=update_treeview)
search_button.grid(row=0, column=1, padx=5, pady=5, sticky="e")  # Suchen-Button rechtsbündig

ersatzteil_tree = ttk.Treeview(root, columns=("Teilenummer", "Ersatzteilname", "Stückzahl"), show="headings")
ersatzteil_tree.heading("Teilenummer", text="Teilenummer")
ersatzteil_tree.heading("Ersatzteilname", text="Ersatzteilname")
ersatzteil_tree.heading("Stückzahl", text="Stückzahl")
ersatzteil_tree.grid(row=1, column=0, columnspan=2, padx=5, pady=5)

# Füge vertikalen Scrollbar zum Treeview hinzu
scrollbar_y = ttk.Scrollbar(root, orient="vertical", command=ersatzteil_tree.yview)
ersatzteil_tree.configure(yscrollcommand=scrollbar_y.set)
scrollbar_y.grid(row=1, column=2, sticky="ns")

# Doppelklick auf ein Ersatzteil im Treeview, um Details anzuzeigen
ersatzteil_tree.bind("<Double-Button-1>", show_ersatzteil_details)

update_treeview()  # Treeview beim Programmstart initialisieren (unchanged)

add_button = tk.Button(root, text="Neues Ersatzteil hinzufügen", command=add_ersatzteil)
add_button.grid(row=2, column=0, columnspan=2, padx=5, pady=5)

root.mainloop()

Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Streifenfrei: Ich denke man wird da nicht viele finden die Lust haben sich das anzuschauen. Schreib das mal ohne ``global``, ohne das immer Elemente aus der GUI gelöscht und hinzugefügt werden, ohne lokale Funktionen, und nur mit Code auf Modulebene der Konstanten, Funktionen, und Klassen definiert. Vielleicht findest Du dabei auch den Fehler schon selbst. Das heisst dann bei jeder nicht-trivialen GUI objektorientierte Programmierung (OOP), also eigene Klasse(n) schreiben.

Man erstellt GUI in der Regel alle genau einmal am Anfang und ändert dann nur deren Inhalt. Wenn man in einem Container-Widget unterschiedliche Inhalte anzeigen will, bastelt man sich da üblicherweise etwas mit `Frame`\s in der gleichen `grid()`-Zelle, die immer den gesamten Platz füllen und wo man den Frame nach vorne holt (`lift()`-Methode) der aktuell sichtbar sein soll. Oder man arbeitet mit Dialogen, beispielsweise um ein neues Ersatzteil zu erfassen.

Beim öffnen von Textdateien sollte man immer die Kodierung angeben. Bei JSON ist das wichtig, denn da muss das UTF-8 sein! Zum lesen kann man die Datei auch im Binärmodus statt als Textdatei öffnen, dann kümmert sich `json.load()` um die korrekte Dekodierung (die Datei darf dann auch UTF-8 + BOM oder eine andere UTF-Kodierung enthalten). Schreiben sollte man aber immer als UTF-8, denn das sagt der Standard.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten