Problem mit Tkinter Grid Geometry Manager

Fragen zu Tkinter.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jbaben hat geschrieben:zu GuiDesigner: das Modul "DynTkInter.py" ist im gleichen Direktorie (Pfad) wie "main.py" vorhanden.
Vielleicht liegt das Problem mit der Einstellung meiner Umgebungsvariablen (PATH).
OS = WINDOWS 10 Pro 64 Bit
Ich weiß auch nicht. Habe geschaut ob ich irgend ein __pycache__ mit auf github draufgespielt habe. Aber war nicht der Fall. Habe es auch einmal mit Windows 7 ultimate probiert. Ging auch. Bis auf eine Kleinigkeit: hatte im Menü leere Label als Platzhalter eingesetzt, aber in Windows sah man da: ( )

Scheint ein allgemeines Problem bei Deinem Windows zu sein, daß Du in Python nichts importieren kannst. Mußt Du eben selber rausfinden, woran das liegt.
jbaben
User
Beiträge: 24
Registriert: Dienstag 12. Januar 2016, 16:05

Hallo,

so nun habe ich mir den gezeigten Code zu meiner Anordnung angeschaut.
Am besten hat mir der Code von "wuf" gefallen.
Da bei diesem Beispiel mit dem "Pack Manager" auch das maximieren funktioniert.
Bei dem Beispiel mit dem "Grid Manager" ist die Anordnung der Elemente Ok, jedoch funktioniert hier das maximieren nicht (die Elemente wandern nicht mit).

Das Problem ist nun das ich die Syntax im Code verstehen muss um den Code entsprechend meinen Anforderungen ändern zu können.

Vielen Dank noch einmal für Eure Hilfe.

MfG

Juergen B.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

