Aktives Button farblich erkennbar machen

Fragen zu Tkinter.
Antworten
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen

Wie kann man ein Button, das man betätigt hat farblich verändern, so daß man dies besser gegenüber den anderen Buttons erkennen kann?

Hier dazu ein kleines Beispiel:

Code: Alles auswählen

#!/usr/bin/python3

import tkinter as tk


CONFIG = {
    'width' : 0,
    'title' : "officeplanet",
    'start_font': ('NimbusSansL', 80), # Startfenster
    'big_font': ('NimbusSansL', 14), # Buttons, Texteingabe
    'txt_font': ('NimbusSansL', 12), # Textausgabe
    'txt_bground': 'grey', # Texteingabe, Textfenster, Buttons
    'font_color': 'black',
    'back_ground' : 'orange'
    }


class View(object):
    def __init__(self, controller, conf):
 
        self.root = tk.Tk()
        self.root.title(conf['title'])
        self.controller = controller
        self.conf = conf
        xpos = 0
        ypos = 0
        screenx = self.root.winfo_screenwidth()
        screeny =  self.root.winfo_screenheight()
        self.root.geometry("%dx%d+%d+%d" % (screenx, screeny, xpos, ypos))

        self.frame = tk.Frame(self.root)
        self.frame.pack(side='top', fill='both', expand=True)

        # Frame rechts
        self.label_right = tk.Label(self.frame, width=18, height=screeny,
            bg=self.conf['back_ground'])
        self.label_right.pack(side='right', fill='both')


        # Buttons rechts
        button_right = {
            '01-Kunden' : lambda: check_Side('01'),
            '02-Lieferanten' : lambda: check_Side('02'),
            '03-Aufträge' : lambda: check_Side('03'),
            '04-Bestellungen' : lambda: check_Side('04'),
            '05-Rechnungen' : lambda: check_Side('05'),
            '06-Verwaltung' : lambda: check_Side('06'),
            '07-Buchhaltung' : lambda: check_Side('07'),
            '08-EDV' : lambda: check_Side('08'),
            '09-Produkte' : lambda: check_Side('09'),
        }
        for row in sorted(button_right):
            tk.Button(self.label_right, width=10,
                text=row.split('-')[1], bg=conf['txt_bground'],
                font=(conf['big_font']), fg=conf['font_color'],
                command=button_right[row]).pack(padx=8, ipady=2, pady=19)

        def check_Side(group):
            if group == '01':
                print('Hallo, hier ist Button 01')
            if group == '02':
                print('Hallo, hier ist Button 02')
            if group == '03':
                print('Hallo, hier ist Button 03')
            if group == '04':
                print('Hallo, hier ist Button 04')
            if group == '05':
                print('Hallo, hier ist Button 05')
            if group == '06':
                print('Hallo, hier ist Button 06')
            if group == '07':
                print('Hallo, hier ist Button 07')
            if group == '08':
                print('Hallo, hier ist Button 08')
            if group == '09':
                print('Hallo, hier ist Button 09')


    def run(self):
        self.frame.mainloop()


class Controller(object):
    def __init__(self):
        self.view = View(self, CONFIG)

    def run(self):
        self.view.run()


def main():
    Controller().run()

if __name__ == '__main__':
    main()
Grüße Nobuddy
Benutzeravatar
StefanLawl
User
Beiträge: 92
Registriert: Donnerstag 7. Juni 2012, 20:23

http://effbot.org/tkinterbook/button.ht ... fig-method
activebackground=
What background color to use when the button is active. The default is system specific. (the option database name is activeBackground, the class is Foreground)
Man sagt uns wir sollen der Idee gedenken und nicht des Mannes. Denn ein Mensch kann versagen. Er kann gefangen werden. Er kann getötet und vergessen werden. Aber 400 Jahre später kann eine Idee immer noch die Welt verändern.
-V
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo StefanLawl

Zu 'activebackground', habe ich das Beispiel hier im Forum gefunden.
Wenn ich mit dem Cursor über das Button gehe, wird es gelb und beim Klicken rot.
Nur bleibt das Button dann nicht rot markiert, sondern nimmt dann wieder das ursprüngliche Farblayout an.

Code: Alles auswählen

import tkinter as tk

root = tk.Tk()
root.title('hallo')
but1 = tk.Button(root, text='Button1', activebackground='yellow')

