askopenfilename als Variable aus Fkt ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Hallo liebes Forum,

dies ist mein Eintrag in diesem Forum. Damit möchte ich euch mitteilen, dass ich ein Python-Anfänger bin.

Ich habe einen Button erstellt, der dem Nutzer die Möglichkeit gibt eine Datei auszuwählen. Der Dateiname Name wird anschließend in ein Eingabefenster geladen. Dies funktioniert bisher gut. Ob ich den effizientesten und schönsten Weg gewählt habe, weiß ich nicht. Wenn ihr dort Verbesserungsvorschläge habt, könnt ihr dort gerne "meckern" :)

Nun möchte ich aber auch den Pfad, der in der Variable "path" hinterlegt ist, auch außerhalb der Funktion nutzen. Dieser wird nämlich später in der Hauptfunktion aufgerufen. Ich habe mir mehrere Beiträge hier im Forum zu dem Thema angeschaut und diese auch verstanden. Z.B. wurde folgender Code zur Erklärung verwendet.

Code: Alles auswählen

def subtrahieren(a, b):
    c = a - b
    return c

ergebnis = subtrahieren(17, 6)
print(ergebnis)
Diesen verstehe ich auch. Allerdings kann ich dieses Wissen nicht auf mein Beispiel übertragen. In meinem Beispiel möchte ich ein String ausgeben. Muss ich deswegen etwas anderes beachten? Ich habe drüber nachgedacht, ob ich einen Eingabewert festlegen sollte aber ich wüsste nicht welchen.
Ich weiß, dass ich durch return path nicht einfach print(path) nutzen kann. Ich müsste es irgendwie in der Form machen, wie es im "Subtrahieren-Beispiel" gemacht wird.

Ich wäre euch sehr dankbar, wenn ich mir helfen könntet. Ich habe nämlich das Gefühl, dass es kein kompliziertes Problem ist sondern mir einfach das know-how fehlt.


Ich habe meinen Code gekürzt, sodass ich euch hier nur den Teil zeige, der das Problem beschreibt.

Code: Alles auswählen

from openpyxl import Workbook, load_workbook
from openpyxl.utils import get_column_letter, column_index_from_string, coordinate_to_tuple
from openpyxl.styles import Font
from PIL import ImageTk, Image, ImageChops
import os
import tkinter as tk
from tkinter import filedialog


# Hier wird das Hauptfenster der GUI erstellt
fenster = tk.Tk()
fenster.geometry("1000x600")
fenster.configure(bg = 'white')
fenster.title("Titel")


def browse_file():

    # Auswählen der Datei
    path = filedialog.askopenfilename(initialdir="/", title="Select a File", filetypes=(("Excel files", "*.xlsx*"), ("all files", "*.*")))

    # Dateinnamen vom Pfad trennen
    filename = os.path.split(path)[1]   # Dateinname wird vom vollständigen Pfad gesplittet

    # Filename wird ins Eingabefenster geladen
    eingabefeld_dateiname_testspec.insert(0,filename)
    return path



# translates an rgb tuple of int to a tkinter friendly color code
def _from_rgb(rgb):
    return "#%02x%02x%02x" % rgb


# Dateiname Testspec Label
dateiname_testspec = tk.Label(fenster, text="Dateiname Testspec: ", bg=_from_rgb((147, 177, 191)))
dateiname_testspec.place(x = 10, y = 140, width=120, height=30)

# Eingabefenster des Dateinamen der Testspec
eingabefeld_dateiname_testspec = tk.Entry(fenster, bd=5, width=40)
eingabefeld_dateiname_testspec.place(x = 140, y = 140, width=500, height=30)

# "Browse File" Button
dateiname_testspec_button = tk.Button(fenster, text="...", command=browse_file,)
dateiname_testspec_button.place(x = 650, y = 140, width=40, height=30)

signalmatrix_erstellen_button = tk.Button(fenster, text="Signalmatrix erstellen", command=fenster.quit, bg='lightgrey',
                                       font='bold')
signalmatrix_erstellen_button.place(x = 30, y = 500, width=180, height=60)


#####################################################################################################

def main():
    testspec_sheet = load_workbook(path).active

    workbook = Workbook()
    workbook.active.title = "Test"


if __name__ == "__main__":
    main()
Sirius3
User
Beiträge: 18278
Registriert: Sonntag 21. Oktober 2012, 17:20