[quote="jbaben"Am besten hat mir der Code von "wuf" gefallen.
Da bei diesem Beispiel mit dem "Pack Manager" auch das maximieren funktioniert.
Bei dem Beispiel mit dem "Grid Manager" ist die Anordnung der Elemente Ok, jedoch funktioniert hier das maximieren nicht (die Elemente wandern nicht mit).[/quote]
Ja stimmt, bei grid paß sich die Containergröße dem Platz, welche die grid widgets darin haben, an.
Vielleicht steht aber hier bei columnconfigure und rowconfigure der weight parameter damit im Zusammenhang. Muß ich mal ausprobieren. Könnte sein, daß es dann doch geht.

Bei pack kann man auch dafür sorgen, dass sich die Widgetgröße der Containergröße anpaßt, sofern dieser groß genug ist.
jbaben
User
Beiträge: 24
Registriert: Dienstag 12. Januar 2016, 16:05

Hallo,

so habe nun den Code um ein neues Fenster erweitert:

Code: Alles auswählen

def service(self):
        service = tk.Toplevel()
        frame = tk.Frame(service)
        service.title('Service-Seite')
        frame.pack()
        # Frame fuer Button "Auswahl Alarmzone"
        service.button1_frame = tk.Frame(service)
        service.button1_frame.pack(fill='x')
        # Button "Auswahl Alarmzone"
        Button_Select1 = tk.Button(service.button1_frame, text='Auswahl Alarmzone', font = 12, command = self.select_alarmzone )
        Button_Select1.pack(side='left', fill='x', padx=0, pady=0)
        # Frame fuer Button "Benutzer Verwaltung"
        service.button2_frame = tk.Frame(service)
        service.button2_frame.pack(fill='x')
        # Button "Benutzer Verwaltung"
        Button_Select2 = tk.Button(service.button2_frame, text='Benutzer Verwaltung', font = 12, command = self.benutzer_verwaltung )
        Button_Select2.pack(side='left', fill='x', padx=0, pady=0)
        # Frame fuer Button "zurück"
        service.button3_frame = tk.Frame(service)
        service.button3_frame.pack(fill='x')
        # Button zum Schließen des Fensters
        ButtonBack = tk.Button(service.button3_frame, text='zurück', command=self.haupt)
        ButtonBack.pack(side='left', fill='x', padx=0, pady=0)
Sieht zwar noch nicht so aus wie ich mir das vorstelle.
Meine Frage zu dem neuen Fenster: wie kann ich das neue Fenster über den Button "zurück" beenden ?
Mit "self.service.destroy() klappt es nicht.

MfG
Juergen B.
:?:
jbaben
User
Beiträge: 24
Registriert: Dienstag 12. Januar 2016, 16:05

Hallo,

ich habe den Fehler gefunden (habe das "self" vergessen).
So funktioniert das schließen des Fensters mit "self.service.destroy()"

Code: Alles auswählen

def service(self):
        # neues Fenster erzeugen
        self.service = tk.Toplevel()
        self.frame = tk.Frame(self.service)
        self.service.title(SERVICE_TITLE)
        self.service.geometry("+{}+{}".format(SERVICE_XPOS, SERVICE_YPOS))
        self.service.geometry("{}x{}".format(SERVICE_WIDTH, SERVICE_HEIGHT))
        self.frame.pack()
        
        # Frame fuer Button "Auswahl Alarmzone"
        self.service.button1_frame = tk.Frame(self.service)
        self.service.button1_frame.pack(fill='both', expand=True)
        # Button "Auswahl Alarmzone"
        Button_Select1 = tk.Button(self.service.button1_frame, text='Auswahl Alarmzone', font = 12, command = self.select_alarmzone )
        Button_Select1.pack(side='left', fill='x', padx=5, pady=0)
        # Frame fuer 
        self.service.z1_frame = tk.Frame(self.service)
        self.service.z1_frame.pack(fill='x')
        # Frame fuer Button "Benutzer Verwaltung"
        self.service.button2_frame = tk.Frame(self.service)
        self.service.button2_frame.pack(fill='both', expand=True)
        # Button "Benutzer Verwaltung"
        Button_Select2 = tk.Button(self.service.button2_frame, text='Benutzer Verwaltung', font = 12, command = self.benutzer_verwaltung )
        Button_Select2.pack(side='left', fill='x', padx=5, pady=0)
        # Frame fuer Button "zurück"
        self.service.button3_frame = tk.Frame(self.service)
        self.service.button3_frame.pack(fill='both', expand=True)
        # Button zum Schließen des Fensters
        ButtonBack = tk.Button(self.service.button3_frame, text='zurück', command=self.haupt)
        ButtonBack.pack(side='left', fill='x', padx=5, pady=0)
MfG

Juergen B.
:D
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jbaben hat geschrieben:Hallo,
so nun habe ich mir den gezeigten Code zu meiner Anordnung angeschaut.
Am besten hat mir der Code von "wuf" gefallen.
Da bei diesem Beispiel mit dem "Pack Manager" auch das maximieren funktioniert.
Bei dem Beispiel mit dem "Grid Manager" ist die Anordnung der Elemente Ok, jedoch funktioniert hier das maximieren nicht (die Elemente wandern nicht mit)..
Ist klar daß Dir das Beispiel von wuf am Besten gefallen hat, der hatte sich auch, die Mühe gemacht, eine Variablennamen zu benützen und nicht die GUI zu generieren mit durchnummerierten Variablennamen und das in alphabetischer Reihenfolge, also ziemlich willkürlich.

SWEnn man allderdings die richtigen Variablenname benützt und das Layout in der Reihenfolge Zeile, Spalte anordnet, wird so ein Grid Layout sehr übersichtlich.

Ich finde überhaupt, dass das Gridlayout, das einfachste und beste Layout ist.

Das Packlayout erfordert eine Zerpflückung in diverse Frames und dann noch Subframes.
Vorteil: man kann es tun durch Nachdenken und muß es nicht vor Augen haben.

Das Panelayout paßt sich nicht an und ohne ein Programm, wie einen Guigeneratur ist es nicht einfach. Aber alle Guigeneratore beherrschen das Panelayout.

Das Gridlayout erscheint schwierig, swenn man es nicht vor Augen hat und so nicht weiß, warum etwas nicht klappt. Aber wenn man sieht, was los ist, ist es eigentlich das einfachste Layout.

Eine kleine Funktion bewältigt das Problem, daß man nicht erkennt, was los ist:

Code: Alles auswählen

def show_grid_table(container,rows,columns):
    for row in range(rows):
        for column in range(columns):
            tk.Frame(container,relief= 'solid',bd =1,bg ='#b3d9d9').grid(row=row, column=column, sticky='news')
Und wenn man diese benützt, ist es einfach ein Grid Layout zu erstellen. Ich habe jetzt mal Deinen Code entsprechend angepaßt, aber ohne Deine Callbacks, sondern nur die Widgets mit dem Layout:

Code: Alles auswählen

import tkinter as tk

# for development ===========================
SHOW_GRID_TABLE = True # for development purposes

GRID_ROW_DEFAULT = { 'minsize' : 25, 'weight' : 1}
GRID_COL_DEFAULT = { 'minsize' : 75, 'weight' : 1}

def show_grid_table(container,rows,columns):
    for row in range(rows):
        for column in range(columns):
            tk.Frame(container,relief= 'solid',bd =1,bg ='#b3d9d9').grid(row=row, column=column, sticky='news')

# === general grid table definition =================
def grid_general_rows(container,rows,**kwargs):
    for row in range(rows):
        container.rowconfigure(row,**kwargs)

def grid_general_columns(container,columns,**kwargs):
    for column in range(columns):
        container.columnconfigure(column,**kwargs)

# Application definition =============================            

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.frame = Frame_1(self,height=600, width=600)
        self.frame.pack(fill='both', expand=1)

class Frame_1(tk.Frame):

    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)
        rows = 9
        columns = 8

        # general grid definition for development =============
        # grid_general_rows(self,9,**GRID_ROW_DEFAULT)
        # grid_general_columns(self,8,**GRID_COL_DEFAULT)

        # general grid definition ==============================
        grid_general_rows(self,rows,weight=1)
        grid_general_columns(self,columns,weight=1)

        # individual grid definition ===========================
        self.rowconfigure(0,minsize = 16, weight = 0)    # top margin
        self.rowconfigure(rows-1,minsize = 16, weight = 0)    # bottom margin
        self.columnconfigure(0,minsize = 16, weight = 0) # left margin
        self.columnconfigure(columns-1,minsize = 16, weight = 0) # right margin
        self.columnconfigure(5,minsize = 16, weight=1) # space before buttons

        # for development =====================================
        if SHOW_GRID_TABLE:
            show_grid_table(self,rows,columns)

        # widget definition ====================================
        self.alarm_on = tk.Button(self,text='Alarm aktivieren')
        self.alarm_status_height = tk.Button(self, state='disabled', relief='flat') # a dummy button for same row height
        self.alarm_status = tk.Label(self,text='Alarm inaktiv')
        self.close = tk.Button(self,text='Close')
        self.feueralarm = tk.Button(self,text='Feueralarm')
        self.medical = tk.Button(self,text='Medical')
        self.panik = tk.Button(self,text='Panik')
        self.radiobutton_1 = tk.Radiobutton(self,font='12', text='A', value=1)
        self.radiobutton_2 = tk.Radiobutton(self,font='12', text='B', value=2)
        self.radiobutton_3 = tk.Radiobutton(self,font='12', text='C', value=3)
        self.radiobutton_4 = tk.Radiobutton(self,font='12', text='D', value=4)
        self.service = tk.Button(self,text='Service')
        self.text = tk.Text(self,height=5, width=30)
        self.text_label1 = tk.Label(self,font='12', text='Alarmzone')

        # layout definition ====================================

        # row 1
        self.text_label1.grid(row=1, column=1, columnspan=3, sticky='ew', padx=5, pady=5)

        # row 2
        self.radiobutton_1.grid(row=2, column=1, padx=5)
        self.radiobutton_2.grid(row=2, column=2)
        self.radiobutton_3.grid(row=2, column=3)
        self.radiobutton_4.grid(row=2, column=4)
        self.alarm_on.grid(row=2, column=6, sticky='ew', pady=2)

        # row 3
        self.text.grid(row=3, column=1, columnspan=4, rowspan=4,  sticky='nesw')
        self.alarm_status_height.grid(row=3, column=6,sticky = 'ew', pady = 2) # a dummy button for same row height
        self.alarm_status.grid(row=3, column=6)

        # row 4
        self.feueralarm.grid(row=4, column=6, sticky='ew', pady=2)

        # row 5
        self.medical.grid(row=5, column=6, sticky='ew', pady=2)
    
        # row 6
        self.panik.grid(row=6, column=6, sticky='ew', pady=2)

        # row 7
        self.close.grid(row=7, column=1,columnspan=2,  sticky='ew', pady=2)
        self.service.grid(row=7, column=6, sticky='ew', pady=2)


        # callback definition ====================================
        # ...
        
Application().mainloop()
Wie gefällt Dir das? :?:

PS: möchtest Du allerdings, dass die Buttons auch in der Höhe wachsen, dann wären sticky = "news" und eine Zwischenraumzeile statt pady = 2 angebracht.
jbaben
User
Beiträge: 24
Registriert: Dienstag 12. Januar 2016, 16:05

Hallo,

der gezeigt Code gefällt mir sehr gut.
Werde ich mit arbeiten.
Vielen Dank für Deine Arbeit.

MfG

Juergen B.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jbaben hat geschrieben: der gezeigt Code gefällt mir sehr gut.
Werde ich mit arbeiten.
Vielen Dank für Deine Arbeit.
Ich habe auch zu danken, denn Dein Problem hat mich inspiriert. Habe jetzt meinem GuiDesigner auch columnconfigure und rowconfigure für den Export und Reimport in und von tkinter beigebracht.

Kannst ja einmal ansehen: https://github.com/AlfonsMittelmeyer/py ... -messaging
Antworten