but1.bind('<ButtonPress-1>',
    lambda ev: but1.config(activebackground='red'))
but1.bind('<ButtonRelease-1>',
    lambda ev: but1.config(activebackground='yellow'))
but1.pack()

but2 = tk.Button(root, text='Button2', activebackground='cyan',
    background='besch'.replace('sch', 'ige'))
but2.pack()

root.mainloop()
Ich möchte aber, daß wenn das Button angeklickt wurde, sich die Farbe des Buttons ändert und beibehält, bis ein anderes Button angewählt wird!
Gibt es dazu eine Lösung?

Grüße Nobuddy
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich habe eine Lösung erarbeitet, welche bestimmt noch verbesserungswürdig ist.

Code: Alles auswählen

#!/usr/bin/python3

import tkinter as tk


CONFIG = {
    'width' : 0,
    'title' : "officeplanet",
    'start_font': ('NimbusSansL', 80), # Startfenster
    'big_font': ('NimbusSansL', 14), # Buttons, Texteingabe
    'txt_font': ('NimbusSansL', 12), # Textausgabe
    'txt_bground': 'grey', # Texteingabe, Textfenster, Buttons
    'font_color': 'black',
    'back_ground' : 'orange'
    }


class View(object):
    def __init__(self, controller, conf):
 
        self.root = tk.Tk()
        self.root.title(conf['title'])
        self.controller = controller
        self.conf = conf
        xpos = 0
        ypos = 0
        screenx = self.root.winfo_screenwidth()
        screeny =  self.root.winfo_screenheight()
        self.root.geometry("%dx%d+%d+%d" % (screenx, screeny, xpos, ypos))

        self.frame = tk.Frame(self.root)
        self.frame.pack(side='top', fill='both', expand=True)

        # Frame rechts
        def lab_r():
            self.label_right = tk.Label(self.frame, width=18, height=screeny,
                bg=self.conf['back_ground'])
            self.label_right.pack(side='right', fill='both')
        lab_r()


        # Buttons rechts
        button_right = {
            '01-Kunden' : lambda: check_Side('01'),
            '02-Lieferanten' : lambda: check_Side('02'),
            '03-Aufträge' : lambda: check_Side('03'),
            '04-Bestellungen' : lambda: check_Side('04'),
            '05-Rechnungen' : lambda: check_Side('05'),
            '06-Verwaltung' : lambda: check_Side('06'),
            '07-Buchhaltung' : lambda: check_Side('07'),
            '08-EDV' : lambda: check_Side('08'),
            '09-Produkte' : lambda: check_Side('09'),
        }
        def button_r(group):
            name = dict()
            for row in sorted(button_right):
                if group == '':
                    self.buttons = tk.Button(self.label_right, width=10,
                        text=row.split('-')[1], bg=conf['txt_bground'],
                        font=(conf['big_font']), fg=conf['font_color'],
                        command=button_right[row]).pack(padx=8, ipady=2, pady=19)
                if group != '':
                    listnames = row.split('-')[0]
                    new_bg = 'yellow'
                    name[group] = [new_bg]
                    if name.get(listnames):
                        self.buttons = tk.Button(self.label_right, width=10,
                            text=row.split('-')[1], bg=name.get(listnames),
                            font=(conf['big_font']), fg=conf['font_color'],
                            command=button_right[row]).pack(padx=8, ipady=2, pady=19)
                    else:
                        self.buttons = tk.Button(self.label_right, width=10,
                            text=row.split('-')[1], bg=conf['txt_bground'],
                            font=(conf['big_font']), fg=conf['font_color'],
                            command=button_right[row]).pack(padx=8, ipady=2, pady=19)
        button_r('')

        def check_Side(group):
            if group == '01':
                self.label_right.destroy()
                lab_r()
                button_r('01')
            if group == '02':
                self.label_right.destroy()
                lab_r()
                button_r('02')
            if group == '03':
                self.label_right.destroy()
                lab_r()
                button_r('03')
            if group == '04':
                self.label_right.destroy()
                lab_r()
                button_r('04')
            if group == '05':
                self.label_right.destroy()
                lab_r()
                button_r('05')
            if group == '06':
                self.label_right.destroy()
                lab_r()
                button_r('06')
            if group == '07':
                self.label_right.destroy()
                lab_r()
                button_r('07')
            if group == '08':
                self.label_right.destroy()
                lab_r()
                button_r('08')
            if group == '09':
                self.label_right.destroy()
                lab_r()
                button_r('09')


    def run(self):
        self.frame.mainloop()


