Was für einen Sinn haben eigentlich in tkinter Klassenattribute für widgets

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

Ich meine auf chinesisch geht das ja:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import tkinter as tk

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.美妙的按钮 = tk.Button(self,text='美妙的按钮')
        self.美妙的按钮.place(y='45', x='54')

if __name__ == '__main__':
    Application().mainloop()
Aber auf englisch geht es nicht.

Da ist die Frage, ob man das mit den Attributnamen nicht lieber gleich besser weglassen sollte
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: Der Sinn von Klassenattributen ist überall gleich. Was Dein Code und was das mit chinesisch zu tun hat, willst Du aber vielleicht noch verraten.
BlackJack

Also ich kann auch englisch in Attributnamen verwenden:

Code: Alles auswählen

# -*- coding: utf-8 -*-
 
import tkinter as tk
 
class Application(tk.Tk):
 
    def __init__(self, **kwargs):
        tk.Tk.__init__(self, **kwargs)
        # widget definitions ===================================
        self.wonderful_button = tk.Button(self, text='Wonderful button')
        self.wonderful_button.place(y=45, x=54)
 
if __name__ == '__main__':
    Application().mainloop()
In diesem konkreten Fall könnte man das Attribut aber tatsächlich weglassen weil auf das Objekt nicht mehr zugegriffen wird. Das ist ja aber nicht immer der Fall.

Klassenattribute sehe ich in dem Beispiel nicht, und ansonsten ist die Frage welchen Sinn Attribute haben nicht an `tkinter` und Anzeigeelemente gebunden.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack: bei mir geht das aber nicht:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.wonderful button = tk.Button(self,text='wonderful button')
        self.wonderful button.place(y='45', x='54')

if __name__ == '__main__':
    Application().mainloop()
Und dieses Beispiel funktioniert auch nicht:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.input a = tk.Entry(self)
        self.input b = tk.Entry(self)
        self.a * b = tk.Button(self,text='a * b')
        self.Ergebnis von a * b = tk.Label(self)
        self.input a.pack()
        self.input b.pack()
        self.a * b.pack(fill='x')
        self.Ergebnis von a * b.pack(fill='x')

if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack: sieht es nicht besser aus, wenn man das mit den Attributren wegläßt?

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

def that(self,name):
    return self.nametowidget(name)

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================

        tk.Entry(self,name = 'input a')
        tk.Entry(self,name = 'input b')
        tk.Button(self,text='a * b',name = 'a * b')
        tk.Label(self, name = 'ergebnis von a * b')

        that(self,'input a').pack()
        that(self,'input b').pack()
        that(self,'a * b').pack(fill='x')
        that(self,'ergebnis von a * b').pack(fill='x')

if __name__ == '__main__':
    Application().mainloop()
Außerdem, wenn man einen Fehler hat und läßt sich mit print ein widget ausgeben, bekommt man dann keine niichtssagende .4555456345 Adresse sondern den Namen des Widgets.
BlackJack

@Alfons Mittelmeyer: Äh, natürlich geht das nicht, das entspricht nicht der Python-Syntax. Das geht aber auch mit Chinesisch nicht, denn auch mit chinesischen Zeichen wird man etwas schreiben können was nicht der Python-Syntax entspricht.

Nein, das sieht nicht besser aus, weil es ungewohnt ist, und damit überraschend. Zumal die Namen Pfadnamen für den Tk-Interpreter sind und ich bin mir gerade nicht so sicher ob Deine den Syntaxregeln dort entsprechen und damit dann auf Tk-Seite Probleme entstehen können. Auch sollte man vorher abklären ob man auf diese Weise nicht Namenskollisionen mit Tk/Tcl-Namen bekommen kann und damit dann nicht etwas überschreibt/verdeckt wenn man Pech hat.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Äh, natürlich geht das nicht, das entspricht nicht der Python-Syntax. Das geht aber auch mit Chinesisch nicht, denn auch mit chinesischen Zeichen wird man etwas schreiben können was nicht der Python-Syntax entspricht.
Die Namen sind Strings. Gibt es eine besondere String Syntax in Python? Habe ich nichts davon gehört.
BlackJack hat geschrieben:Zumal die Namen Pfadnamen für den Tk-Interpreter sind und ich bin mir gerade nicht so sicher ob Deine den Syntaxregeln dort entsprechen und damit dann auf Tk-Seite Probleme entstehen können. Auch sollte man vorher abklären ob man auf diese Weise nicht Namenskollisionen mit Tk/Tcl-Namen bekommen kann und damit dann nicht etwas überschreibt/verdeckt wenn man Pech hat.
Die Namen müssen mit einem Kleinbuchstaben beginnen aber eine Raute geht auch.

