Lexikon als Gui

Fragen zu Tkinter.
Antworten
solver
User
Beiträge: 7
Registriert: Freitag 19. Januar 2018, 20:43

Hallo,

ich möchte gern ein kleines Lexikon als Gui programmieren.
Es soll ungefähr so aussehen wie auf dem Bild.

Bild

Auf den Buttons links sollen die Wörter des Lexikons angezeigt werden.
Bei Klick auf einen Button soll im Textfeld rechts die Erklärung zum geklickten Button geladen werden.
Die Erklärung soll man über das Textfeld ändern können.

Momentan sieht mein Code folgendermaßen aus:

Code: Alles auswählen

from tkinter import *
import functools


class Application(Frame):
    def __init__(self, master):
        super(Application, self).__init__(master)
        self.grid()
        self.create_textanzeige()
        self.create_objects()

    def create_textanzeige(self):
        self.textanzeige = Text(height=2, width=50)
        self.textanzeige.grid()

    def create_objects(self):
        self.objects = {"zebra": "Das Zebra lebt in Afrika. \nEs ist ein Saeugetier.",
                        "koala": "Der Koala lebt in Australien. \nEr ist ein Beuteltier.",
                        "Känguru": "Das Känguru lebt in Australien und ist ein Beuteltier."
                        }

        for wort, erklaerung in self.objects.items():
            but = Button(self, text=wort, command=functools.partial(self.textanzeige.insert, END, erklaerung))
            but.grid()


root = Tk()
root.title("Lexikon")
root.geometry("410x200")

app = Application(root)

root.mainloop()
Aktuelles Problem:

Jedes Mal, wenn ein Button angeklickt wird, wird die jeweilige Erklärung geladen, ohne dass die vorherige Erklärung gelöscht wird.
Aber eigentlich soll die vorherige Erklärung gelöscht werden und die neue Erklärung eingefügt werden.
Wie kann ich dies erreichen?



Vielen Dank fürs Lesen und Helfen im Voraus

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

`insert` heisst halt „einfügen“, und nicht „ersetzen”. Ersetzen gibt's auf `Text`-Widgets nicht, das muss man sich aus zwei anderen Operationen basteln. Hier steht was es so für Methoden gibt auf `Text`-Widgets: https://effbot.org/tkinterbook/text.htm

Widgets sollten sich nicht selbst anordnen, das ``self.grid()`` gehört nicht in die `__init__()`. Dafür ist das auslagern der Erzeugung der GUI in extra Methoden nicht wirklich sinnvoll.

Sternchen-Importe sind Böse™. `tkinter` wird üblicherweise als ``import tkinter as tk`` importiert, und die Werte aus dem Modul dann über ``tk.Button`` usw. angesprochen.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du dir mal die Methoden von tkinter.Text angeschaut? Ich bin sicher da findest du etwas: http://effbot.org/tkinterbook/text.htm
solver
User
Beiträge: 7
Registriert: Freitag 19. Januar 2018, 20:43

Vielen Dank für die Hinweise auf die Methoden.
Ich habe nun einen Weg gefunden, wie ich eine Funktion mit den beiden Methoden und den jeweiligen Argumenten definieren kann. Diese wird durch Klick auf den Button als command ausgeführt.

sieht jetzt folgendermaßen aus:

Code: Alles auswählen

import tkinter as tk
import functools


class Application(tk.Frame):
    def __init__(self, master):
        super(Application, self).__init__(master)
        self.grid()
        self.create_textanzeige()
        self.create_objects()

    def ersetzen(self, erklaerung):
        self.textanzeige.delete(1.0, tk.END)
        self.textanzeige.insert(tk.END, erklaerung)

    def create_textanzeige(self):
        self.textanzeige = tk.Text(height=2, width=50)
        self.textanzeige.grid()

    def create_objects(self):
        self.objects = {"zebra": "Das Zebra lebt in Afrika. \nEs ist ein Saeugetier.",
                        "koala": "Der Koala lebt in Australien. \nEr ist ein Beuteltier.",
                        "Känguru": "Das Känguru lebt in Australien und ist ein Beuteltier."
                        }

        for wort, erklaerung in self.objects.items():
            self.temp_text = erklaerung
            but = tk.Button(self, text=wort, command=functools.partial(self.ersetzen, erklaerung))
            but.grid()


root = tk.Tk()
root.title("Lexikon")
root.geometry("410x200")

app = Application(root)

root.mainloop()
Als nächstes werde ich einen Weg suchen, damit nach Änderung der Erklärung im Textfeld die neue Erklärung gespeichert wird.
Wenn ich bei einem Problem Hilfe brauche, melde ich mich wieder.
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein Tk-Element sollte sich nicht selbst platzieren, weil Du jetzt auf grid festgelegt bist, obwohl das übergeordnete Fenster vielleicht besser per pack anordnen möchte.
Was soll self.temp_text?
Benutzeravatar
__blackjack__
User
Beiträge: 14092
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@solver: Beim `Text`-Widget gibst Du gar nicht an wo das angezeigt werden soll, was dazu führt das es direkt im Hauptfenster landet, was ziemlich undurchsichtig ist.

Code: Alles auswählen

#!/usr/bin/env python3
from functools import partial
import tkinter as tk


class Application(tk.Frame):
    
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.objects = {
            'Zebra': 'Das Zebra lebt in Afrika. \nEs ist ein Saeugetier.',
            'Koala': 'Der Koala lebt in Australien. \nEr ist ein Beuteltier.',
            'Känguru': 'Das Känguru lebt in Australien und ist ein Beuteltier.',
        }
        frame = tk.Frame(self)
        for wort, erklaerung in self.objects.items():
            tk.Button(
                frame, text=wort, command=partial(self.ersetzen, erklaerung)
            ).pack(side=tk.TOP)
        frame.pack(side=tk.LEFT, anchor=tk.NW)
        
        self.textanzeige = tk.Text(self, height=2, width=50)
        self.textanzeige.pack(side=tk.LEFT, anchor=tk.NW)

    def ersetzen(self, erklaerung):
        self.textanzeige.delete(1.0, tk.END)
        self.textanzeige.insert(tk.END, erklaerung)


def main():
    root = tk.Tk()
    root.title('Lexikon')

    app = Application(root)
    app.pack()

    root.mainloop()


if __name__ == '__main__':
    main()
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
solver
User
Beiträge: 7
Registriert: Freitag 19. Januar 2018, 20:43

Okay. Das ist für mich als Anfänger erstmal viel neues. Da werde ich mich genauer damit beschäftigen, wenn ich die Zeit habe.
Der Unterschied ob man .grid() oder .pack() verwendet ist anscheinend ziemlich wesentlich.
Was den allgemeinen Aufbau einer Gui angeht, kann ich auch noch viel lernen.
Antworten