class Controller(object):
    def __init__(self):
        self.view = View(self, CONFIG)

    def run(self):
        self.view.run()


def main():
    Controller().run()

if __name__ == '__main__':
    main()
Vielleicht habt Ihr noch einen besseren Vorschlag?

Grüße Nobuddy
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wir haben es dir ja sicher schon öfter mal gesagt: Hör auf Code zu kopieren und Daten doppelt zu speichern.

- Warum stehen in button_right die Ids im Schlüssel, warum nicht als Wert? Und warum bekonnt check_Side eine Id (ausgerechnet auch noch als String) übergeben, warum nicht gleich der Button?

- check_Side ist eine einzige riesige Kopie. Ist dir nicht aufgefallen, dass die ganze Funktion im Prinzip nur aus diesen drei Zeilen bestehen müsste?

Code: Alles auswählen

self.label_right.destroy()
lab_r()
button_r(group
Hast du die Funktion mal getestet? lab_r dürfte dort gar nicht verfügbar sein. Und warum zersörst du jedes Mal alle Buttons? Warum setzt du nicht einfach die Farbe? Das ist mit Google ja jetzt nicht so schwer herauszufinden.

- Auch deine button_r-Methode ist eine riesige Kopie. Da hast du doch offensichtlich drei Codeblöcke, welche fast vollständig identisch sind.

- Das es neben if und else auch noch elif gibt, solltest du inzwischen auch gelernt haben ;-) Bei der Gelegenheit kannst du dir auch merken, dass man ellenlange if/elif-Kaskaden mittels eines Dictionarys umsetzt.
Das Leben ist wie ein Tennisball.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Nobuddy

Hier nocht etwas betreffs (Aktive Schaltfläche farblich erkennbar machen):

Code: Alles auswählen

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

import sys
import os

try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkFont as fnt
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.font as fnt

class MyButton(tk.Button):

    selected_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR, activebackground=HIGHLIGHT_COLOR)
    
    def __init__(self, parent, **options):
        
        if 'command' in options:
            self.command_call = options['command']
            del options['command']
        else:
            self.command_call = None
            
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
        
    def callback(self, event=None):
        button_obj = MyButton.selected_button_obj
        if button_obj is not None:
            button_obj.config(self.std_conf)
                
        if self.command_call:
            self.config(MyButton.HIGHLIGHT_CONF)
            MyButton.selected_button_obj = self
            self.command_call(event.widget['text']) 

#--- MODUL-TEST ---------------------------------------------------------------#
if __name__ == '__main__':
    
    def button_callback(button_name):
        print(button_name)
                
    app_win = tk.Tk()

    my_buttons = ['Kunden', 'Lieferanten', 'Aufträge', 'Bestellungen',
        'Rechnungen', 'Verwaltung', 'Buchhaltung', 'EDV', 'Produkte']
        
    [MyButton(app_win, text=button_name, command=button_callback
        ).pack(fill='x') for button_name in my_buttons]

    app_win.mainloop()
Gruß wuf :wink:
Take it easy Mates!
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo EyDu

Mir ist der meiste Bullshit anschließend aufgefallen und wollte ihn noch ändern, aber Du warst schneller.
Da rächt sich dann das Kopieren ... :wink:
EyDu hat geschrieben:Wir haben es dir ja sicher schon öfter mal gesagt: Hör auf Code zu kopieren und Daten doppelt zu speichern.

- Warum stehen in button_right die Ids im Schlüssel, warum nicht als Wert? Und warum bekonnt check_Side eine Id (ausgerechnet auch noch als String) übergeben, warum nicht gleich der Button?
Das mit der ID, hat die Reihenfolge der Buttons garantiert und dient zur Weiterverarbeitung.
Klicke ich das Button 'Kunden' an, dann können ja mehrere Funktionen dadurch angesprochen werden.
Wahrscheinlich fehlt mir das Wissen, um es momentan anderst zu machen.
EyDu hat geschrieben:- check_Side ist eine einzige riesige Kopie. Ist dir nicht aufgefallen, dass die ganze Funktion im Prinzip nur aus diesen drei Zeilen bestehen müsste?

Code: Alles auswählen

