Fenster mit variablen Einstellungsmöglichkeiten

Fragen zu Tkinter.
Antworten
anbey7
User
Beiträge: 3
Registriert: Donnerstag 12. Oktober 2017, 10:45

Hallo zusammen
Ich versuche in meiner GUI ein Optionsfenster mit variablen Einstellungsmöglichkeiten zu realisieren.

Ich habe die verschiedenen Widgets in der Funktion in eine for-Schleife gepackt, um sie über die Funktionsparameter zu platzieren. Die Funktionsparameter werden mittels Radiobutton übergeben.

Meine Frage:
Kann ich das so machen, oder gibt es eine bessere Lösung?

Falls Ok, habe ich das Problem, das die Widgets (Umrandungen) wie Buttons immer sichtbar sind, auch wenn keine Buttons sein sollten.
Nach meinem Verständnis als Anfänger, liegt das Problem wahrscheinlich bei der Variable spalte in der for-Schleife die die Widgets Anordnungen speichert und erst beim beenden des Programms gelöscht werden. Wie kann ich das ändern?

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import tkinter as tk
import tkinter.ttk as ttk

class Optionen_Frame(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)

        # ----------------------------------- Layoutwidget -------------------------------------

        def layoutwidget(buttonspalte,combospalte,checkspalte,widget_txt):

            widget_txt1,widget_txt2,widget_txt3,widget_txt4,widget_txt5,widget_txt6 = widget_txt

            self.como_txt = ('1. Jan', '1. Febr', '1. März', '1. Apr', '1. Mai', '1. Juni',
                               '1. Juli', '1. Aug', '1. Sept', '1. Okt', '1. Nov', '1. Dez',)
            var = tk.StringVar()
            eingabespalte = []
            for spalte in range(6):
                if spalte in buttonspalte:
                    button = tk.Button(self.widgetrahmen,
                                       width=15,
                                       height=2,
                                       relief=tk.GROOVE,
                                       justify=tk.CENTER)
                    button.grid(row=1, column=spalte + 1)
                    eingabespalte.append(button)
                elif spalte in combospalte:
                    combo = ttk.Combobox(self.widgetrahmen,
                                         width=10,
                                         font=12,
                                         values=self.como_txt,
                                         justify=tk.CENTER)
                    combo.grid(row=1, column=spalte + 1)
                    eingabespalte.append(combo)
                elif spalte in checkspalte:
                    check = tk.Checkbutton(self.widgetrahmen,
                                           width=10,
                                           height=2,
                                           justify=tk.CENTER,
                                           bg=farbe_innen,
                                           activebackground=farbe_innen,
                                           anchor=tk.W,
                                           variable=var)
                    check.grid(row=1, column=spalte + 1)
                    eingabespalte.append(check)
                else:
                    label = tk.Label(self.widgetrahmen,
                                        width=15,
                                        height=2,
                                        bg=farbe_innen,
                                        anchor=tk.E)
                    label.grid(row=1, column=spalte + 1)
                    eingabespalte.append(label)

            erstes_widget = eingabespalte[0]
            erstes_widget.config(text=widget_txt1)
            zweites_widget = eingabespalte[1]
            zweites_widget.config(text=widget_txt2)
            drittes_widget = eingabespalte[2]
            drittes_widget.config(text=widget_txt3)
            viertes_widget = eingabespalte[3]
            viertes_widget.config(text=widget_txt4)
            füntes_widget = eingabespalte[4]
            füntes_widget.config(text=widget_txt5)
            sechstes_widget = eingabespalte[5]
            sechstes_widget.config(text=widget_txt6)

        # ----------------------------------- Layoutmanager -----------------------------------

        def layoutmanager():
            inhalt = self.var.get()
            if inhalt == self.txt_neu:
                self.textAnzeige.config(textvariable=self.var)
                #  [ Button ], [ Combobox ], [Checkbutton], ( Text )
                layoutwidget([0],[5],[],('Neuer Eintrag\nspeichern','','','','Gültig ab:',''))
            elif inhalt == self.txt_ändern:
                self.textAnzeige.config(textvariable=self.var)
                layoutwidget([0],[5],[2],('Änderung\nspeichern','','Mit Einfluss','','Gültig ab:',''))
            elif inhalt == self.txt_löschen:
                self.textAnzeige.config(textvariable=self.var)
                layoutwidget([0,4,5,],[],[],('Eintrag\nlöschen','','','','Jahresanfang\nAlles auf Null','Alles\nlöschen'))
            else:
                self.textAnzeige.config(textvariable=self.var)
                layoutwidget([0,1,3,4,5],[],[],('Nur Aktive\nanzeigen','Alle\nanzeigen','','ID-Nummer\n sortieren',
                              'Rechnungssteller\n sortieren','Jahreskosten\n sortieren'))

        # ----------------------------------- Rahmen -------------------------------------------

        farbe_innen = 'GREY85'


        self.textAnzeige = tk.Label(self,)
        self.textAnzeige.pack()

        self.hauptrahmen = tk.Label(self,
                                    bg=farbe_innen,
                                    relief=tk.GROOVE)
        self.hauptrahmen.pack(pady=10,padx=20)

        self.radiorahmen = tk.Label(self.hauptrahmen,
                                    bg=farbe_innen)
        self.radiorahmen.pack(pady=10)

        self.widgetrahmen = tk.Label(self.hauptrahmen,
                                     bg=farbe_innen)
        self.widgetrahmen.pack(pady=10)

        # -----------------------------  Radiobutten ----------------------------------------

        self.txt_ansicht = 'Datenansicht'
        self.txt_neu = 'Neue Einträge speichern'
        self.txt_ändern = 'Einträge ändern'
        self.txt_löschen = 'Div. Löschvorgänge'

        self.hf_titel = (self.txt_ansicht, self.txt_neu, self.txt_ändern, self.txt_löschen)
        self.var = tk.StringVar()
        self.var.set(self.txt_ansicht)
        for a in self.hf_titel:
            rb = tk.Radiobutton(self.radiorahmen,
                                text=a,
                                value=a,
                                width=28,
                                bg=farbe_innen,
                                activebackground=farbe_innen,
                                variable=self.var,
                                command=layoutmanager)
            rb.pack(side=tk.LEFT)

        self.layoutmanager = layoutmanager()

