[Tkinter-discuss] Fwd: WxPython -> Tkinter

Guilherme Polo ggpolo at gmail.com
Sun Nov 2 22:23:12 CET 2008


On Sun, Nov 2, 2008 at 7:17 PM, Olrik Lenstra <o.lenstra at gmail.com> wrote:
> Hmm, The program worked and no error messages popped up but the GUI
> still hung when I tried running the scan.

If the scan blocks the application then that safe_yield is not
supposed to work, it wouldn't work in wxpython either (using only
that). Do use polling to determine when the scan finishes for example
? That would be the place to run safe_yield. If this is not the case,
and the scanner doesn't let you work it in an asynchronous way, then
you will have to run that scan in another thread/process and the gui
will not block.

> Maybe this is a help:
>
> The program is a program that does a couple of scans like ipconfig / dxdiag etc.
> While the scan is running the GUI has a status bar in which the text
> changes when the scan is running a new part of the scan.
> like: "TSO is now making an ipconfig log"
>
> Thanks again! :)
> Regards,
> Olrik
>
> 2008/11/2 Guilherme Polo <ggpolo at gmail.com>:
>> On Sun, Nov 2, 2008 at 2:40 PM, Guilherme Polo <ggpolo at gmail.com> wrote:
>>> On Sun, Nov 2, 2008 at 12:34 PM, Olrik Lenstra <o.lenstra at gmail.com> wrote:
>>>> I would like to thank you already for all the help you've given me, it
>>>> is really appreciated :)
>>>
>>> You are welcome.
>>>
>>>> I decided to update to Python2.6 instead of using the tile pack. My
>>>> application now shows the GUI again.
>>>> So I added the code you gave me to prevent the window from hanging
>>>> once I execute my scan.
>>>> I get the following Traceback:
>>>>
>>>> D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)>python TSO.
>>>> pyw
>>>> Exception in Tkinter callback
>>>> Traceback (most recent call last):
>>>>  File "D:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
>>>>    return self.func(*args)
>>>>  File "D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)\TSO
>>>> main.pyw", line 29, in OnScan
>>>>    TSOscn.Scan(root, status)
>>>>  File "D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)\TSO
>>>> scn.pyw", line 23, in Scan
>>>>    TSOex.safe_yield(Frame, True)
>>>>  File "D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)\TSO
>>>> ex.pyw", line 75, in safe_yield
>>>>    window_disabler(window)
>>>>  File "D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)\TSO
>>>> ex.pyw", line 90, in window_disabler
>>>>    if widget.instate(['!disabled']):
>>>> AttributeError: Button instance has no attribute 'instate'
>>>>
>>>
>>> That is because Button is not a ttk.Button, but a "normal"
>>> Tkinter.Button. I didn't know before you would be using windows, but
>>> since this is the case, you may try substituting the use of instate
>>> and state calls (that are available only for ttk widgets) by the use
>>> of widget.wm_attributes('-disabled', 1),
>>> widget.wm_attributes('-disabled', 0) and
>>> widget.wm_attributes('-disabled'). I will be able to test it here
>>> later since my new pc arrived with a windows vista.
>>>
>>
>> I have changed it a bit now, please retry with this one:
>>
>> import sys
>>
>> inside_tkyield = False
>> disabled_wins = {}
>> platform_win = 'win' in sys.platform
>> if not platform_win:
>>    import ttk
>>
>> def safe_yield(window, only_if_needed=False):
>>    window_disabler(window)
>>    try:
>>        return tk_yield(window, only_if_needed)
>>    finally:
>>        window_enabler(window)
>>
>>
>> def window_enabler(window):
>>    for widget, flags in disabled_wins.iteritems():
>>        if platform_win:
>>            window.wm_attributes('-disabled', 0)
>>        else:
>>            ttk.Widget.state(widget, flags)
>>    disabled_wins.clear()
>>
>>
>> def window_disabler(window):
>>    if platform_win and not int(window.wm_attributes('-disabled')):
>>        window.wm_attributes('-disabled', 1)
>>        disabled_wins[window] = 1
>>        return
>>
>>    widgets = window.children.values()
>>    widgets.append(window)
>>
>>    for widget in widgets:
>>        if widget.instate(['!disabled']):
>>            prev_flags = widget.state(['disabled'])
>>            disabled_wins[widget] = prev_flags
>>
>>
>> def tk_yield(window, only_if_needed=False):
>>    # wx implements this differently based on the backend it is using
>>    global inside_tkyield
>>    if inside_tkyield:
>>        if not only_if_needed:
>>            raise RuntimeError("safe_yield called recursively")
>>
>>        return False
>>
>>    inside_tkyield = True;
>>
>>    window.update()
>>    window.update_idletasks()
>>
>>    inside_tkyield = False;
>>
>>    return True
>>
>> It should work under windows, but it is not very nice elsewhere right
>> now unfortunately.
>>
>>>> D:\Documents\OLPrograms\TroubleShooting Olrik\sourcecode\TSO(source)>
>>>>
>>>> I don't know if it makes a difference, But I think you should know
>>>> that I use different files that import other applications (made by me)
>>>> Example:
>>>>
>>>> TSO.pyw is the main script, this looks if the very first argument is
>>>> "TSO.pyw", if it is, run "TSOmain.TSO()"
>>>> TSOmain.pyw is the GUI and the GUI only, from there it calls other files etc.
>>>> I hope that wasn't too confusing.
>>>>
>>>> Thanks again, I really appreciate it.
>>>>
>>>> Regards,
>>>> Olrik
>>>>
>>
>>
>> --
>> -- Guilherme H. Polo Goncalves
>>
>



-- 
-- Guilherme H. Polo Goncalves


More information about the Tkinter-discuss mailing list