self.label_right.destroy()
lab_r()
button_r(group
Hast du die Funktion mal getestet? lab_r dürfte dort gar nicht verfügbar sein. Und warum zersörst du jedes Mal alle Buttons? Warum setzt du nicht einfach die Farbe? Das ist mit Google ja jetzt nicht so schwer herauszufinden.
Auf Deinen Code-Vorschlag. bin ich anschließend auch gekommen.
Die Funktion habe ich getestet und funktioniert auch, sonst hätte ich es hier nicht gepostet.
Ich habe zuerst versucht, direkt auf die Buttons Einfluß zu bekommen, was mir aber nicht gelang trotz Google, daher zerstöre ich jedes mal das Label, was mir überhaupt nicht gefällt..
Vielleicht ein Hinweis von Dir?
EyDu hat geschrieben:- Auch deine button_r-Methode ist eine riesige Kopie. Da hast du doch offensichtlich drei Codeblöcke, welche fast vollständig identisch sind.
Ja, verdammtes Kopieren, hätte da zuerst mehr darüber nachdenken sollen.
EyDu hat geschrieben:- Das es neben if und else auch noch elif gibt, solltest du inzwischen auch gelernt haben ;-) Bei der Gelegenheit kannst du dir auch merken, dass man ellenlange if/elif-Kaskaden mittels eines Dictionarys umsetzt.
Das werde ich mir merken und versuchen zu ändern.

Grüße Nobuddy
Zuletzt geändert von Nobuddy am Freitag 16. November 2012, 12:43, insgesamt 1-mal geändert.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo wuf

Das ist genau das, was ich wollte.
Werde mir den Code studieren und dann überlegen, wie ich den in mein Hauptfenster integrieren kann.

Danke und Grüße :wink:
Nobuddy
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo wuf

Zu Deinem wirklich sehr gut funktionierendem Code, habe ich noch Fragen.

Ich habe 2 Spalten Buttons, einmal rechts und einmal auf der linken Seite meines Fensters.
Die rechte Seite der Buttons, sind die Master-Buttons, die dann die Linke Seite der Buttons ansteuert.
Beispiel:
Master-Button = Kunden
Sub-Button-zu-Kunden = [Neuanlage, Formulare, Registrierung, Konditionen, Bank, Info, Kunde, Angebot, History]

Also wenn ich das Button auf der rechten Seite 'Kunden' klicke, wird dann auf der linken Seite die Buttons von 'Sub-Button-zu-Kunden' erstellt.
Muß ich für die linke Seite der Buttons, nochmals eine Class erstellen, die dann 'MySubButtons' heißt und die Linke Seite der Buttons steuert?

Ich habe auch versucht von der Funktion 'button_callback' Werte zu veröffentlichen, was mir aber irgendwie nicht gelingt.

Code: Alles auswählen

def button_callback(button_name):
    self.button_name = button_name
    return self.button_name

print(button_name)
Was mache ich da falsch, oder funktioniert es einfach nicht aus 'button_callback' einen Wert zu veröffentlichen?

Habe da noch einiges zu lernen! :wink:

Grüße Nobuddy
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Ok Nobuddy

Hier eine Erweiterung für die Sub-Buttons (Fürs Wochenend-Studium :wink: ):

Code: Alles auswählen

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

import sys
import os

try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkFont as fnt
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.font as fnt

class MyButton(tk.Button):

    selected_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR, activebackground=HIGHLIGHT_COLOR)
    
    def __init__(self, parent, **options):
        
        if 'command' in options:
            self.command_call = options['command']
            del options['command']
        else:
            self.command_call = None
            
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
        
    def callback(self, event=None):
        button_obj = MyButton.selected_button_obj
        if button_obj is not None:
            button_obj.config(self.std_conf)
                
        if self.command_call:
            self.config(MyButton.HIGHLIGHT_CONF)
            MyButton.selected_button_obj = self
            self.command_call(event.widget['text']) 

