Seite 1 von 1

Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 05:34
von Bl3nder
Guten Morgen,


Ich habe folgende Frage bzw Problem Ich möchte gerne eine Funktion für unterschiedliche Widgets.

Beispiel:

Ich habe 2 Entrys bei beiden öffnet sich per klick ein Filedialog danach möchte Ich die dazugehörige Textvariable setzen.Da der Grundsatz dont repeat yourself im Kopf rumschwiert weiß Ich leider nicht wie Ich das schaffe diese Funktion so zu stricken das sie mit mehreren events gekoppelt werden kann.


Code: Alles auswählen

import configparser
from pathlib import Path
import tkinter as tk
from tkinter import filedialog


def config_datei_laden(default_pfad):
    """
    Falls Configdatei vorhanden ist ( je nach dem wo das skript liegt) wird diese ausgelesen
    :return: dictonary mit pfaden
    """
    if default_pfad.exists():
        config = configparser.ConfigParser()
        config.read(default_pfad)
        pfade_dict = {}
        for section in config.sections():
            for (key, value) in config.items(section):
                pfade_dict[key] = value
        return pfade_dict


def gui(config_pfade):
   

    def file_dialog():
        ausgewaehlter_ordner = tk.filedialog.askdirectory()
        textvariable.set(ausgewaehlter_ordner)

    # Hauptfenster
    window = tk.Tk()
    window.title("Konfigurator")
    window.geometry("300x300")

    config_frame = tk.Frame()
    textvariable = tk.StringVar()
    config_label = tk.Label(master=config_frame, text="Pfad zur Konfigurationsdatei:")
    if not list(config_pfade.values())[0] == "test":
        textvariable.set(str(list(config_pfade.values())[0]))
    config_entry = tk.Entry(master=config_frame, text=textvariable)
    config_entry.bind("<1>", file_dialog)    #<--------------------------------------- hier geht es drum später möchte Ich mehrere solcher pfade eingeben und das dafür nur eine Funktion haben 
    config_label.grid(row=1, column=1, padx=5, pady=5)
    config_entry.grid(row=1, column=2, padx=5, pady=5)

    # Frame positionieren
    config_frame.pack(fill="both", expand=True)

    window.mainloop()




def main():
    config_pfaden = config_datei_laden((Path(__file__).parent / "config.ini"))
    gui(config_pfaden)


if __name__ == "__main__":
    main()


p.s Ich habe es schon mit lamda versucht aber dann wird immer ( mehrere funktionen hintereinander aufgerufen lambda x: [filedialog(),textvariable.set(x)] nur x ist das quasi einfach nur das event objekt)

Jemand eine Idee ?

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 07:54
von rogerb
@Bl3nder,

es gibt bei bind() noch einen dritten Parameter: 'add'
Damit kann man weitere Funktionen verbinden:

Code: Alles auswählen

config_entry.bind("<1>", function1)
config_entry.bind("<1>", function2, "+")
Wenn 'add' ein leerer String ist "", werden alle existierenden Bindungen aufgelöst und die neue Funktion als erste und einzige verbunden.
Wenn 'add' ein '+' enthält bleiben die bestehenden Verbindungen bestehen und die neue Funktion wird hinzugefügt.

https://docs.python.org/3/library/tkint ... and-events

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 08:01
von Bl3nder
Ok danke ich probiere es gleich mal aus :)

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 09:31
von Bl3nder
Ok vill war die Frage nicht ganz klar gestellt von mir also mal angenommen ich habe 10 entry Widgets die alle einen filedialog haben den ich dann in das Feld setzten möchte muss ich dann 10 einzelne callback Funktion machen oder bekommt man sowas auch mit 1 Funktion hin ?

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 10:03
von rogerb
@Bl3nder,

dann würde ich eine Funktionschreiben, die diese 10 oder meinetwegen 100 Widgets in einer Schleife erstellt und auch das binding übernimmt.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 10:50
von __deets__
Ob man das mit 10 oder 1 Funktion hinbekommt hängt doch davon ab, was die machen. Machen die 10 unterschiedliche Dinge? Dann nicht. Machen die 10 mal das gleiche? Dann ja. Und im kontinuum dazwischen kann es sein, dass zb eine Bewertung (von 1 bis 10) abgegeben werden soll, dann kann man natürlich eine Funktion mit dem Wert als Parameter erstellen. Oder Namen oder was auch immer da an Variablität zugrunde liegt, weswegen es mehrere Knöpfe sind.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:05
von rogerb
@__deets__,
Ob man das mit 10 oder 1 Funktion hinbekommt hängt doch davon ab, was die machen. Machen die 10 unterschiedliche Dinge?
Kann sein, dass ich es falsch verstanden habe, aber ich dachte es *ist* nur eine Funktion aber mehrere Widgets, die alle ein binding zu *dieser* Funktion haben sollen.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:23
von Bl3nder
OK Ich mache dann mal einen Pseudocode damit ihr das besser versteht.

