[Tkinter-discuss] Fwd: WxPython -> Tkinter

Guilherme Polo ggpolo at gmail.com
Sun Nov 2 23:04:46 CET 2008


On Sun, Nov 2, 2008 at 7:41 PM, Olrik Lenstra <o.lenstra at gmail.com> wrote:
> I see, now if I recall correctly I can run the scan by using the
> following command:
> thread.start_new_thread(myfunction,("Thread No:1",2))

It's more likely that you will want to use the threading module instead.
That would then be: mythread = threading.Thread(target=myfunction,
args=("Thread No: 1", 2))
and at some point you would call mythread.start() and then at some
other point you could check if it is alive by doing mythread.is_alive
(in python 2.6 or mythread.isAlive() in older versions), and possible
other things you may want to do of course.

>
> So I'd replace myfunction with the scan function and it would run at
> the same time?
>

Not really at same time, GIL doesn't allow for that, but you don't
need this "feature" for this task. It wouldn't block the GUI tho.

> Regards,
> Olrik
>
> 2008/11/2 Guilherme Polo <ggpolo at gmail.com>:
>> 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
>>
>



-- 
-- Guilherme H. Polo Goncalves


More information about the Tkinter-discuss mailing list