#--- MODUL-TEST ---------------------------------------------------------------#
if __name__ == '__main__':
    
    def button_callback(button_name):
        """Rückruf der Haupt-Buttons"""
        
        print("Button (rechts): {0}".format(button_name))
        # Entferne alle bestehende Sub-Buttons aus dem linken Frame
        [button.destroy() for button in button_frame_left.winfo_children()]
        # Kontrolle: Hat der aktivierte rechte Button zugehörige Sub-Buttons?
        if button_name in my_sub_buttons:
            # Ja es gibt Sub-Buttons!
            # Erzeuge alle Sub-Buttons
            [MyButton(button_frame_left, text=button_name,
                command=sub_button_callback).pack(fill='x')
                for button_name in my_sub_buttons[button_name]]
        
    def sub_button_callback(sub_button_name):
        """Rückruf der Sub-Buttons"""
        print("Sub-Button (links): {0}".format(sub_button_name))
        
    app_win = tk.Tk()
    
    button_frame_left = tk.Frame(app_win)
    button_frame_left.pack(side='left')

    button_frame_right = tk.Frame(app_win)
    button_frame_right.pack(side='left')
    
    # Namen der Sub-Buttons für Kunden (linke Seite)
    sub_buttons_kunden = ['Neuanlage', 'Formulare', 'Registrierung',
        'Konditionen', 'Bank', 'Info', 'Kunde', 'Angebot', 'History']
    # Namen der Sub-Buttons für Lieferanten (linke Seite) 
    sub_buttons_lieferanten = ['Item-1', 'Item-2', 'Item-3',
        'Item-4', 'Item-5', 'Item-6', 'Item-7', 'Item-8', 'Item-9']
    # Namen der Sub-Buttons für Aufträge (linke Seite)    
    sub_buttons_auftraege = list()
    # usw.
    # usw.
    # usw.
    
    # Zusammenfassung aller Sub-Buttons
    my_sub_buttons = {
        'Kunden': sub_buttons_kunden,
        'Lieferanten': sub_buttons_lieferanten,
        'Aufträge': sub_buttons_auftraege,
        }
    
    # Namen der Haupt-Buttons (rechte Seite)    
    my_buttons = ['Kunden', 'Lieferanten', 'Aufträge', 'Bestellungen',
        'Rechnungen', 'Verwaltung', 'Buchhaltung', 'EDV', 'Produkte']
    
    # Erzeuge Haupt-Buttons (rechte Seite    
    [MyButton(button_frame_right, text=button_name, command=button_callback
        ).pack(fill='x') for button_name in my_buttons]

    app_win.mainloop()
Gruß wuf :wink:
Take it easy Mates!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@wuf: Vorher auf die Existens eines Eintrags in einem Dictionary zu testen ist in Python eher ungewöhnlich. Das solltest du mit einem try-except lösen

Code: Alles auswählen

try:
    self.command_call = options['command']
    del options['command']
except KeyError:
    self.command_call = None
EAFP-Prinzip an Stelle von LBYL.

Und dann solltest du dir unbedingt abgewöhnen List Comprehensions als for-Schleifen zu verwenden. LCs sind dazu gedacht Daten zu generieren und nur dafür sollten sie auch eingesetzt werden.
Das Leben ist wie ein Tennisball.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi EyDu

Danke für deine Anregungen. Das EAFP-Prinzip an Stelle von LBYL ist neu für mich. Habe mich im Tutorial und Googel-Imperium schlau gemacht.
LBYL (Look before you leap = Schaue bevor du springst)
EAFP (Easier to ask for forgiveness than permission = Es ist einfacher um Vergebung zu bitten als um Erlaubnis)

@Nobuddy: Im folgenden habe ich die Anregungen von EyDu einfliessen lassen:

Code: Alles auswählen

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

import sys
import os

try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkFont as fnt
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.font as fnt

class MyButton(tk.Button):

    selected_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR, activebackground=HIGHLIGHT_COLOR)
    
    def __init__(self, parent, **options):
        
        try:
            self.command_call = options['command']
            del options['command']
        except KeyError:
            self.command_call = None
               
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
        
    def callback(self, event=None):
        button_obj = MyButton.selected_button_obj
        if button_obj is not None:
            button_obj.config(self.std_conf)
                
        if self.command_call:
            self.config(MyButton.HIGHLIGHT_CONF)
            MyButton.selected_button_obj = self
            self.command_call(event.widget['text']) 