Code: Alles auswählen

from pathlib import Path
import tkinter as tk
from tkinter import filedialog



def filedialog():
    ausgewaehlter_ordner = tk.filedialog.askdirectory()
    #textvariable.set(ausgewahlter_ordner)

window = tk.Tk()
config1_entry.bind("<1>", file_dialog)
config2_entry.bind("<1>", file_dialog)
config3_entry.bind("<1>", file_dialog)
config4_entry.bind("<1>", file_dialog)
config5_entry.bind("<1>", file_dialog)
config6_entry.bind("<1>", file_dialog)
config7_entry.bind("<1>", file_dialog)


window.mainloop()

Der Code dient wirklich nur der verdeutlichung ... also Ich habe 10 entry die Ich immer an die gleiche funktion binde ( es soll ein filedialog geöffnet werden) und später setzte Ich dann jedes mal den ausgewählten file_pfad als text in das entry . Und Ich weiß leider nicht wie Ich in dem Fall die Argumente übergeben kann das Ich definiert sagen kann :"OK config3_entry wurde gedrückt" also setze Ich dann auch später die Textvariable in config3 .Ich hoffe ihr könnt mich verstehen .

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:28
von __deets__
Mit functools partial oder einem lambda. Wie immer.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:30
von Bl3nder
also so in der art ?

lambda event, a=1 :file_dialog(a) dann einfach in dem filedialog if a = 1 ... setze die textvariable etc ? macht man das so also ist das so ein gute Umsetzung


Code: Alles auswählen

import configparser
from pathlib import Path
import tkinter as tk
from tkinter import filedialog


def config_datei_laden(default_pfad):
    """
    Falls Configdatei vorhanden ist ( je nach dem wo das skript liegt) wird diese ausgelesen
    :return: dictonary mit pfaden
    """
    if default_pfad.exists():
        config = configparser.ConfigParser()
        config.read(default_pfad)
        pfade_dict = {}
        for section in config.sections():
            for (key, value) in config.items(section):
                pfade_dict[key] = value
        return pfade_dict


def gui(config_pfade):
    # erstellt configdatei
    def configdatei_erstellen():
        config = configparser.ConfigParser()
        config['PATH_DEFAULT'] = {"wetterstation_pfad": r"C:\Users\Marcel\Desktop\WETTERSTATION"}
        with open('config.ini', 'w') as configfile:
            config.write(configfile)

    def file_dialog(test):

        ausgewaehlter_ordner = tk.filedialog.askdirectory()
        if test == 1:
            textvariable.set(ausgewaehlter_ordner)

    # Hauptfenster
    window = tk.Tk()
    window.title("Konfigurator")
    window.geometry("300x300")

    config_frame = tk.Frame()
    textvariable = tk.StringVar()
    config_label = tk.Label(master=config_frame, text="Pfad zur Konfigurationsdatei:")
    if not list(config_pfade.values())[0] == "test":
        textvariable.set(str(list(config_pfade.values())[0]))
    config_entry = tk.Entry(master=config_frame, text=textvariable)
    config_entry.bind("<1>", lambda event, a=1 :file_dialog(a))
    config_label.grid(row=1, column=1, padx=5, pady=5)
    config_entry.grid(row=1, column=2, padx=5, pady=5)

    # Frame positionieren
    config_frame.pack(fill="both", expand=True)

    window.mainloop()


def main():
    config_pfaden = config_datei_laden((Path(__file__).parent / "config.ini"))
    gui(config_pfaden)


if __name__ == "__main__":
    main()



Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:33
von __deets__
Das ist der Weg, Argumente reinzubekommen, ja.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 11:39
von Bl3nder
ok alles klar vielen dank euch beiden

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 12:12
von Sirius3
Statt lambda benutzt man functools.partial.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 12:14
von __deets__
@Sirius3: das fliegt mir regelmäßig um die Ohren, weil der tkinter wrapper das nicht schluckt. Leider.

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 15:16
von Sirius3
Was schluckt denn der nicht?

Re: Eine Funktion für mehrere Widgets

Verfasst: Mittwoch 21. Juli 2021, 16:25
von __deets__
Ein Partial Objekt. Bin ich schon diverse Male drüber gestolpert. Und defaulte darum bei tkinter immer auf lambdas 🤷‍♂️