Und ein Punkt hat eine besondere Bedeutung, ähnlich wie '/' bei einem Directory oder '.' bei Python Objekten:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

def that(self,name):
    return self.nametowidget(name)


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.minsize(170, 250)
        
        # widget definitions ===================================

        tk.Entry(self,name = 'input a')
        tk.Entry(self,name = 'input b')
        tk.Button(self,text='a * b',name = 'a * b')
        tk.Label(self, name = 'ergebnis von a * b')
        Ein_Labelframe(self,name = 'ein LabelFrame')
 
        that(self,'input a').pack()
        that(self,'input b').pack()
        that(self,'a * b').pack(fill='x')
        that(self,'ergebnis von a * b').pack(fill='x')
        that(self,'ein LabelFrame').pack()

        # besondere Bedeutung eines Punktes
        that(self,'ein LabelFrame.ein Button im LabelFrame')['bg'] = 'yellow'

class Ein_Labelframe(tk.LabelFrame):

    def __init__(self,master,**kwargs):
        tk.LabelFrame.__init__(self,master,**kwargs)
        self.config(text='ein LabelFrame')
        # widget definitions ===================================

        py_referenz = tk.Button(self,text='ein Button im LabelFrame',name = 'ein Button im LabelFrame')

        # Mit Namen, kann man das Widget schön geprintet sehen
        print(py_referenz)

        that(self,'ein Button im LabelFrame').pack()

        # besondere Bedeutung eines Punktes
        that(self,'.a * b')['bg'] = 'lightgreen'

if __name__ == '__main__':
    Application().mainloop()
Also, wer auf die Root zugreifen will, das kann man immer tun mit '.'
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Und das mit den Klassen braucht man natürlich auch nicht

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

def that(self,name):
    return self.nametowidget(name)

# Widgets ==================

# == Application ==
self = tk.Tk()
self.minsize(170, 250)
tk.Entry(self,name = 'input a')
tk.Entry(self,name = 'input b')
tk.Button(self,text='a * b',name = 'a * b')
tk.Label(self, name = 'ergebnis von a * b')
tk.LabelFrame(self,text = 'ein LabelFrame',name = 'ein LabelFrame')

that(self,'input a').pack()
that(self,'input b').pack()
that(self,'a * b').pack(fill='x')
that(self,'ergebnis von a * b').pack(fill='x')
that(self,name = 'ein LabelFrame').pack()


# Subframe ==
self = that(self,name = 'ein LabelFrame')
tk.Button(self,text='ein Button im LabelFrame',name = 'ein Button im LabelFrame')        
that(self,'ein Button im LabelFrame').pack()


# Start ====================

that(self,'.').mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Optimal allerdings dürfte das sein, oder?

Code: Alles auswählen

import tkinter
tcl = tkinter.Tcl(None,None,"test",1)

result = tcl.eval('''

pack [entry ".input a"]
pack [entry ".input b"]
pack [button ".a * b" -text "a * b"] -fill x
pack [label ".ergebnis von a * b"] -fill x

''')
tcl.mainloop()
BlackJack

@Alfons Mittelmeyer:
Optimal wäre in dem Fall wohl eher das Tcl-Programm nicht unnötig in Python zu verpacken. ;-)
[codebox=tcl file=Unbenannt.txt]#!/usr/bin/env wish

pack [entry ".input a"]
pack [entry ".input b"]
pack [button ".a * b" -text "a * b"] -fill x
pack [label ".ergebnis von a * b"] -fill x[/code]
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer:
Optimal wäre in dem Fall wohl eher das Tcl-Programm nicht unnötig in Python zu verpacken. ;-)
Naja, wollte testen, inwieweit man danach von tkinter aus auf die tcl/tk GUI zugreifen kann. Anscheinend gar nicht. mainloop ging, aber das war es dann schon auch. Kein winfo_chidren und kein nametowidget.

Wenn man eine tcl/tk GUI hat, bleibt wohl nichts anderes übrig als diese zuerst unter tcl/tk nach Python zu konvertieren, damit man danach unter Python Zugriff bekommt.
Antworten