#--- MODUL-TEST ---------------------------------------------------------------#
if __name__ == '__main__':
    
    def button_callback(button_name):
        """Rückruf der Haupt-Buttons"""
        
        print("Button (rechts): {0}".format(button_name))
        
        # Entferne alle bestehende Sub-Buttons aus dem linken Frame
        for button in button_frame_left.winfo_children():
            button.destroy()
             
        # Kontrolle: Hat der aktivierte rechte Button zugehörige Sub-Buttons?
        try:
            for button_name in my_sub_buttons[button_name]:
                MyButton(button_frame_left, text=button_name,
                    command=sub_button_callback).pack(fill='x')
            # Ja es gibt Sub-Buttons!
        except KeyError:
            print("Für {} gibt es keine Liste mit Sub-Buttons!".format(
                button_name))
                    
    def sub_button_callback(sub_button_name):
        """Rückruf der Sub-Buttons"""
        
        print("Sub-Button (links): {0}".format(sub_button_name))
        
    app_win = tk.Tk()
    
    button_frame_left = tk.Frame(app_win)
    button_frame_left.pack(side='left')

    button_frame_right = tk.Frame(app_win)
    button_frame_right.pack(side='left')
    
    # Namen der Sub-Buttons für Kunden (linke Seite)
    sub_buttons_kunden = ['Neuanlage', 'Formulare', 'Registrierung',
        'Konditionen', 'Bank', 'Info', 'Kunde', 'Angebot', 'History']
    # Namen der Sub-Buttons für Lieferanten (linke Seite) 
    sub_buttons_lieferanten = ['Item-1', 'Item-2', 'Item-3',
        'Item-4', 'Item-5', 'Item-6', 'Item-7', 'Item-8', 'Item-9']
    # Namen der Sub-Buttons für Aufträge (linke Seite)    
    sub_buttons_auftraege = list()
    # usw.
    # usw.
    # usw.
    
    # Zusammenfassung aller Sub-Buttons
    my_sub_buttons = {
        'Kunden': sub_buttons_kunden,
        'Lieferanten': sub_buttons_lieferanten,
        'Aufträge': sub_buttons_auftraege,
        }
    
    # Namen der Haupt-Buttons (rechte Seite)    
    my_buttons = ['Kunden', 'Lieferanten', 'Aufträge', 'Bestellungen',
        'Rechnungen', 'Verwaltung', 'Buchhaltung', 'EDV', 'Produkte']
    
    # Erzeuge Haupt-Buttons (rechte Seite)
    for button_name in my_buttons:
        MyButton(button_frame_right, text=button_name, command=button_callback
            ).pack(fill='x')

    app_win.mainloop()
Gruß wuf :wink:
Take it easy Mates!
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo wuf, hallo EyDu

Danke für Eure Unterstützung, jetzt habe ich meine Hausaufgaben fürś Wochenende. :wink:

Grüße Nobuddy

Nachtrag:
Eins habe ich gerade bemerkt.
Wenn ich ein Button auf der linken Seite (Sub-Buttons) anklicke, ändert sich das markierte rechte Button (Haupt-Button) und wird wieder neutral, also nicht mehr markiert.
Gibt es da eine Möglichkeit, die Markierung des rechten Buttons aktiv zu lassen, wenn ein Button auf der linken Seite ausgewählt wird, so lange nicht rechts ein anderes Button ausgewählt wird?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen

Habe mit wufś Code versucht, eine Trennung zwischen Haupt- und Sub-Buttons, bezüglich der Markierung zu erreichen.
Einen kleinen Teilerfolg habe ich, das ausgewählte Hauptbutton bleibt solange markiert, bis ein anderes Hauptbutton ausgewählt wird. Das Auswählen der Subbuttons, beeinflusst jetzt nicht mehr die Hauptbuttons.

Leider hat das Ganze noch einen Haken, den ich noch nicht gelöst bekommen habe.
Bei der ersten Auswahl der Hauptbuttons, funktioniert das Auswählen der Subbuttons ohne Probleme und Fehlermeldung.
Ab der zweiten Auswahl der Hauptbuttons, kommt dann beim Auswählen der Subbottons eine Fehlermeldung 'tkinter.TclError'.

Poste hier mal den Code.

Code: Alles auswählen

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

import sys
import os

try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkFont as fnt
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.font as fnt

class MyButton(tk.Button):

    selected_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR, activebackground=HIGHLIGHT_COLOR)
   
    def __init__(self, parent, **options):
       
        try:
            self.command_call = options['command']
            del options['command']
        except KeyError:
            self.command_call = None
               
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
       
    def callback(self, event=None):
        button_obj = MyButton.selected_button_obj
        if button_obj is not None:
            button_obj.config(self.std_conf)
               
        if self.command_call:
            self.config(MyButton.HIGHLIGHT_CONF)
            MyButton.selected_button_obj = self
            self.command_call(event.widget['text'])