#===============================================================================
# ************************************************ HAUPTPROGRAMM **************************************
#===============================================================================

class Hauptprogramm(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.pack()

        self.optionen = Optionen_Frame(self)
        self.optionen.pack()

if __name__ == '__main__':
    root = tk.Tk()
    Hauptprogramm(master=root)
    root.mainloop()
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi anbey7

Willkommen in unserem Forum. Es gibt natürlich x-Varianten um deine Aufgabe zu lösen. Hier meine leicht abgeänderte Variante. Die noch nicht komplett ist:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import tkinter as tk
import tkinter.ttk as ttk

APP_TITLE = "Application"
APP_XPOS = 100
APP_YPOS = 100


class OptionenFrame(tk.Frame):
    CONTAINERS = 6
    CONTAINER_WIDTH = 120
    CONTAINER_HEIGHT = 40
    CONTAINER_XGAP = 4
    CONTAINER_BG = 'gray88'
            
    OPTION_VIEW = 'Datenansicht'
    OPTION_NEW = 'Neue Einträge speichern'
    OPTION_CHANGE = 'Einträge ändern'
    OPTION_CLEAR = 'Div. Löschvorgänge'

    RADIO_BUTTONS = [OPTION_VIEW, OPTION_NEW, OPTION_CHANGE, OPTION_CLEAR] 
    
    BUTTON = 'Button'
    COMBOBOX = 'Combobox'
    CHECKBUTTON = 'Checkbutton'
    
    WIDGET_BG = 'grey85'
    COMBO_VALUES = ('1. Jan', '1. Febr', '1. März', '1. Apr', '1. Mai',
        '1. Juni', '1. Juli', '1. Aug', '1. Sept', '1. Okt', '1. Nov', '1. Dez')
       
    WIDGET_ARANGEMENTS = {
        OPTION_VIEW : [
            [BUTTON, 'Nur Aktive\nanzeigen'],
            [BUTTON, 'Alle\nanzeigen'],
            [],
            [BUTTON, 'ID-Nummer\n sortieren'],
            [BUTTON, 'Rechnungssteller\n sortieren'],
            [BUTTON, 'Jahreskosten\n sortieren']
            ],
        
        OPTION_NEW: [
            [BUTTON, 'Neuer Eintrag\nspeichern'],
            [],
            [],
            [],
            [COMBOBOX, 'Gültig ab:'],
            []
            ],

        OPTION_CHANGE: [
            [BUTTON, 'Änderung\nspeichern'],
            [],
            [CHECKBUTTON, 'Mit Einfluss'],
            [],
            [COMBOBOX, 'Gültig ab:'],
            []
            ],

        OPTION_CLEAR: [
            [BUTTON, 'Eintrag\nlöschen'],
            [],
            [],
            [],
            [COMBOBOX, 'Jahresanfang'],
            [CHECKBUTTON, 'Alles\nlöschen']
            ]
        }
          
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        
        self.widgets = list()
        self.build()
        
    def build(self):
        radio_button_frame = tk.Frame(self)
        radio_button_frame.pack(pady=20)
        
        self.var_radio_buttons = tk.StringVar(None, self.RADIO_BUTTONS[0])
        for button_name in self.RADIO_BUTTONS:
            radio_button = tk.Radiobutton(radio_button_frame,
                text=button_name, value=button_name, width=28,bg=self.WIDGET_BG,
                variable=self.var_radio_buttons,activebackground=self.WIDGET_BG,
                command=self.layout_manager)
            radio_button.pack(side='left')

        option_widget_frame = tk.Frame(self)
        option_widget_frame.pack(pady=20)
        
        for col in range(self.CONTAINERS):
            widget = tk.Frame(option_widget_frame, bg=self.CONTAINER_BG, 
            width=self.CONTAINER_WIDTH, height=self.CONTAINER_HEIGHT)
            widget.propagate(False)
            widget.pack(side='left', padx=self.CONTAINER_XGAP)
            self.widgets.append([widget, None])

    def layout_manager(self):
        option = self.var_radio_buttons.get()

        if option == self.OPTION_VIEW:
            for index, widget in enumerate(
                self.WIDGET_ARANGEMENTS[self.OPTION_VIEW]):
                self.create_widgets(index, widget)
            
        if option == self.OPTION_NEW:
            for index, widget in enumerate(
                self.WIDGET_ARANGEMENTS[self.OPTION_NEW]):
                self.create_widgets(index, widget)

        if option == self.OPTION_CHANGE:
            for index, widget in enumerate(
                self.WIDGET_ARANGEMENTS[self.OPTION_CHANGE]):
                self.create_widgets(index, widget)
                
        if option == self.OPTION_CLEAR:
            for index, widget in enumerate(
                self.WIDGET_ARANGEMENTS[self.OPTION_CLEAR]):
                self.create_widgets(index, widget)
                    
    def create_widgets(self, index, widget):
        widget_frame, content = self.widgets[index]
        
        if content != None:
            content.destroy()
            
        if widget == []: return
        
        widget_type, text = widget
        
        if widget_type == self.BUTTON:
            print('Create Widget:', index, widget_type, text)
            button = tk.Button(widget_frame, relief='groove', bd=2, 
                text=text, justify='center')
            button.pack(fill='both')
            self.widgets[index][1] = button
        
        if widget_type == self.COMBOBOX:
            combobox = ttk.Combobox(widget_frame, values=self.COMBO_VALUES,
                justify='center')
            combobox.pack(expand=True, fill='x')
            combobox.set(text)
            self.widgets[index][1] = combobox

        if widget_type == self.CHECKBUTTON:
            var = tk.StringVar()
            checkbutton = tk.Checkbutton(widget_frame, justify='center',
                anchor='w', bg=self.WIDGET_BG, variable=var)
            checkbutton.pack(expand=True)
            checkbutton['text'] = text
            self.widgets[index][1] = checkbutton


class Application(object):
    def __init__(self, app_win):
        self.app_win = app_win
        
        self.option_frame = OptionenFrame(app_win)
        self.option_frame.pack(padx=20, pady=20)

 
if __name__ == '__main__':
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    
    app = Application(app_win)
    app_win.mainloop()
Viel Spass! Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@wuf: und um was unterscheiden sich Deine ganzen if-Blöcke in `layout_manager`?
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

@Sirius3:
Um das:

Code: Alles auswählen

    OPTION_VIEW = 'Datenansicht'
    OPTION_NEW = 'Neue Einträge speichern'
    OPTION_CHANGE = 'Einträge ändern'
    OPTION_CLEAR = 'Div. Löschvorgänge'
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@wuf: oder anders ausgedrückt, um nichts als eine Variable.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

@Sirius3: Das heisst?
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Code: Alles auswählen

    def layout_manager(self):
        option = self.var_radio_buttons.get()
        widgets = self.WIDGET_ARANGEMENTS[option]
        for index, widget in enumerate(widgets):
            self.create_widgets(index, widget)
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

OK Sirius3

Danke für die Klärung. Du hast recht. Da habe ich es mit meiner Schreiberei ein wenig übetrieben.

Gruss wuf :wink:
Take it easy Mates!
anbey7
User
Beiträge: 3
Registriert: Donnerstag 12. Oktober 2017, 10:45

Wow, danke Wuf und Sirius3 für die super Hilfe. Werde den Code schritt für schritt durchgehen um zu verstehen, was da abgeht :) :wink:.
Besten Dank
Antworten