Question

TOP LEVEL EDIT: this question has in principle been answered in the original thread - however, there are some fundamental questions that I would like to learn more about. Please don't bust a gut answering the question directly. I am happy to remove this Q if its cluttering!


Related to this question I asked yesterday: Python/ttk/tKinter - passing an argument with a button click func?

I am trying a new approach, and I can (sort of) get it to work, however, only if I 'hard' code the function, which I am trying to avoid...

I have 36 buttons [a-z] & [0-9]. When a user has clicks the button, the askcolor dialogue pops up, and I want the returning colour to be recorded.

In the class init, I declare some vars (all setting a colour value to white):

class MakeGUI(Frame):
    def __init__(self,root):
        Frame.__init__(self, root)
        self.root = root
        ##colour values
        self.AVal = "#FFFFFF"
        self.BVal = "#FFFFFF"
        self.CVal = "#FFFFFF"
        etc. 

when I populate a text box, I use the colour var as the bg arg:

    ## letter labels
    self.boxA = Text(self.mainframe, state='normal', width=3, height=1, background=self.AVal).grid(column=2, row=2, padx=4)
    self.boxB = Text(self.mainframe, state='normal', width=3, height=1, background=self.BVal).grid(column=3, row=2, padx=4)
    self.boxC = Text(self.mainframe, state='normal', width=3, height=1, background=self.CVal).grid(column=4, row=2, padx=4)
    etc.

Then I set the buttons up:

    self.bloba = ttk.Button(self.mainframe, text="A",style= 'mainSmall.TButton', command= lambda: self.getColour("self.AVal")).grid(column=2, row=3)
    self.blobb = ttk.Button(self.mainframe, text="B",style= 'mainSmall.TButton', command= lambda: self.getColour("self.BVal")).grid(column=3, row=3)
    self.blobc = ttk.Button(self.mainframe, text="C",style= 'mainSmall.TButton', command= lambda: self.getColour(("self.CVal")).grid(column=4, row=3)

Note - I am "sending" the string for the var, as I couldn't get the object to pass over properly - ideally I want to send just the object, but this was the only work around I could get to work.

Then I set up the button func:

def getColour(self,glyphRef):
    print self.AVal
    (triple, hexstr) = askcolor()
    if hexstr:
        eval(glyphRef+"=hexstr")
    print self.AVal

The two print statements are there for monitoring purposes only as I figure out how to get it to work.

I am also very aware that the eval method is not desirable or ideal. I just can't find an alternate way that gets me close to my ideal solution....

This method throws an error:

#FFFFFF
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in __call__
    return self.func(*args)
  File "colourPicker/colourTest.py", line 109, in <lambda>
    self.bloba = ttk.Button(self.mainframe, text="A",style= 'mainSmall.TButton', command= lambda: self.getColour("self.AVal")).grid(column=2, row=3)
  File "colourPicker/colourTest.py", line 161, in getColour
    eval(glyphRef+"=hexstr")
  File "<string>", line 1
    self.AVal=hexstr
         ^
SyntaxError: invalid syntax

To try and test what is going on, I tried hard coding the var in the button func:

def getColour(self,glyphRef):
    print self.AVal
    (triple, hexstr) = askcolor()
    if hexstr:
        self.AVal=hexstr
    print self.AVal

This does result in the var being changed:

#FFFFFF
#24d9d9

This means I could write 36 different button click funcs, but that seems counter intuitive... esp when what little I understand of class funcs, its to deal with exactly this kind of challenge!

Any suggestions gratefully received.

Was it helpful?

Solution

I ended up throwing the init values into a self.dict, and then changing the dict from the click func.

so now the init is:

    self.colourDict = \
    {"AVal":"#FFFFFF",
     "BVal":"#FFFFFF",
     "CVal":"#FFFFFF",
     "DVal":"#FFFFFF",
      etc. 

The text box maker is:

    self.boxA = Text(self.mainframe, state='normal', width=3, height=1, background=self.colourDict['AVal'])
    self.boxB = Text(self.mainframe, state='normal', width=3, height=1, background=self.colourDict['BVal'])
    self.boxC = Text(self.mainframe, state='normal', width=3, height=1, background=self.colourDict['CVal'])
    etc.

which are then gridded:

    self.boxA.grid(column=2, row=2, padx=4)
    self.boxB.grid(column=3, row=2, padx=4)
    self.boxC.grid(column=4, row=2, padx=4)
    etc.

and then the buttons:

    self.bloba = ttk.Button(self.mainframe, text="A",style= 'mainSmall.TButton', command= lambda: self.getColour(self.boxA,"AVal")).grid(column=2, row=3)
    self.blobb = ttk.Button(self.mainframe, text="B",style= 'mainSmall.TButton', command= lambda: self.getColour(self.boxB,"BVal")).grid(column=3, row=3)
    self.blobc = ttk.Button(self.mainframe, text="C",style= 'mainSmall.TButton', command= lambda: self.getColour(self.boxC,"CVal")).grid(column=4, row=3)
    etc.

which point at the button func:

def getColour(self,glyphRef, value):
    (triple, hexstr) = askcolor()
    if hexstr:
        glyphRef.config(bg=hexstr)
        self.colourDict[value] = hexstr

Which both sets the visual colour, and gives me a callable dict that I can use to save the results in XML for later analysis. Job done. :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top