class MySubButton(tk.Button):

    selected_sub_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR, activebackground=HIGHLIGHT_COLOR)
   
    def __init__(self, parent, **options):
       
        try:
            self.command_call = options['command']
            del options['command']
        except KeyError:
            self.command_call = None
               
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
       
    def callback(self, event=None):
        sub_button_obj = MySubButton.selected_sub_button_obj
        if sub_button_obj is not None:
            sub_button_obj.config(self.std_conf)
               
        if self.command_call:
            self.config(MySubButton.HIGHLIGHT_CONF)
            MySubButton.selected_sub_button_obj = self
            self.command_call(event.widget['text'])

#--- MODUL-TEST ---------------------------------------------------------------#
if __name__ == '__main__':
   
    def button_callback(button_name):
        """Rückruf der Haupt-Buttons"""
       
        print("Button (rechts): {0}".format(button_name))
       
        # Entferne alle bestehende Sub-Buttons aus dem linken Frame
        for button in button_frame_left.winfo_children():
            button.destroy()
             
        # Kontrolle: Hat der aktivierte rechte Button zugehörige Sub-Buttons?
        try:
            for button_name in my_sub_buttons[button_name]:
                MySubButton(button_frame_left, text=button_name,
                    command=sub_button_callback).pack(fill='x')
            # Ja es gibt Sub-Buttons!
        except KeyError:
            print("Für {} gibt es keine Liste mit Sub-Buttons!".format(
                button_name))
                   
    def sub_button_callback(sub_button_name):
        """Rückruf der Sub-Buttons"""
       
        print("Sub-Button (links): {0}".format(sub_button_name))
       
    app_win = tk.Tk()
   
    button_frame_left = tk.Frame(app_win)
    button_frame_left.pack(side='left')

    button_frame_right = tk.Frame(app_win)
    button_frame_right.pack(side='left')
   
    # Namen der Sub-Buttons für Kunden (linke Seite)
    sub_buttons_kunden = ['Neuanlage', 'Formulare', 'Registrierung',
        'Konditionen', 'Bank', 'Info', 'Kunde', 'Angebot', 'History']
    # Namen der Sub-Buttons für Lieferanten (linke Seite)
    sub_buttons_lieferanten = ['Item-1', 'Item-2', 'Item-3',
        'Item-4', 'Item-5', 'Item-6', 'Item-7', 'Item-8', 'Item-9']
    # Namen der Sub-Buttons für Aufträge (linke Seite)    
    sub_buttons_auftraege = list()
    # usw.
    # usw.
    # usw.
   
    # Zusammenfassung aller Sub-Buttons
    my_sub_buttons = {
        'Kunden': sub_buttons_kunden,
        'Lieferanten': sub_buttons_lieferanten,
        'Aufträge': sub_buttons_auftraege,
        }
   
    # Namen der Haupt-Buttons (rechte Seite)    
    my_buttons = ['Kunden', 'Lieferanten', 'Aufträge', 'Bestellungen',
        'Rechnungen', 'Verwaltung', 'Buchhaltung', 'EDV', 'Produkte']
   
    # Erzeuge Haupt-Buttons (rechte Seite)
    for button_name in my_buttons:
        MyButton(button_frame_right, text=button_name, command=button_callback
            ).pack(fill='x')

    app_win.mainloop()
Grüße Nobuddy
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Nobuddy

Es bedarf wiederum nur eine kleine Ergänzung. Nach dem entfernen aller Sub-Buttons aus dem linken Button-Frame musst du vor der Platzierung der neunen Sub-Buttons die Klassen-Variable 'selected_sub_button_obj' in der Klasse 'MySubButton' auf None setzen. Dies geschieht mit folgender Anweisung:

Code: Alles auswählen

MySubButton.selected_sub_button_obj = None
dann sieht das Skript wie folgt aus:

Code: Alles auswählen

        # Kontrolle: Hat der aktivierte rechte Button zugehörige Sub-Buttons?
        try:
            MySubButton.selected_sub_button_obj = None # wuf mod 21.11.2012
            for button_name in my_sub_buttons[button_name]:
                MySubButton(button_frame_left, text=button_name,
                    command=sub_button_callback).pack(fill='x')
            # Ja es gibt Sub-Buttons!
        except KeyError:
            print("Für {} gibt es keine Liste mit Sub-Buttons!".format(
                button_name))
