Wie soll man **{...} anders schreiben?

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

Also man hat mal geschrieben, dass man nicht **{..} schreiben soll, sondern (key1 = par1, key2 = par2)

Aber ich bekomme es nicht hin. Hier das Beispiel:

Code: Alles auswählen

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

class Button(tk.Button):
    def __init__(self,master,**kwargs):
        call_code = kwargs.pop('call code',None)
        tk.Button.__init__(self,master,**kwargs)
        if call_code:
            self['command'] = call_code

def code_function():
    print('hat geklappt')

class Application(tk.Tk) :

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.call_code = Button(self,**{'text' : 'button', 'call code' : code_function})
        self.call_code.pack()

Application().mainloop()
Ich habe probiert:

Code: Alles auswählen

        self.call_code = Button(self,text = 'button', call code = code_function)
        # und auch
        self.call_code = Button(self,text = 'button', 'call code' = code_function)
Aber nichts davon geht. Wie kann man das schreiben, sodass es funktioniert?
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: warum sollte auch irgendjemand solche Argumentnamen verwenden? Solch eine Funktion kannst Du doch auch gar nicht definieren. »call code« sollte einfach »command« heißen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: warum sollte auch irgendjemand solche Argumentnamen verwenden? Solch eine Funktion kannst Du doch auch gar nicht definieren. »call code« sollte einfach »command« heißen.
Das mit dem Namen 'command' könnte problematisch werden. Da war mein Beispiel etwas zu knapp dargestellt gegenüber dem realen Fall. Das kommt dann schon besser hin:

Code: Alles auswählen

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

class Button(tk.Button):
    def __init__(self,master,**kwargs):

        self.call_code = kwargs.pop('command',None)
        tk.Button.__init__(self,master,**kwargs)
        kwargs = {'command' : self.call_code}
        self.config(**kwargs)

    def config(self,**kwargs):
        if not kwargs:
            kwargs = tk.Button.config(self)
            if self.call_code:
                kwargs['command'] = (self.call_code,)
                return kwargs
        else:
            if 'command' in kwargs:
                self['command'] = kwargs.pop('command')
            return tk.Button.config(self,kwargs)

def code_function():
    print('hat geklappt')

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.call_code = Button(self,text = 'button', command = code_function)
        self.call_code.pack()


Application().mainloop()
Das funktioniert zwar. Aber wenn ich im Weiteren den command des Buttons ändern würde, könnte ich ihn nicht mehr per config zurücklesen. Und natürlich wäre auch __getitem__ entsprechend angepaßt, sodass ich dann den richtigen command des Buttons gar nicht mehr bekäme.

Aber ob ich den original command des Buttons brauche. Bisher zwar nicht, aber wer weiß?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sorry das war auch nicht er Realfall. Sondern das ist der Realfall:

Code: Alles auswählen

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

class Button(tk.Button):
    def __init__(self,master,**kwargs):

        self.call_code = kwargs.pop('command',None)
        tk.Button.__init__(self,master,**kwargs)

    def config(self,**kwargs):
        if not kwargs:
            kwargs = tk.Button.config(self)
            if self.call_code:
                kwargs['command'] = self.call_code
                return kwargs
        else:
            if 'command' in kwargs:
                self.call_code = kwargs.pop('command')
            return tk.Button.config(self,kwargs)

def code_function():
    print('hat geklappt')

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.call_code = Button(self,text = 'button', command = code_function)
        self.call_code.pack()


Application().mainloop()
Und entsprechend natürlich auch __getitem__ und __setitem__

'command' darf es ganz gewiß nicht heißen, weil sonst der richtige command nicht mehr funktioniert!
BlackJack

@Alfons Mittelmeyer: Dann nenn es halt anders. Es muss halt nur etwas sein das in Python ein gültiger Bezeichner ist.

Ich habe schon wieder das Gefühl Du trollst. Das übliche Muster: Jemand sagt Dir das macht man so nicht, und Du versuchst prompt auf Teufel komm raus irgendwelche exotischen Fälle zu konstruieren die angeblich beweisen sollen das man das so machen muss, wie man das normalerweise nicht macht.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Dann nenn es halt anders. Es muss halt nur etwas sein das in Python ein gültiger Bezeichner ist.

Ich habe schon wieder das Gefühl Du trollst. Das übliche Muster: Jemand sagt Dir das macht man so nicht, und Du versuchst prompt auf Teufel komm raus irgendwelche exotischen Fälle zu konstruieren die angeblich beweisen sollen das man das so machen muss, wie man das normalerweise nicht macht.
Ich trolle nicht, und es kein exotischer Fall. Ich bin dabei, zu implementieren, dass der GuiDesigner beim Exportieren nicht nur die Gui Exportiert, sondern bei Wunsch auch einen zusätzlichen Funktions oder Klassenaufruf. Da kann man dann die Gui in einem File haben und seine Code Klassen dazu in einem anderen Modul. Wenn man die Gui ändert und exportiert, braucht man nicht diese irgendwie in seinen Code reinkopieren, sondern das Programm läuft dann auch bei geänderter Gui.

