2

I am writing a library that can be used with some GUI and would like to be able to build an interface where user can see and/or change most of the object's parameters, and also write some of these parameters into the separate tables of SQL database.

Instead of hard-coding GUI representations for each object, I want to create them from objects parameters, so each parameter should have a corresponding type of GUI element associated with it. In a same manner, I want to write parameters to SQL tables based on the sql_tables property of parameter.

The best I came up so far is the following:

class Param:
  def __init__(name, value, gui_element, sql_tables):
    self.name = name
    self.value = value
    self.gui_element = gui_element
    # Names of the tables into which the parameter will be written
    self.sql_tables = sql_tables


class FruitParams:
  def __init__(fruit_type, init_amount, sold_amount):
    self.fruit_type = Param(
                   'Fruit type', fruit_type, 'Label', ('Fruits', 'Inventory'))
    self.init_amount = Param('Amount harvested', init_amount, 'EditableLabel', ('Inventory',) )
    self.sold_amount = Param('Amount sold', sold_amount, 'Slider', ('Inventory',))


class Fruit:
  def __init__(self, params):
    self.params = params


apple_params = FruitParams('Apple', 100, 0)
apple = Fruit(apple_params)

# proceed to Building GUI from apple.params ...

There will be dozens of parameters for each object. I wonder if there is a better approach than the one I am thinking about? It seems like a fairly common problem, so I don't want to re-invent the wheel. Also, I already have a big chunk of library written, so if I am to change all parameters into the proposed form, I would have to add .value to every already existing usage of each parameter, which I would prefer to avoid.

Or would some dictionaries that match parameters to their corresponding elements of other objects will be better in this case? Or should I add some factory object and somehow use it for the matching?

1

First, I'd like you to consider that 90% of your properties are likely going to end up using the same GUI element types (i.e. text edit, spinner, check box, drop down), and that the GUI element you're going to display does not need to be bound by each individual property, but rather by the datatype of said property. I.E. you display a spinner for an integer property, a checkbox for a boolean property, dropdown for a list property, etc.

Based on that, rather than forcing each individual property to define it's type, just look at the type of the property's value when deciding how to display a control to the user, as mentioned above.

The next natural progression of this solution is to ask how to handle properties which store complex datatypes (class objects, dictionaries). Just define a custom GUI element that can handle displaying that datatype in the way you want, and key off the type in the same way.

This way, you shouldn't even need to change your properties, just instead modify the code that displays the GUI to accept any given object, look at that object's list of properties, checking the type of each, and populate a table with the appropriate GUI elements based on the datatypes. Here's a simple workflow in code form that I think may demonstrate what I mean better:

class ObjectEditorGUI:
    def __init__(self, object_to_display):
        self.table = Table() # create a gui table here
        for property in object_to_display.property_list():
            property_type = type(property)
            if property_type == bool:
                self.table.insert_row(CheckBox(property))
            elif property_type == int:
                self.table.insert_row(Spinner(property))
            elif property_type == str:
                self.table.insert_row(TextBox(property))
            elif property_type == list:
                self.table.insert_row(DropDown(property))
            elif property_type == dict:
                self.table.insert_row(DictEditor(property))

This is pseudocode, obviously, but will hopefully make the proposed solution clear.

  • I like this approach. However, one thing bothers me: I also want to write to specified SQL tables. If I will be doing it in some other place rather then in the parameter object itself, it will be yet another place where I will have to add something every time I add a new parameter (first place is parameter initialization, second is the ObjectEditorGUI you have suggested, and third place is some SQL writing logic). That is the thing that I would like to avoid. Could you please comment on how SQL writing can be realized along the lines of the solution you proposed? – Cos_ma Sep 16 at 6:14
  • This one is a bit tougher of a solve... But it seems odd to me that you're writing to multiple tables for a single "parameter", based solely on the example you provided. In your example, you create a "fruit_type" and specify that it should be written to the SQL tables "fruit" and "inventory". Basing off of that, couldn't this solution be simplified by using only the inventory table, and instead using queries to get only the fruit (or even vice versa)? Again, i'm only basing on your example. If you can provide some more details on your database structure/use case, I may be able to help more. – TheKewlStore Sep 19 at 15:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.