Seite 1 von 1

Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Mittwoch 4. April 2018, 21:20
von anbey7
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()

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 13:38
von wuf
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:

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 15:14
von Sirius3
@wuf: und um was unterscheiden sich Deine ganzen if-Blöcke in `layout_manager`?

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 15:25
von wuf
@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:

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 16:02
von Sirius3
@wuf: oder anders ausgedrückt, um nichts als eine Variable.

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 17:08
von wuf
@Sirius3: Das heisst?
Gruss wuf :wink:

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 18:08
von Sirius3

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)

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 18:21
von wuf
OK Sirius3

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

Gruss wuf :wink:

Re: Fenster mit variablen Einstellungsmöglichkeiten

Verfasst: Donnerstag 5. April 2018, 19:11
von anbey7
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