Gruß wuf :wink:
Take it easy Mates!
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo wuf

Danke für Deinen Tipp, nach dieser kleinen Änderung, funktioniert es wie ich es mir vorgestellt habe! :wink:

Grüße Nobuddy
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zuammen,
benötige nochmal Eure Hilfe, für eine Löung.

Ich habe damals (ist ja schon eine Weile her ... :wink: ), wufś Code umgesetzt, welcher auch so prima funktioniert.

Die Sub-Buttons werden mit Klicken der Maustaste aktiviert und die Farbe des Backgrounds ändert sich auf grün.
Jetzt suche ich eine Lösung bei meinen Sub-Buttons, ohne mechanische Betätigung einer Hardware, Sub-Buttons zu aktivieren und die Farbe des Backgrounds zu verändern.

Hier mal die dazu gehörenden Codestücke:

Code: Alles auswählen

class MyButton(tk.Button):
    """Steuerung der Hauptbuttons"""

    selected_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR,
        activebackground=HIGHLIGHT_COLOR)
   
    def __init__(self, parent, **options):
       
        try:
            self.command_call = options['command']
            del options['command']
        except KeyError:
            self.command_call = None
           
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
       
    def callback(self, event=None):
        button_obj = MyButton.selected_button_obj
        if button_obj is not None:
            button_obj.config(self.std_conf)
               
        if self.command_call:
            self.config(MyButton.HIGHLIGHT_CONF)
            MyButton.selected_button_obj = self
            self.command_call(event.widget['text'])


class MySubButton(tk.Button):
    """Steuerung der Subbuttons"""

    selected_sub_button_obj = None
    HIGHLIGHT_COLOR = 'green'
    HIGHLIGHT_CONF = dict(bg=HIGHLIGHT_COLOR,
        activebackground=HIGHLIGHT_COLOR)
   
    def __init__(self, parent, **options):
       
        try:
            self.command_call = options['command']
            del options['command']
        except KeyError:
            self.command_call = None
               
        tk.Button.__init__(self, parent, **options)
        self.bind('<Button-1>', self.callback)
        self.std_conf = dict(bg=self['bg'],
            activebackground=self['activebackground'])
       
    def callback(self, event=None):
        sub_button_obj = MySubButton.selected_sub_button_obj
        self.mysubbutton = sub_button_obj
        if sub_button_obj is not None:
            sub_button_obj.config(self.std_conf)
               
        if self.command_call:
            self.config(MySubButton.HIGHLIGHT_CONF)
            MySubButton.selected_sub_button_obj = self
            self.command_call(event.widget['text'])
Sub-Buttons werden anhand der gewählten Haupt-Buttons erstellt:

Code: Alles auswählen

    def button_callback(self, button_name):
        """Rückruf der Haupt-Buttons"""
        print("Button (rechts): {0}".format(button_name))

        self.master_check = button_name
        self.sub_check = ''

        # Entferne alle bestehende Sub-Buttons aus dem linken Frame
        for button in self.button_frame_left.winfo_children():
            button.destroy()

        # Kontrolle: Hat der aktivierte rechte Button zugehörige Sub-Buttons?
        try:
            MySubButton.selected_sub_button_obj = None
            for button_name in self.my_sub_buttons[button_name]:
                MySubButton(self.button_frame_left,
                width=self.conf['button_width'],
                font=(self.conf['sub_font']), text=button_name,
                command=self.sub_button_callback).pack(padx=8, ipady=2, 
                pady=19, fill='x')
            # Ja es gibt Sub-Buttons!
        except KeyError:
            print("Für {} gibt es keine Liste mit Sub-Buttons!".format(
                button_name))
Ausgewähltes Sub-Button wird verarbeitet:

Code: Alles auswählen

    def sub_button_callback(self, sub_button_name):
        """Rückruf der Sub-Buttons"""
        print("Sub-Button (links): {0}".format(sub_button_name))
Mit

Code: Alles auswählen

self.sub_button_callback('Sub-Button-1')
kann ich das ausgewählte Sub-Button aktivieren, aber die Farbe des Backgrounds verändert sich nicht auf grün.

Wie kann man dies lösen?

Grüße Nobuddy
Antworten