-1

I cannot get the state of a (tk.)Label and (tk.)Checkbutton to visually turn to disable and normal depending on the value of an OptionMenu.

The command binding on the OptionMenu below seems fine, but my use of configure(state=...), in updateState() has no visible effect. Should I force some "refresh" or "repaint" (if yes how in the partial code below?) or am I missing something else?

import Tkinter
from Tkinter import Frame, LabelFrame, Label, Entry, Button, StringVar, OptionMenu, Checkbutton, IntVar, DISABLED, NORMAL

class GeneratorDialog:

  # The UI to configure the settings by the user
  def __init__(self, root, ctrl):
    self.__root = root
    self.__ctrl = ctrl

  def updateState(self, value, label, entry):
    if(value.get()==CONST.FORMAT_PDF): # test works, as the dialog below show in alternance as expected
        tkMessageBox.showinfo('Info', message="enabling checkbox")
        label.configure(state=NORMAL)
        entry.configure(state=NORMAL)
    else:            
        tkMessageBox.showinfo('Info', message="disabling the checkbox")
        label.configure(state=DISABLED)
        entry.configure(state=DISABLED)
    #self.__root.update_idletasks() # how to force "redraw" with grid() manager?


  def show(self):
    self.__root.title(CONST.APP_NAME)
    mainFrame = Frame(self.__root)
    mainFrame.grid(sticky='ew')
    outputFrame = LabelFrame(mainFrame, text='Output Settings')
    outputFrame.grid(column=0, row=1, padx=5, pady=5, sticky='ew')


    keepGeneratedScribusFilesLabel = Label(outputFrame, text='Keep Scribus Files:', width=15, anchor='e')
    keepGeneratedScribusFilesLabel.grid(column=4, row=2, padx=5, pady=5, sticky='e')
    keepGeneratedScribusFilesCheckbox = Checkbutton(outputFrame, variable=self.__ctrl.getKeepGeneratedScribusFilesCheckboxVariable(), anchor='w')
    keepGeneratedScribusFilesCheckbox.grid(column=5, row=2, padx=5, pady=5, sticky='w')

    mergeOutputLabel = Label(outputFrame, text='Merge in Single File:', width=15, anchor='w')
    mergeOutputLabel.grid(column=0, row=2, padx=5, pady=5, sticky='w')
    mergeOutputCheckbox = Checkbutton(outputFrame, variable=self.__ctrl.getMergeOutputCheckboxVariable())
    mergeOutputCheckbox.grid(column=1, row=2, padx=5, pady=5, sticky='w')  

    outputFormatLabel = Label(outputFrame, text='Output Format:', anchor='e')
    outputFormatLabel.grid(column=2, row=2, padx=5, pady=5, sticky='e')
    outputFormatListBox = OptionMenu(outputFrame, self.__ctrl.getSelectedOutputFormat(), *self.__ctrl.getOutputFormatList(),
        command=lambda l=keepGeneratedScribusFilesLabel, c=keepGeneratedScribusFilesCheckbox, v=self.__ctrl.getSelectedOutputFormat(): self.updateState(v, l, c))
    outputFormatListBox.grid(column=3, row=2, padx=5, pady=5, sticky='w')            


    # Buttons to Cancel or to Run the Generator with the given Settings
    helpButton = Button(buttonFrame, text='Help', width=10, command=self.__ctrl.helpButtonHandler)
    helpButton.grid(column=0, row=0, padx=5, pady=5, sticky='e')
    cancelButton = Button(buttonFrame, text='Cancel', width=10, command=self.__ctrl.buttonCancelHandler)
    cancelButton.grid(column=1, row=0, padx=5, pady=5, sticky='e')
    generateButton = Button(buttonFrame, text='Generate', width=10, command=self.__ctrl.buttonOkHandler)
    generateButton.grid(column=2, row=0, padx=5, pady=5, sticky='e')

    # Finally show the Generator Dialog
    mainFrame.grid()
    self.__root.grid()
    self.__root.mainloop()

full code is at https://github.com/berteh/ScribusGenerator/blob/93a12de4be28054344533ad8fc424e37180668de/ScribusGenerator.py#L278

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
Berteh
  • 73
  • 8
  • 2
    You need to provide an [MCVE] that would be able to reproduce your issue. A standalone program. – Anand S Kumar Sep 15 '15 at 08:54
  • Add a list item you want to change. create a function that will change. you're doing without the use of a namespace in your applications, you must use list or dictionary. – dsgdfg Sep 15 '15 at 09:06
  • 2
    Can you provide a runable example of your problem. I was not able to reproduce your problem. So to answer your question you don't need to update your label after changing its state. – VRage Sep 15 '15 at 10:06
  • It's very odd that you're calling `mainloop` inside the dialog. Don't you already have a `mainloop` running for your program as a whole? – Bryan Oakley Sep 15 '15 at 11:52
  • @AnandSKumar ok, will try. – Berteh Sep 16 '15 at 10:10
  • @dsgdfg ok, will try, but why would creating a list of the items to change be any different from passing them as parameters to the function "updateState" as I currently do? – Berteh Sep 16 '15 at 10:14
  • @BryanOakley no I have no other mainloop. This dialog is a "standalone" GUI, but with a companion controller class in the same file, thus I put the mainloop in the dialog class. Is it bad for any particular reason, or just unusual? – Berteh Sep 16 '15 at 10:14
  • 1
    @Berteh: you shouldn't have more than one `mainloop` running, but if you only call it once, that's OK. – Bryan Oakley Sep 16 '15 at 11:23
  • solved it by using class variables (self.X) instead of lambda local variables. still don't know why the former code (with local variables in the lambda) would not update the status of the elements (maybe it created copies thereof?)... but I found a workaround. thanks all for your help. – Berteh Sep 16 '15 at 13:49

1 Answers1

0

solved it by using class variables (self.X) instead of lambda local variables.

still don't know why the former code (with local variables in the lambda) would not update the status of the Tk elements (maybe it created copies thereof?)... but I found a workaround.

thanks all for your help

Berteh
  • 73
  • 8
  • 1
    As a general rule of thumb, IMHO I think lambdas should be avoided. Unless you truly need them, they add complexity without providing any real benefits – Bryan Oakley Sep 16 '15 at 14:08