0

I'm making a framework for building GUI apps with tkinter and in my code I have a Scene class that has a add(widget,params) function which creates a tkinter widget and adds it to the Scenes widget dictionary. But I can only add a widget that I have built an add() function for because different widgets have different named parameters.

how would I make a function that takes a dictionary in the form {paramName,value} which would then pass it to the widget function

for example

scene.add(button, {'command':Click, "text":"click me"} )

my current code is

import tkinter as tk

class scene():
    def __init__(self, title, width, height):
        self.widgets = {}
        self.title = title
        self.width = width
        self.height = height

    def add(self, name, type, widget, root, params):
        if name in self.widgets.keys():
            return
        else:
            if type == "button":
                width = params[0]
                height = params[1]
                text = params[2]
                self.widgets[name] = [widget(root,width=width, height=height,text=text),params[2:]]

    def get(self,name):
        if name in self.widgets.keys():
            return self.widgets[name][0]
faruk13
  • 1,276
  • 1
  • 16
  • 23
  • You may want to take a look on approach 4 of the accepted answer here https://stackoverflow.com/questions/62050496/nested-class-factory-with-tkinter – Thingamabobs Jul 25 '20 at 12:12
  • Are you aware of ``**kwargs``? – MisterMiyagi Jul 25 '20 at 12:19
  • Can you clarify which of your code or description are correct? The description says you have ``Scene.add(self, widget, params)``, the code shows you have ``Scene.add(self, name, type, widget, root, params)``. The description says you want to pass "a dictionary" ``{paramName,value}`` which is a set, but the code shows a proper dictionary. – MisterMiyagi Jul 25 '20 at 12:22
  • I hope I understood your question correctly. If the duplicate isn't answering what you tried to ask, please [edit] to clarify and ping me hlike @tripleee) to have the duplicate removed. – tripleee Jul 25 '20 at 12:27
  • sorry about the duplicate I couldn't find it when searching for the answer – an inconspicuous semicolon Jul 25 '20 at 12:41
  • also the answer on that page was how to get them from dict(name="thing") I was asking it the other way such as diction = {"name" : "thing"} foo(diction) which would return " name= 'thing' " – an inconspicuous semicolon Jul 25 '20 at 12:57
  • ``dict(name="thing")`` and ``{"name" : "thing"}`` produce precisely the same value. – MisterMiyagi Jul 25 '20 at 13:31
  • i meant, that answer went from dict(name="thing") to {"name":"thing"} whereas mine needed to go from {"name":"thing"} to name="thing" not dict(name="thing") – an inconspicuous semicolon Jul 25 '20 at 17:27

1 Answers1

1

You can make use of setattr. See example below, where I have defined an if clause for the "generic" string:

from tkinter import Tk, Button

class scene():
    def __init__(self, title, width, height):
        self.widgets = {}
        self.title = title
        self.width = width
        self.height = height

    def add(self, name, type, widget, root, params, attributes={}):
        if name in self.widgets.keys():
            return
        else:
            if type == "button":
                width = params[0]
                height = params[1]
                text = params[2]
                self.widgets[name] = [widget(root,width=width, height=height,text=text),params[2:]]
            elif type == "generic":
                width = params[0]
                height = params[1]
                text = params[2]
                widget_obj = widget(root,width=width, height=height,text=text)
                for key, val in attributes.items():
                    setattr(widget_obj, key, val)
                self.widgets[name]=[widget_obj,params[2:]]

    def get(self,name):
        if name in self.widgets.keys():
            return self.widgets[name][0]

# Create intance of tkinter
root = Tk(className = 'Python Examples - Window 0')
root.geometry("600x700")
root.resizable(0,0)

# Call class
sc=scene("Some title", 100, 100)
sc.add("button_widget", "button", Button, root, [10, 10, "some text"])
sc.add("button_widget2", "generic", Button, root, [10, 10, "some text"], {"command": "click", "text": "click me"})
David Duran
  • 1,786
  • 1
  • 25
  • 36