So funktionieren GUIs nicht. Man braucht Klassen um darin die Information zu speichern.
Außerdem benutzt man keine absoluten Größen- oder Positionsangaben. Ich habe mal alles durch pack ersetzt, aber es gibt auch noch grid und Frames um es schöner zu gestalten.

Hier fehlt natürlich noch, dass der Button deaktiviert ist, solange noch kein Pfad eingegeben worden ist. Im Moment ist das Entry-Feld auch noch falsch, weil man dort etwas eingeben kann, was aber nicht berücksichtigt wird.

Code: Alles auswählen

import os
import tkinter as tk
from tkinter import filedialog
from openpyxl import load_workbook

class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.path = None

        self.configure(bg = 'white')
        self.title("Titel")
        tk.Label(self, text="Dateiname Testspec: ").pack()
        self.eingabefeld_dateiname_testspec = tk.Entry(self, bd=5, width=40)
        self.eingabefeld_dateiname_testspec.pack()

        tk.Button(self, text="...", command=self.browse_file).pack()
        tk.Button(self, text="Signalmatrix erstellen",
            command=self.erstelle_signatur, bg='lightgrey', font='bold').pack()

    def browse_file(self):
        path = filedialog.askopenfilename(initialdir="/", title="Select a File", filetypes=(("Excel files", "*.xlsx*"), ("all files", "*.*")))
        filename = os.path.basename(path)
        self.eingabefeld_dateiname_testspec.insert(0,filename)
        self.path = path

    def erstelle_signatur(self):
        testspec = load_workbook(self.path).active
        ...

def main():
    main_window = MainWindow()
    main_window.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
noisefloor
User
Beiträge: 4195
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

mittels `return` gibst du, allgemein gesprochen, ein Objekt zurück, dass du an eine Variable binden kannst. Wie im subtrahieren Beispiel.

Bei `dateiname_testspec_button = tk.Button(fenster, text="...", command=browse_file,)` machst du aber was anderes: da bindest du eine Instanz von tk.Button an die Variable `dateiname_testspec_button`. In dieser Instanz weist du dem Attribut `command` das Objekt `browse_file` zu. In dem Fall ist das Objekt halt eine Funktion. Was damit passiert ist innerhalb der Klasse `tk.Button` definiert, die du instanzierst. Ein Rückgabewert wird da jedenfalls nicht erwartet.

Bei der Programmierung von GUIs ist es immer sehr sinnvoll, ein Verständnis von objektorientierter Programmierung, Klassen und deren Instanzen zu haben, weil man da bei GUIs quasi nicht umhin kommt. Und bei allem ausser mega-trivialen GUIs sollten man die GUI in eine Klasse packen, wäre bei dir auch der Fall. Ein Beispiel dafür ist in der Python-Doku. Dann kannst du auch z.B. den Pfadnamen an ein Attribut deiner Klasse binden und somit ist der Pfadname für "greifbar".

Hast du dich schon mal mit Klassen und deren Instanzen beschäftigt? Wenn nein wäre jetzt ein guter Zeitpunkt das z.B. im Tutorial der Python-Doku auf docs.python.org nachzulesen :-)

Gruß, noisefloor
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Hallo,

erst einmal vielen Dank für die Rückmeldungen.

Na dann sieht es wohl so aus als hätte ich noch einiges nachzuholen.

Allerdings verstehe ich nicht warum man keine absoluten Größen- oder Positionsangaben benutzt. Meine GUI wird noch weitere Buttons und Funktionen erhalten. Wenn es einen anderen Endbenutzer geben wird, ist's doch sinnvoll das ein wenig "schick" zu gestalten. Zudem habe ich bereits Frames und ein Logo verwendet und die sollen vordefinierte Position haben und nicht irgendwo platziert werden.

Gruß
Krystek
Sirius3
User
Beiträge: 18278
Registriert: Sonntag 21. Oktober 2012, 17:20

"schick" wird es nur, wenn man per Frames und grid/pack die Elemente auf dem Fenster automatisch anordnen läßt. Sonst ist die GUI für andere Nutzer nicht bedienbar, weil sich alles überlagert, oder Teile außerhalb des Fensters liegen.
Benutzeravatar
__blackjack__
User
Beiträge: 14077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Du weisst doch gar nicht wie gross der Bildschirm auf einem beliebigen Rechner ist, also wie viele Pixel und wie gross physisch, und dementsprechend auch nicht wie viele Pixel Schrift zum Beispiel benötigt, also kannst Du auch nicht problemlos Grössen und Positionen absolut in Pixeln angeben.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten