Click Event eines Objektes
Hallo, beim Erstellen einer GUI zeichne ich auf ein CANVAS einen Kreis mit kreis1=c.create_oval('2c','2c','3c','3c', fill='', outline='#B6EEEB', activeoutline='blue', activefill ='red', width='2'), den ich jetzt als Button verwenden möchte. Bisher habe ich aber noch keine Idee, wie ich ein click-event dazufügen kann. Geht das überhaupt?
@yellowman: Das geht mit der `tag_bind()`-Methode auf dem `Canvas`-Exemplar.
Was soll die 1 bei `kreis1` bedeuten? Namen zu nummerieren ist ein „code smell“.
Was soll die 1 bei `kreis1` bedeuten? Namen zu nummerieren ist ein „code smell“.
Ich möchte einen Taschenrechner programmieren. Mit Button sieht das nicht so gut aus, daher zeichne ich 3x4 Kreise für die Buttons 0-9 und "+" und "-"BlackJack hat geschrieben:@yellowman: Das geht mit der `tag_bind()`-Methode auf dem `Canvas`-Exemplar.
Was soll die 1 bei `kreis1` bedeuten? Namen zu nummerieren ist ein „code smell“.
Wenn ich mit der Maus über einem Button(Kreis) bin, verändert sich dessen Farbe. Jetzt brauche ich nur noch ein click-event. Wenn ich das haben, kann ich auch kreis1 in eins umbenennen. Hast du da eine Idee?
@yellowman: Idee wofür? `tag_bind()` habe ich ja schon erwähnt. Erst schlechte Namen verwenden um die später noch mal richtig zu benennen ist eine komische Vorgehensweise. Was spricht dagegen gleich gute Namen zu wählen? Das macht weniger Arbeit.
Falls man Schwierigkeiten hat einen guten, passenden Namen für einen Wert zu wählen, dann deutet das oft darauf hin, dass man das zu lösende Problem noch nicht komplett verstanden hat, oder die Lösung nicht genug durchdacht hat, oder Daten zu einer Struktur zusammengefasst hat, die so nicht sinnvoll zusammen gehört. Das sind alles Sachen die man eher sofort als später angehen möchte, weil sie einen aufhalten oder gar eine sinnvolle Lösung komplett blockieren und man sich irgendwie verzettelt.
Wobei die Frage ist, ob man für diese ”Buttons” tatsächlich Namen braucht, beziehungsweise ob die tatsächlich unterschiedlich sein müssen. Denn Du kapselst das ja hoffentlich in einer Klasse damit Du nicht zwölf mal gleichen/ähnlichen Code für jede runde Schaltfläche schreiben musst. Falls Du tatsächlich das Verhalten von `Button` nachprogrammieren möchtest, dann ist das vielleicht auch aufwändiger als Du denkst. Denn normalerweise löst eine Schaltfläche nicht aus wenn man die Maustaste drückt, sondern wenn man sie los lässt. Und das auch nur falls man sich beim loslassen noch mit der Maus auf der Schaltfläche befindet.
Falls man Schwierigkeiten hat einen guten, passenden Namen für einen Wert zu wählen, dann deutet das oft darauf hin, dass man das zu lösende Problem noch nicht komplett verstanden hat, oder die Lösung nicht genug durchdacht hat, oder Daten zu einer Struktur zusammengefasst hat, die so nicht sinnvoll zusammen gehört. Das sind alles Sachen die man eher sofort als später angehen möchte, weil sie einen aufhalten oder gar eine sinnvolle Lösung komplett blockieren und man sich irgendwie verzettelt.
Wobei die Frage ist, ob man für diese ”Buttons” tatsächlich Namen braucht, beziehungsweise ob die tatsächlich unterschiedlich sein müssen. Denn Du kapselst das ja hoffentlich in einer Klasse damit Du nicht zwölf mal gleichen/ähnlichen Code für jede runde Schaltfläche schreiben musst. Falls Du tatsächlich das Verhalten von `Button` nachprogrammieren möchtest, dann ist das vielleicht auch aufwändiger als Du denkst. Denn normalerweise löst eine Schaltfläche nicht aus wenn man die Maustaste drückt, sondern wenn man sie los lässt. Und das auch nur falls man sich beim loslassen noch mit der Maus auf der Schaltfläche befindet.
Klassen habe ich zum Erstellen der Buttons noch nicht verwendet, aber eine doppelte Schleife. Das Klassenkapitel wird doch durchgearbeitet. Dazu werde ich bestimmt noch Fragen haben. Bis dannBlackJack hat geschrieben:@yellowman: Idee wofür? `tag_bind()` habe ich ja schon erwähnt. Erst schlechte Namen verwenden um die später noch mal richtig zu benennen ist eine komische Vorgehensweise. Was spricht dagegen gleich gute Namen zu wählen? Das macht weniger Arbeit.
Falls man Schwierigkeiten hat einen guten, passenden Namen für einen Wert zu wählen, dann deutet das oft darauf hin, dass man das zu lösende Problem noch nicht komplett verstanden hat, oder die Lösung nicht genug durchdacht hat, oder Daten zu einer Struktur zusammengefasst hat, die so nicht sinnvoll zusammen gehört. Das sind alles Sachen die man eher sofort als später angehen möchte, weil sie einen aufhalten oder gar eine sinnvolle Lösung komplett blockieren und man sich irgendwie verzettelt.
Du hast Recht, ich habe tatsächlich ohne große Überlegung losprogrammiert und die Sache nicht bis zum Ende durchdacht. Es sind halt meine ersten Gehversuche mit Python, welches ich nach dem Tod von Flash, dann Silverlight und dem sich nicht durchsetzenden WPF, jetzt beruflich Python erlernen soll. Das ist eine rieeesige Umstellung, besonders im Zusammenhang mit den mir jetzt fehlenden guten IDE's von Adobe (Flex/Flash) und, (bitte mich jetzt nicht lynchen), VS.
Wobei die Frage ist, ob man für diese ”Buttons” tatsächlich Namen braucht, beziehungsweise ob die tatsächlich unterschiedlich sein müssen. Denn Du kapselst das ja hoffentlich in einer Klasse damit Du nicht zwölf mal gleichen/ähnlichen Code für jede runde Schaltfläche schreiben musst. Falls Du tatsächlich das Verhalten von `Button` nachprogrammieren möchtest, dann ist das vielleicht auch aufwändiger als Du denkst. Denn normalerweise löst eine Schaltfläche nicht aus wenn man die Maustaste drückt, sondern wenn man sie los lässt. Und das auch nur falls man sich beim loslassen noch mit der Maus auf der Schaltfläche befindet.
Hi yellowman
Hier noch ein bisschen Code zum experimentieren:
Wenn du nicht alles verstehst musst du vielleicht noch einmal in die Bücher gucken! Noch viel Spass!
Gruss wuf
Hier noch ein bisschen Code zum experimentieren:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from functools import partial
try:
# Tkinter for Python 2.xx
import Tkinter as tk
except:
# Tkinter for Python 3.xx
import tkinter as tk
APP_TITLE = "Canvas Button"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 230
APP_HEIGHT = 360
BUTTON_NAMES = [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '+', '-'],
['x', '/', '.']
]
class CanvasButton(object):
DISPLACEMENT = 1
FONT_NAME = ('Helvetica', 20, 'normal')
COLOR_TEXT = 'brown'
def __init__(self, panel, xpos, ypos, diameter, name, callback=None, **opt):
self.panel = panel
self.xpos = xpos
self.ypos = ypos
self.diameter = diameter
self.name = name
self.callback = callback
self.tag = 'Button-{}'.format(name)
radius = diameter / 2
coords = (xpos-radius, ypos-radius, xpos+radius, ypos+radius)
self.panel.create_oval(coords, tags=self.tag, **opt)
self.panel.create_text(xpos, ypos, text=name, font=self.FONT_NAME,
fill=self.COLOR_TEXT, state='disabled', tag=self.tag)
self.panel.tag_bind(self.tag, '<Button-1>', partial(
self.press_button))
self.panel.tag_bind(self.tag, '<ButtonRelease-1>', partial(
self.release_button))
self.panel.tag_bind(self.tag, '<Enter>', partial(self.cursor_on))
self.panel.tag_bind(self.tag, '<Leave>', partial(self.cursor_off))
def press_button(self, event):
self.panel.move(self.tag, self.DISPLACEMENT, self.DISPLACEMENT)
self.button_callback()
def release_button(self, event):
self.panel.move(self.tag, -self.DISPLACEMENT, -self.DISPLACEMENT)
def cursor_on(self, event):
self.panel.config(cursor='hand1')
def cursor_off(self, event):
self.panel.config(cursor='arrow')
def button_callback(self):
self.callback(self.name)
class Application(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, master)
# Button panel
self.canvas = tk.Canvas(self)
self.canvas.pack(fill='both', expand=True)
# Button-Options
opt = dict(fill='khaki3', outline='blue', activeoutline='red',
activefill ='khaki1', width=1)
# Create the buttons and place them as array
xorg, yorg = 50, 50
xpos = xorg
ypos = yorg
diameter = 60
xgap = 65
ygap = 65
for row in BUTTON_NAMES:
for name in row:
CanvasButton(self.canvas, xpos, ypos, diameter, name,
self.button_callback, **opt)
xpos += xgap
xpos = xorg
ypos += ygap
def button_callback(self, name):
print(name)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = Application(app_win).pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Gruss wuf
Take it easy Mates!
Vielen Dank, das sieht schon sehr vielversprechend aus. Natürlich lese ich mich da noch rein. Der Code gibt mir wichtige Infos und Anregungen, (noch) nicht verstandenes nachzulesen. Aber nicht heute. Meine Daumen hier in München brauche ich für Bayernwuf hat geschrieben:Hi yellowman
Hier noch ein bisschen Code zum experimentieren:Wenn du nicht alles verstehst musst du vielleicht noch einmal in die Bücher gucken! Noch viel Spass!Code: Alles auswählen
#!/usr/bin/env python # -*- coding: utf-8 -*- from functools import partial try: # Tkinter for Python 2.xx import Tkinter as tk except: # Tkinter for Python 3.xx import tkinter as tk APP_TITLE = "Canvas Button" APP_XPOS = 100 APP_YPOS = 100 APP_WIDTH = 230 APP_HEIGHT = 360 BUTTON_NAMES = [ ['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['0', '+', '-'], ['x', '/', '.'] ] class CanvasButton(object): DISPLACEMENT = 1 FONT_NAME = ('Helvetica', 20, 'normal') COLOR_TEXT = 'brown' def __init__(self, panel, xpos, ypos, diameter, name, callback=None, **opt): self.panel = panel self.xpos = xpos self.ypos = ypos self.diameter = diameter self.name = name self.callback = callback self.tag = 'Button-{}'.format(name) radius = diameter / 2 coords = (xpos-radius, ypos-radius, xpos+radius, ypos+radius) self.panel.create_oval(coords, tags=self.tag, **opt) self.panel.create_text(xpos, ypos, text=name, font=self.FONT_NAME, fill=self.COLOR_TEXT, state='disabled', tag=self.tag) self.panel.tag_bind(self.tag, '<Button-1>', partial( self.press_button)) self.panel.tag_bind(self.tag, '<ButtonRelease-1>', partial( self.release_button)) self.panel.tag_bind(self.tag, '<Enter>', partial(self.cursor_on)) self.panel.tag_bind(self.tag, '<Leave>', partial(self.cursor_off)) def press_button(self, event): self.panel.move(self.tag, self.DISPLACEMENT, self.DISPLACEMENT) self.button_callback() def release_button(self, event): self.panel.move(self.tag, -self.DISPLACEMENT, -self.DISPLACEMENT) def cursor_on(self, event): self.panel.config(cursor='hand1') def cursor_off(self, event): self.panel.config(cursor='arrow') def button_callback(self): self.callback(self.name) class Application(tk.Frame): def __init__(self, master): self.master = master tk.Frame.__init__(self, master) # Button panel self.canvas = tk.Canvas(self) self.canvas.pack(fill='both', expand=True) # Button-Options opt = dict(fill='khaki3', outline='blue', activeoutline='red', activefill ='khaki1', width=1) # Create the buttons and place them as array xorg, yorg = 50, 50 xpos = xorg ypos = yorg diameter = 60 xgap = 65 ygap = 65 for row in BUTTON_NAMES: for name in row: CanvasButton(self.canvas, xpos, ypos, diameter, name, self.button_callback, **opt) xpos += xgap xpos = xorg ypos += ygap def button_callback(self, name): print(name) def main(): app_win = tk.Tk() app_win.title(APP_TITLE) app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS)) app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT)) app = Application(app_win).pack(fill='both', expand=True) app_win.mainloop() if __name__ == '__main__': main()
Gruss wuf
@wuf: ein paar Anmerkungen zu Deinem Code:
Zeile 4, 248ff: partial wird nicht wirklich gebraucht. Ein partial-Aufruf, bei dem kein Argument mitgegeben wird, kann man genausogut weglassen.
Zeile 9: ein nacktes except sollte man nie benutzen, hier brauchst Du nur ImportError abfangen.
Zeile 33: eine Instanz mit callback=None produziert einen Fehler beim Mausclick, der Defaultwert ist also nicht sinnvoll. Weg damit.
Zeile 35ff: die Attribute xpos, ypos und diameter werden nicht gebraucht.
Zeiel 57: wie BlackJack schon geschrieben hat, ist das erwartete Verhalten, dass erst beim Loslassen der Maus über dem Kreis der Callback ausgelöst wird.
Zeile 82: Wenn Du die Variable gleich button_options nennst, sparst Du Dir einen Kommentar.
Zeile 87, 91f: wann Du Konstanten am Anfang des Programms definierst und wann mittendrin, ist mir unklar.
Zeile 88, 99: Variablen sollten dann Initalisiert werden, wenn sie gebraucht werden, bei xpos also einmal vor der inneren for-Schleife.
Zeile 4, 248ff: partial wird nicht wirklich gebraucht. Ein partial-Aufruf, bei dem kein Argument mitgegeben wird, kann man genausogut weglassen.
Zeile 9: ein nacktes except sollte man nie benutzen, hier brauchst Du nur ImportError abfangen.
Zeile 33: eine Instanz mit callback=None produziert einen Fehler beim Mausclick, der Defaultwert ist also nicht sinnvoll. Weg damit.
Zeile 35ff: die Attribute xpos, ypos und diameter werden nicht gebraucht.
Zeiel 57: wie BlackJack schon geschrieben hat, ist das erwartete Verhalten, dass erst beim Loslassen der Maus über dem Kreis der Callback ausgelöst wird.
Zeile 82: Wenn Du die Variable gleich button_options nennst, sparst Du Dir einen Kommentar.
Zeile 87, 91f: wann Du Konstanten am Anfang des Programms definierst und wann mittendrin, ist mir unklar.
Zeile 88, 99: Variablen sollten dann Initalisiert werden, wenn sie gebraucht werden, bei xpos also einmal vor der inneren for-Schleife.
@ Sirius3: Besten Dank für deine wertvollen Anmerkungen. Habe diese in mein Skript einfliessen lassen.
Hier mein aktualisiertes Skript:
Gruss wuf
Hier mein aktualisiertes Skript:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from functools import partial
try:
# Tkinter for Python 2.xx
import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
import tkinter as tk
APP_TITLE = "Canvas Button"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 230
APP_HEIGHT = 360
BUTTON_NAMES = [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '+', '-'],
['x', '/', '.']
]
DISPLACEMENT = 1
FONT_NAME = ('Helvetica', 20, 'normal')
COLOR_TEXT = 'brown'
class CanvasButton(object):
def __init__(self, panel, xpos, ypos, diameter, name, callback=None, **opt):
self.panel = panel
self.name = name
self.callback = callback
self.tag = 'Button-{}'.format(name)
radius = diameter / 2
coords = (xpos-radius, ypos-radius, xpos+radius, ypos+radius)
self.panel.create_oval(coords, tags=self.tag, **opt)
self.panel.create_text(xpos, ypos, text=name, font=FONT_NAME,
fill=COLOR_TEXT, state='disabled', tag=self.tag)
self.panel.tag_bind(self.tag, '<Button-1>', self.press_button)
self.panel.tag_bind(self.tag, '<ButtonRelease-1>', self.release_button)
self.panel.tag_bind(self.tag, '<Enter>', self.cursor_on)
self.panel.tag_bind(self.tag, '<Leave>', self.cursor_off)
def press_button(self, event):
self.panel.move(self.tag, DISPLACEMENT, DISPLACEMENT)
def release_button(self, event):
self.panel.move(self.tag, -DISPLACEMENT, -DISPLACEMENT)
self.button_callback()
def cursor_on(self, event):
self.panel.config(cursor='hand1')
def cursor_off(self, event):
self.panel.config(cursor='arrow')
def button_callback(self):
if self.callback != None:
self.callback(self.name)
class Application(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, master)
# Button panel
self.canvas = tk.Canvas(self)
self.canvas.pack(fill='both', expand=True)
button_options = dict(fill='khaki3', outline='blue', activeoutline='red',
activefill ='khaki1', width=1)
# Create the buttons and place them as array
xorg, yorg = 50, 50
xpos = xorg
ypos = yorg
diameter = 60
xgap = 65
ygap = 65
for row in BUTTON_NAMES:
xpos = xorg
for name in row:
CanvasButton(self.canvas, xpos, ypos, diameter, name,
self.button_callback, **button_options)
xpos += xgap
ypos += ygap
def button_callback(self, name):
print(name)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = Application(app_win).pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Take it easy Mates!
Hallo, Python zu lernen ist ganz bestimmt kein Fehler. Wie ich in obigen Postings gesehen habe -vielen Dank dafür- muss ich noch einiges lernen. Angenommen, ich bin etwas sicherer in der Programmierung, dann stellt sich für mich die Frage, was wird in der Praxis häufiger verlangt Kleiner GUI’s mit tkinter oder eher mit PyQt/PySide? Im Zusammenhang mit C++ wurde vor Jahren in unsere Firma über den Einsatz von Qt diskutiert, aber aufgrund der Linzenspolitik von Qt wurde dieses Framework nicht genommen. Hier ist zwar nicht das Qt-Forum, daher ganz kurz: Daumen hoch oder eher nicht?
@yellowman: Ich denke so ganz allgemein kann man da nichts zu sagen, da fehlen die (öffentlich zugänglichen) Daten zu. Tk hat den Vorteil zur Python-Standardbibliothek zu gehören. Es ist allerdings was die Auswahl der Widgets angeht, eher beschränkt. Man sollte sich IMHO vorher überlegen ob Tk für die konkrete Anwendung ausreicht und dann entscheiden.
wuf hat geschrieben:@ Sirius3: Besten Dank für deine wertvollen Anmerkungen. Habe diese in mein Skript einfliessen lassen.
Hier mein aktualisiertes Skript:Gruss wufCode: Alles auswählen
#!/usr/bin/env python # -*- coding: utf-8 -*- from functools import partial try: # Tkinter for Python 2.xx import Tkinter as tk except ImportError: # Tkinter for Python 3.xx import tkinter as tk APP_TITLE = "Canvas Button" APP_XPOS = 100 APP_YPOS = 100 APP_WIDTH = 230 APP_HEIGHT = 360 BUTTON_NAMES = [ ['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['0', '+', '-'], ['x', '/', '.'] ] DISPLACEMENT = 1 FONT_NAME = ('Helvetica', 20, 'normal') COLOR_TEXT = 'brown' class CanvasButton(object): def __init__(self, panel, xpos, ypos, diameter, name, callback=None, **opt): self.panel = panel self.name = name self.callback = callback self.tag = 'Button-{}'.format(name) radius = diameter / 2 coords = (xpos-radius, ypos-radius, xpos+radius, ypos+radius) self.panel.create_oval(coords, tags=self.tag, **opt) self.panel.create_text(xpos, ypos, text=name, font=FONT_NAME, fill=COLOR_TEXT, state='disabled', tag=self.tag) self.panel.tag_bind(self.tag, '<Button-1>', self.press_button) self.panel.tag_bind(self.tag, '<ButtonRelease-1>', self.release_button) self.panel.tag_bind(self.tag, '<Enter>', self.cursor_on) self.panel.tag_bind(self.tag, '<Leave>', self.cursor_off) def press_button(self, event): self.panel.move(self.tag, DISPLACEMENT, DISPLACEMENT) def release_button(self, event): self.panel.move(self.tag, -DISPLACEMENT, -DISPLACEMENT) self.button_callback() def cursor_on(self, event): self.panel.config(cursor='hand1') def cursor_off(self, event): self.panel.config(cursor='arrow') def button_callback(self): if self.callback != None: self.callback(self.name) class Application(tk.Frame): def __init__(self, master): self.master = master tk.Frame.__init__(self, master) # Button panel self.canvas = tk.Canvas(self) self.canvas.pack(fill='both', expand=True) button_options = dict(fill='khaki3', outline='blue', activeoutline='red', activefill ='khaki1', width=1) # Create the buttons and place them as array xorg, yorg = 50, 50 xpos = xorg ypos = yorg diameter = 60 xgap = 65 ygap = 65 for row in BUTTON_NAMES: xpos = xorg for name in row: CanvasButton(self.canvas, xpos, ypos, diameter, name, self.button_callback, **button_options) xpos += xgap ypos += ygap def button_callback(self, name): print(name) def main(): app_win = tk.Tk() app_win.title(APP_TITLE) app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS)) app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT)) app = Application(app_win).pack(fill='both', expand=True) app_win.mainloop() if __name__ == '__main__': main()
Hallo, der Rechner sieht wirklich schön aus. Auch das mit dem Mauszeiger ist sehr lehrreich. Jetzt muss ich nur den Code noch verstehen lernen. Vielen Dank auch an die anderen.yellowman hat geschrieben:wuf hat geschrieben:@ Sirius3: Besten Dank für deine wertvollen Anmerkungen. Habe diese in mein Skript einfliessen lassen.
Hier mein aktualisiertes Skript:Gruss wufCode: Alles auswählen
#!/usr/bin/env python # -*- coding: utf-8 -*- from functools import partial try: # Tkinter for Python 2.xx import Tkinter as tk except ImportError: # Tkinter for Python 3.xx import tkinter as tk APP_TITLE = "Canvas Button" APP_XPOS = 100 APP_YPOS = 100 APP_WIDTH = 230 APP_HEIGHT = 360 BUTTON_NAMES = [ ['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['0', '+', '-'], ['x', '/', '.'] ] DISPLACEMENT = 1 FONT_NAME = ('Helvetica', 20, 'normal') COLOR_TEXT = 'brown' class CanvasButton(object): def __init__(self, panel, xpos, ypos, diameter, name, callback=None, **opt): self.panel = panel self.name = name self.callback = callback self.tag = 'Button-{}'.format(name) radius = diameter / 2 coords = (xpos-radius, ypos-radius, xpos+radius, ypos+radius) self.panel.create_oval(coords, tags=self.tag, **opt) self.panel.create_text(xpos, ypos, text=name, font=FONT_NAME, fill=COLOR_TEXT, state='disabled', tag=self.tag) self.panel.tag_bind(self.tag, '<Button-1>', self.press_button) self.panel.tag_bind(self.tag, '<ButtonRelease-1>', self.release_button) self.panel.tag_bind(self.tag, '<Enter>', self.cursor_on) self.panel.tag_bind(self.tag, '<Leave>', self.cursor_off) def press_button(self, event): self.panel.move(self.tag, DISPLACEMENT, DISPLACEMENT) def release_button(self, event): self.panel.move(self.tag, -DISPLACEMENT, -DISPLACEMENT) self.button_callback() def cursor_on(self, event): self.panel.config(cursor='hand1') def cursor_off(self, event): self.panel.config(cursor='arrow') def button_callback(self): if self.callback != None: self.callback(self.name) class Application(tk.Frame): def __init__(self, master): self.master = master tk.Frame.__init__(self, master) # Button panel self.canvas = tk.Canvas(self) self.canvas.pack(fill='both', expand=True) button_options = dict(fill='khaki3', outline='blue', activeoutline='red', activefill ='khaki1', width=1) # Create the buttons and place them as array xorg, yorg = 50, 50 xpos = xorg ypos = yorg diameter = 60 xgap = 65 ygap = 65 for row in BUTTON_NAMES: xpos = xorg for name in row: CanvasButton(self.canvas, xpos, ypos, diameter, name, self.button_callback, **button_options) xpos += xgap ypos += ygap def button_callback(self, name): print(name) def main(): app_win = tk.Tk() app_win.title(APP_TITLE) app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS)) app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT)) app = Application(app_win).pack(fill='both', expand=True) app_win.mainloop() if __name__ == '__main__': main()
Hi yellowman
Um das Ganze noch ein wenig aufzupeppen kannst du natürlich die 'oval'-Canvas-Objekte für die grafische Darstellung der Schaltfächen durch eigene 'image'-Canvas-Objekte ersetzen. Im folgenden modifizierten Skript habe ich 60x60 pixel 'gif'-Bilddaten im Base64-Format für die grafische Schaltflächen verwende. (Sorry betreffs meiner verrückten Farbenwahl)
Hier mein angepasstes Skript:
Gruss wuf
Um das Ganze noch ein wenig aufzupeppen kannst du natürlich die 'oval'-Canvas-Objekte für die grafische Darstellung der Schaltfächen durch eigene 'image'-Canvas-Objekte ersetzen. Im folgenden modifizierten Skript habe ich 60x60 pixel 'gif'-Bilddaten im Base64-Format für die grafische Schaltflächen verwende. (Sorry betreffs meiner verrückten Farbenwahl)
Hier mein angepasstes Skript:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from functools import partial
try:
# Tkinter for Python 2.xx
import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
import tkinter as tk
APP_TITLE = "Canvas Button"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 230
APP_HEIGHT = 360
BUTTON_NAMES = [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '+', '-'],
['x', '/', '.']
]
DISPLACEMENT = 1
FONT_NAME = ('Helvetica', 20, 'normal')
COLOR_TEXT = 'brown'
BUTTON_IMAGE = 'ButtonImage_01.gif'
ACTIVE_BUTTON_IMAGE = 'ActiveButtonImage_01.gif'
# Base64 Bildkonstanten
button_image_b64 =\
'''
R0lGODlhPAA8AKUgAEaRPUiVPkmWP0qZQEycQUydQk2fQk6gQ0+hRE+jRFCk
RVGnRlKoR1OrSFStSFWvSlaxSleyS1izTFm0TVy1UGC3VGG3VmS5WGW5Wma6
W2m7Xmq8X2u8YW29Ym69ZG++Zf//////////////////////////////////
////////////////////////////////////////////////////////////
/////////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1Q
ACH5BAEKACAALAAAAAA8ADwAAAb+QJBwSCwaix6OkrNpHp/QqFToqSY3mmw2
w+1mpuCwtcPZei9oSxqdDruRVmwGQ79Y7pW8Xn/vv8VVZVwYdngUh4iJiol/
UYEag30VixQTlJeNRx8ecoQWeYmWExMSEqOjl4yZVFWQGYahoxIRtLWnp6kT
mVVyhYqns7XCtKa3uKgUEX+8kHaTocHD0rQQxcaHlg9uvFyw2BPT4cPGxhEO
YhvdFrHR4u7W5dpTSeqxEO74wvCjEQ/yUK0y2EF0Kp9BYQVrPWgAZYOHZuu+
gTtIkZiwhQyecJrzieDEiiAVLjyyoQyGjt9CqlToQIERQXc8rlzpz0FGIhrS
DSR4b2b+SH8LExARdOFZpXY+KQJt4HIIpJMyk6qs2RTElpjYpNJ80BKBkCwn
n5HSOpUrA6FWBUasRLaszaaQ1vJrCxIoA7hQsSGlm68mUxBcdrLlW/ftgW5i
9xLG5++ugQuvxC4uzLTAhbyDJx9srICAmohjNW9+cNezXMWipflrsCDBAKxH
U/dduODAa6NzZYszW3sAiFi63ZlVcEAIu+DTat4t/tvjR+Qi7yIwYFwidNUN
pBMQYknic+RcsxMXMERUwuv9SLemXr4c+tXLtw+pdgu1ZuVnDZAn8sC+7Mbx
GeFPBN/pBp8CCRywXxEOoJfeW8TJZ4QDDjxwnVnLGRAAFAzUAGXhfzbdlaBv
UXQ4YGoYIniAhCVW6CFh+LW2YhgKMODii2TFmCABG4aRAAMNcOXhhzP5xYCI
Ky4YxgELHEnhkFs5kB2SBCjpxgE12vgkUHVxFaICxK3Y4yoJZNlAkDeeGI6H
Zx4powEkrjLEAWUeCWQDaVr4oZ5GMrAAmAckKacRBNCZpZ14blkThXbepeIB
cI45aBGFlvlno2dmaieYYCa44gCSTnoEAQYEyimnTZ6aAAKBGsBjqKJGMQCp
gdZqq6sEDCAAALEOKkAAwAYAwLC9BgEAOw==
'''
active_button_image_b64 =\
'''
R0lGODlhPAA8AIQdAPXVNvXWPPXXPvXYQvXYRvXZSPbZSfbaS/baT/bbUfbb
U/bcVfbdW/fdXvfeYPfeYvffZPffZvffaPfgavfhcPjidfjjd/jje/jkffjk
f/jlgfjlg/jlhf///////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEK
AB8ALAAAAAA8ADwAAAX+4CeOZGmWW6au2em+cCxudJph+HVZfG/JwGBNc9v5
KkhKEpkMOlG1jJFXoViv2Kz1KaRJe9XrZEwum8tcmHeKPU8i7nj6xEkZw5Ry
RBKJQCB9fRIScWNzIzUYPGJ6fRAPkJGBgXF8c2sWYWaBj5GekICTlH1jD1yY
mmR8nZ+tkA6hooN7DU5ei1aqfa68n6KiDwxCGbiNrL3IscC1MinFZH0OyNOe
yrsNzC80O1XQu9Tgkt+QDcIuGRvceWOB4e6Rx+ULLs4WuewR7/qf2OYlKjvu
vcm3ryA5BglM3LC3bqBBg/3mkcBArNsYPtIe7sNWDgGJLxZXaSzIEeHERd7+
RkIsl1DEBUUCCarcyPKACAwB1/mZSVKexw/qoPHsyWBBy4Aph+rjaNSlvYs7
lb7rZ5JKQ5lS3clLcOBZ1KxaGxg1UIEhO7BLGSAsUPYq2qliExBQovPY22nY
jM69avcur34KEAyI2ddvK8AHBl/FatiVPAWJPzRqjGyrTclQv1L2FJGriEaM
Nz/Iy9XAZ3yhRVsmIAIOoUmiI5UrylXACDiwY5MTG9j0bWC6Ox9gPQLWpMJ3
Iy5AYMA2iQbIG+c1OtwEtgep/XZGcMB5CQa6R2/lStyE2gax5VFv/mIBR/SG
1SfgPiCG++vaixrlXh7GAgbvwaeUcoFVB0QC/wWlKKBKBPLnnQwIJAjgeyNR
tcB+wz0IxAEKXHgehUTpN1+GcxyA4H8f4heWWhcmwBWJh3yAwInnTchRZSXp
V6AB9cU4wgEzXoiijdfBh16OFyrg4gEw+jgCAUCeKKRaKc6mX4sjHsBjAE6e
AOWMSgo5JItYusjdcANo2GUJBBjApItwJtBhnGdqSYAAaq7pwgBtMunnnwYQ
QECaAOgZI56IAqConiEAADs=
'''
class CanvasButton(object):
def __init__(self, panel, xpos, ypos, name, callback=None):
self.panel = panel
self.name = name
self.callback = callback
# Als Dateidaten einlesen
#self.button_image = tk.PhotoImage(file=BUTTON_IMAGE)
#self.active_button_image = tk.PhotoImage(file=ACTIVE_BUTTON_IMAGE)
# Als Base64-Daten aus Konstante einlesen
self.button_image = tk.PhotoImage(data=button_image_b64)
self.active_button_image = tk.PhotoImage(data=active_button_image_b64)
self.tag = 'Button-{}'.format(name)
self.panel.create_image(xpos, ypos, image=self.button_image,
activeimage=self.active_button_image, tags=self.tag)
self.panel.create_text(xpos, ypos, text=name, font=FONT_NAME,
fill=COLOR_TEXT, state='disabled', tag=self.tag)
self.panel.tag_bind(self.tag, '<Button-1>', self.press_button)
self.panel.tag_bind(self.tag, '<ButtonRelease-1>', self.release_button)
self.panel.tag_bind(self.tag, '<Enter>', self.cursor_on)
self.panel.tag_bind(self.tag, '<Leave>', self.cursor_off)
def press_button(self, event):
self.panel.move(self.tag, DISPLACEMENT, DISPLACEMENT)
def release_button(self, event):
self.panel.move(self.tag, -DISPLACEMENT, -DISPLACEMENT)
self.button_callback()
def cursor_on(self, event):
self.panel.config(cursor='hand1')
def cursor_off(self, event):
self.panel.config(cursor='arrow')
def button_callback(self):
if self.callback != None:
self.callback(self.name)
class Application(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, master)
# Button panel
self.canvas = tk.Canvas(self, bd=4, relief='raised',
highlightthickness=0)
self.canvas.pack(fill='both', expand=True)
# Create the buttons and place them as array
xorg, yorg = 50, 50
xpos = xorg
ypos = yorg
xgap = 65
ygap = 65
for row in BUTTON_NAMES:
xpos = xorg
for name in row:
CanvasButton(self.canvas, xpos, ypos, name,
self.button_callback)
xpos += xgap
ypos += ygap
def button_callback(self, name):
print(name)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = Application(app_win).pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Take it easy Mates!