Da bin ich beim Überlegen, ob er entsprechende Config Optionsname 'call_code' oder 'call code' heißen soll, der wird ja nicht exportiert. Bei meinem GuiDesigner Code, könnte ich ja wieder auf **{...} zurücksetzen, diesen Code will ja sowieso keiner. Und beim Exportieren lasse ich es wie jetzt, also Button(self,text='button'). Das wäre zumindest meine Idee,
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Was hältst du von der folgenden drolligen Schreibart:

Code: Alles auswählen

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
 
class Button(tk.Button):
    def __init__(self,master,**kwargs):
        call_code = kwargs.pop('call code',None)
        tk.Button.__init__(self,master,**kwargs)
        if call_code:
            self['command'] = call_code
 
def code_function():
    print('hat geklappt')
 
class Application(tk.Tk) :
 
    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        my_button_options = {'text' : 'button', 'call code' : code_function}
        self.call_code = Button(self, **my_button_options)
        self.call_code.pack()
 
Application().mainloop()
Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf: diese Schreibweise ist wohl auch nicht das Wahre. Ich habe mich entschlossen, es doch 'call_code' zu nennen.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: weise Entscheidung. Man sollte halt die Eigenschaften der Sprache nicht versuchen umzubiegen. Bezeichner bestehen nunmal nicht aus Leerzeichen, sondern können nur Buchstaben, Zahlen, Unterstrich enthalten.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Nein ich habe mich umentschieden, die Option heißt jetzt: 'call Code(self)'

Das wäre ein Beispiel in GuiDesigner Code:

Code: Alles auswählen

Button('button',**{'text': 'button', 'call Code(self)': 'code.CallCode'})

widget('button').pack()
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Troll!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3: Was hast Du dagegen, wenn ich das so nenne? Ich will deutlich machen, dass es sich dabei nicht um eine normale config Option handelt, sondern um etwas anderes. Es geht nämlich darum, was exportiert wird.

Hier und daher auch im dazugehörigen Eingabefeld im GuiDesigner heißt es 'call Code(self)'

Code: Alles auswählen

LabelFrame('labelframe',**{'myclass': 'FrameWithCode', 'width': 150, 'call Code(self)': 'code.CodeForFrameWithCode', 'height': 150, 'text': 'Frame with Code'})
goIn()

Button('button',**{'call Code(self)': 'code.CodeForMyButton', 'myclass': 'MyButton', 'text': 'button'}).place(y='34', x='29')

goOut()


widget('labelframe').pack()
Und exportiert wird es als:

Code: Alles auswählen

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
#import DynTkInter as tk # for GuiDesigner

# Application definition ============================

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.labelframe = FrameWithCode(self,name='#0_labelframe',text='Frame with Code', width=150, height=150)
        self.labelframe.pack()

class FrameWithCode(tk.LabelFrame):

    def __init__(self,master,**kwargs):
        tk.LabelFrame.__init__(self,master,**kwargs)
        self.myclass = 'FrameWithCode'
        self.call_code = 'code.CodeForFrameWithCode'
        # widget definitions ===================================
        self.button = MyButton(self,name='#1_button',text='button')
        self.button.place(x='29', y='34')
        # call Code ===================================
        code.CodeForFrameWithCode(self)

class MyButton(tk.Button):

    def __init__(self,master,**kwargs):
        tk.Button.__init__(self,master,**kwargs)
        self.myclass = 'MyButton'
        self.call_code = 'code.CodeForMyButton'
        # call Code ===================================
        code.CodeForMyButton(self)

#Application().mainloop('guidesigner/Guidesigner.py') # for GuiDesigner
Application().mainloop()
Wenn man dazu noch ein oder auch mehrere Module mit dem dazugehörigen Code importiert, hat man ein lauffähiges Programm!!!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Und so sieht der export ohne Namen aus, bei dem man nicht wieder aus dieser Source im GuiDesigner alle Angaben zurückbekommt.

Code: Alles auswählen

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.labelframe = FrameWithCode(self,text='Frame with Code', height=150, width=150)
        self.labelframe.pack()

class FrameWithCode(tk.LabelFrame):

    def __init__(self,master,**kwargs):
        tk.LabelFrame.__init__(self,master,**kwargs)
        # widget definitions ===================================
        self.button = MyButton(self,text='button')
        self.button.place(y='34', x='29')
        # call Code ===================================
        code.CodeForFrameWithCode(self)

class MyButton(tk.Button):

    def __init__(self,master,**kwargs):
        tk.Button.__init__(self,master,**kwargs)
        # call Code ===================================
        code.CodeForMyButton(self)

Application().mainloop()
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: woher kommt denn code in "code.CodeForFrameWithCode(self)"? Das läuft so nicht. Wenn Du kenntlich machen willst, dass etwas aus einem anderen Framework kommt, dann nimmt man übelicherweise eine Prefix, z.B. "dyn_" -> "dyn_code" / "dyn_call" oder was auch immer die Funktion dieses Arguments ist.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3: das kommt nicht aus einem anderen Framework, sondern es handelt sich dabei um die Eingabe des Users.

Dafür ist natürlich noch ein import manuell zu ergänzen, etwa:

import MyCodeModul as code

ob das jetzt code oder anders heißt, hängt davon ab, was eingegeben wird!
Jedenfalls sollte der Code in einem anderen Modul sein, damit er nicht durch den Gui export überschrieben wird.
Antworten