Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #50766 > unrolled thread

tkinter redraw rates

Started byfronagzen@gmail.com
First post2013-07-16 17:57 -0700
Last post2013-07-17 20:10 +0200
Articles 20 on this page of 21 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  tkinter redraw rates fronagzen@gmail.com - 2013-07-16 17:57 -0700
    Re: tkinter redraw rates David Hutto <dwightdhutto@gmail.com> - 2013-07-16 21:32 -0400
    Re: tkinter redraw rates David Hutto <dwightdhutto@gmail.com> - 2013-07-16 21:34 -0400
    Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-16 21:40 -0400
      Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-16 18:51 -0700
        Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-16 22:21 -0400
          Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-16 20:04 -0700
            Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-17 06:07 -0400
              Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-17 04:08 -0700
                Re: tkinter redraw rates Michael Torrie <torriem@gmail.com> - 2013-07-17 16:53 -0600
              Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-17 04:10 -0700
                Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-17 07:42 -0400
                  Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-17 06:18 -0700
                    Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-17 13:38 -0400
                      Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-17 17:44 -0700
                        Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-17 21:07 -0400
                          Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-17 21:38 -0700
                            Re: tkinter redraw rates Dave Angel <davea@davea.name> - 2013-07-18 00:52 -0400
                            Re: tkinter redraw rates Christian Gollwitzer <auriocus@gmx.de> - 2013-07-18 09:20 +0200
                              Re: tkinter redraw rates fronagzen@gmail.com - 2013-07-18 02:10 -0700
                    Re: tkinter redraw rates Peter Otten <__peter__@web.de> - 2013-07-17 20:10 +0200

Page 1 of 2  [1] 2  Next page →


#50766 — tkinter redraw rates

Fromfronagzen@gmail.com
Date2013-07-16 17:57 -0700
Subjecttkinter redraw rates
Message-ID<b80dcc82-7fdb-4213-bec0-5e704483ce28@googlegroups.com>
Hm. So I've written a GUI in tkinter. I've found two performance issues, I was hoping someone could point me in the right direction.

Firstly, I'm using an image as a border, namely:

from tkinter import *
from tkinter import ttk

root_frame = Tk()
root_frame.configure(background = 'black')

img1 = PhotoImage("frameBorder", data="""
       R0lGODlhQABAAMIHAAAAABkfLTMrMzMrZjNVZjNVmUFch////ywAAAAAQABAAAAD9A
       i63P4wykmrvTjrzbu/hlGMZGmeaBp2QmgIQSzPdG3fbShk+u3/wFkONAgaj7aBoWIo
       Ip9P5aQFrSJfkpd1C2xluWDfEhIKm2mrh/bM9qrZ8MDYYYiz54263Yxn6PdgfQt/gF
       uCCoSFVYcAiYpPjI6PR5GTVpWWUJiZV2SckJ6flKGiQZulP6eoN6qrNa2uM7CxMbO0
       trG4rrqrvKi+pcCiwp/EnMaZyJbKk8yPzorQhdKA1HuRMLQ0bnSSuYyN2mhZ2eLcD1
       TicjtZ3sPgfu7J8A0EBOWfQxg5a4/87BtcCBxIsKDBgh8SKlzIsKHDhxAVJgAAOw==""")

style = ttk.Style()
style.element_create("RoundedFrame", "image", "frameBorder",
                                  border=30, sticky="nsew")
style.layout("RoundedFrame", [("RoundedFrame", {"sticky": "nsew"})])

input_frame = ttk.Frame(root_frame,
                        style = "RoundedFrame",
                        padding = 15,
                        width = 640,
                        height = 180
                        )
input_frame.pack(padx=10, pady=10)

This works, yes, but is annoyingly laggy on an older computer when I try to move the window around. I figure it's because the program has to keep redrawing the image border when dragged around, and is exacerbated by the fact that I have two of the imageborder frames in my application. How can I remedy this? I've tried using a hard-drawn image on a Canvas instead of the image border, but it's suboptimal because that prevents resizing the window.


The other performance issue I've found is that when the logic is running, the app doesn't redraw. Ordinarily this would be acceptable, but as part of my program, it loads data from a website, and during the load, the window completely freezes up and doesn't respond until the download is done; as I understand it, tkinter doesn't redraw until it is forced to by .update() or control is given back to the mainloop. How can I force a more frequent redraw rate?

[toc] | [next] | [standalone]


#50770

FromDavid Hutto <dwightdhutto@gmail.com>
Date2013-07-16 21:32 -0400
Message-ID<mailman.4791.1374024725.3114.python-list@python.org>
In reply to#50766

[Multipart message — attachments visible in raw view] — view raw

I've had a similar problem with a tkinter/3D app. right now I'm looking
toward Blender, and the Python API, but there is also wxpython, and the
usual python's library gtk.

There is also matplotlib with the ion window. but, I, personally, am going
to go with Blender, and Python API, with maybe a few other imports, and if
ctypes...includes if I remember C correctly without reference at this time
the usages of returned data type values
for you to utilize.


But for the plainer answer I'd go with wxpython if you decide not to use a
different library, and for a GDK, Blend


On Tue, Jul 16, 2013 at 8:57 PM, <fronagzen@gmail.com> wrote:

> Hm. So I've written a GUI in tkinter. I've found two performance issues, I
> was hoping someone could point me in the right direction.
>
> Firstly, I'm using an image as a border, namely:
>
> from tkinter import *
> from tkinter import ttk
>
> root_frame = Tk()
> root_frame.configure(background = 'black')
>
> img1 = PhotoImage("frameBorder", data="""
>        R0lGODlhQABAAMIHAAAAABkfLTMrMzMrZjNVZjNVmUFch////ywAAAAAQABAAAAD9A
>        i63P4wykmrvTjrzbu/hlGMZGmeaBp2QmgIQSzPdG3fbShk+u3/wFkONAgaj7aBoWIo
>        Ip9P5aQFrSJfkpd1C2xluWDfEhIKm2mrh/bM9qrZ8MDYYYiz54263Yxn6PdgfQt/gF
>        uCCoSFVYcAiYpPjI6PR5GTVpWWUJiZV2SckJ6flKGiQZulP6eoN6qrNa2uM7CxMbO0
>        trG4rrqrvKi+pcCiwp/EnMaZyJbKk8yPzorQhdKA1HuRMLQ0bnSSuYyN2mhZ2eLcD1
>
>  TicjtZ3sPgfu7J8A0EBOWfQxg5a4/87BtcCBxIsKDBgh8SKlzIsKHDhxAVJgAAOw==""")
>
> style = ttk.Style()
> style.element_create("RoundedFrame", "image", "frameBorder",
>                                   border=30, sticky="nsew")
> style.layout("RoundedFrame", [("RoundedFrame", {"sticky": "nsew"})])
>
> input_frame = ttk.Frame(root_frame,
>                         style = "RoundedFrame",
>                         padding = 15,
>                         width = 640,
>                         height = 180
>                         )
> input_frame.pack(padx=10, pady=10)
>
> This works, yes, but is annoyingly laggy on an older computer when I try
> to move the window around. I figure it's because the program has to keep
> redrawing the image border when dragged around, and is exacerbated by the
> fact that I have two of the imageborder frames in my application. How can I
> remedy this? I've tried using a hard-drawn image on a Canvas instead of the
> image border, but it's suboptimal because that prevents resizing the window.
>
>
> The other performance issue I've found is that when the logic is running,
> the app doesn't redraw. Ordinarily this would be acceptable, but as part of
> my program, it loads data from a website, and during the load, the window
> completely freezes up and doesn't respond until the download is done; as I
> understand it, tkinter doesn't redraw until it is forced to by .update() or
> control is given back to the mainloop. How can I force a more frequent
> redraw rate?
> --
> http://mail.python.org/mailman/listinfo/python-list
>



-- 
Best Regards,
David Hutto
*CEO:* *http://www.hitwebdevelopment.com*

[toc] | [prev] | [next] | [standalone]


#50771

FromDavid Hutto <dwightdhutto@gmail.com>
Date2013-07-16 21:34 -0400
Message-ID<mailman.4793.1374024892.3114.python-list@python.org>
In reply to#50766

[Multipart message — attachments visible in raw view] — view raw

On Tue, Jul 16, 2013 at 9:32 PM, David Hutto <dwightdhutto@gmail.com> wrote:

> I've had a similar problem with a tkinter/3D app. right now I'm looking
> toward Blender, and the Python API, but there is also wxpython, and the
> usual python's library gtk.
>
> There is also matplotlib with the ion window. but, I, personally, am going
> to go with Blender, and Python API, with maybe a few other imports, and if
> ctypes...includes if I remember C correctly without reference at this time
> the usages of returned data type values
> for you to utilize.
>
>
> But for the plainer answer I'd go with wxpython if you decide not to use a
> different library, and for a GDK, Blend
>
>
> On Tue, Jul 16, 2013 at 8:57 PM, <fronagzen@gmail.com> wrote:
>
>> Hm. So I've written a GUI in tkinter. I've found two performance issues,
>> I was hoping someone could point me in the right direction.
>>
>> Firstly, I'm using an image as a border, namely:
>>
>> from tkinter import *
>> from tkinter import ttk
>>
>> root_frame = Tk()
>> root_frame.configure(background = 'black')
>>
>> img1 = PhotoImage("frameBorder", data="""
>>        R0lGODlhQABAAMIHAAAAABkfLTMrMzMrZjNVZjNVmUFch////ywAAAAAQABAAAAD9A
>>        i63P4wykmrvTjrzbu/hlGMZGmeaBp2QmgIQSzPdG3fbShk+u3/wFkONAgaj7aBoWIo
>>        Ip9P5aQFrSJfkpd1C2xluWDfEhIKm2mrh/bM9qrZ8MDYYYiz54263Yxn6PdgfQt/gF
>>        uCCoSFVYcAiYpPjI6PR5GTVpWWUJiZV2SckJ6flKGiQZulP6eoN6qrNa2uM7CxMbO0
>>        trG4rrqrvKi+pcCiwp/EnMaZyJbKk8yPzorQhdKA1HuRMLQ0bnSSuYyN2mhZ2eLcD1
>>
>>  TicjtZ3sPgfu7J8A0EBOWfQxg5a4/87BtcCBxIsKDBgh8SKlzIsKHDhxAVJgAAOw==""")
>>
>> style = ttk.Style()
>> style.element_create("RoundedFrame", "image", "frameBorder",
>>                                   border=30, sticky="nsew")
>> style.layout("RoundedFrame", [("RoundedFrame", {"sticky": "nsew"})])
>>
>> input_frame = ttk.Frame(root_frame,
>>                         style = "RoundedFrame",
>>                         padding = 15,
>>                         width = 640,
>>                         height = 180
>>                         )
>> input_frame.pack(padx=10, pady=10)
>>
>> This works, yes, but is annoyingly laggy on an older computer when I try
>> to move the window around. I figure it's because the program has to keep
>> redrawing the image border when dragged around, and is exacerbated by the
>> fact that I have two of the imageborder frames in my application. How can I
>> remedy this? I've tried using a hard-drawn image on a Canvas instead of the
>> image border, but it's suboptimal because that prevents resizing the window.
>>
>>
>> The other performance issue I've found is that when the logic is running,
>> the app doesn't redraw. Ordinarily this would be acceptable, but as part of
>> my program, it loads data from a website, and during the load, the window
>> completely freezes up and doesn't respond until the download is done; as I
>> understand it, tkinter doesn't redraw until it is forced to by .update() or
>> control is given back to the mainloop. How can I force a more frequent
>> redraw rate?
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
>
> I've had a similar problem with a tkinter/3D app. right now I'm looking
> toward Blender, and the Python API, but there is also wxpython, and the
> usual python's library gtk.
>
> There is also matplotlib with the ion window. but, I, personally, am going
> to go with Blender, and Python API, with maybe a few other imports, and if
> ctypes...includes if I remember C correctly without reference at this time
> the usages of returned data type values
> for you to utilize.
>
>
> But for the plainer answer I'd go with wxpython if you decide not to use a
> different library, and for a GDK, Blender.
>



-- 
Best Regards,
David Hutto
*CEO:* *http://www.hitwebdevelopment.com*

[toc] | [prev] | [next] | [standalone]


#50772

FromDave Angel <davea@davea.name>
Date2013-07-16 21:40 -0400
Message-ID<mailman.4794.1374025243.3114.python-list@python.org>
In reply to#50766
On 07/16/2013 08:57 PM, fronagzen@gmail.com wrote:
> Hm. So I've written a GUI in tkinter. I've found two performance issues, I was hoping someone could point me in the right direction.
>
> Firstly, I'm using an image as a border, namely:

     <SNIP>
>
> This works, yes, but is annoyingly laggy on an older computer when I try to move the window around. I figure it's because the program has to keep redrawing the image border when dragged around, and is exacerbated by the fact that I have two of the imageborder frames in my application. How can I remedy this? I've tried using a hard-drawn image on a Canvas instead of the image border, but it's suboptimal because that prevents resizing the window.
>

This part I can't help with, as I'm not that familiar with tkinter in 
particular.  If I had to guess an approach, I'd tell you to create an 
object that represents the scaled border image, and then when it moves, 
you just reblit it.  And if/when the scale changes, you then recreate 
the object at the new scale.  Most of the time you won't be scaling.

But what that means in tkinter calls, I don't know and don't have time 
tonight to figure out.

>
> The other performance issue I've found is that when the logic is running, the app doesn't redraw. Ordinarily this would be acceptable, but as part of my program, it loads data from a website, and during the load, the window completely freezes up and doesn't respond until the download is done; as I understand it, tkinter doesn't redraw until it is forced to by .update() or control is given back to the mainloop. How can I force a more frequent redraw rate?
>

Tkinter, like every other GUI I know of, is event driven.  You're not 
intended to do "logic is running" kinds of events.  Break up larger 
problems into little tasks, and daisy chain them, returning to the event 
loop after each little piece.

A second approach that works with some GUI's is to fire up the event 
loop at periodic intervals in your long function;  get it to do a few 
other events and then return to you.  This isn't recommended usually 
because it can get very messy.  And it may not even be possible in tkinter.

Third approach is to start another thread to do the "logic is running." 
  Make sure that thread never calls any GUI stuff, but just updates 
values that can be seen by the main thread and its GUI stuff.  When 
you're done, post a message to the GUI to tell it to redraw whichever 
parts are now changed.


-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50773

Fromfronagzen@gmail.com
Date2013-07-16 18:51 -0700
Message-ID<17c2ef71-ee2d-4229-9731-e0d54a0997cb@googlegroups.com>
In reply to#50772
On Wednesday, July 17, 2013 9:40:15 AM UTC+8, Dave Angel wrote:
> On 07/16/2013 08:57 PM, fronagzen@gmail.com wrote:
> 
> > Hm. So I've written a GUI in tkinter. I've found two performance issues, I was hoping someone could point me in the right direction.
> 
> >
> 
> > Firstly, I'm using an image as a border, namely:
> 
> 
> 
>      <SNIP>
> 
> >
> 
> > This works, yes, but is annoyingly laggy on an older computer when I try to move the window around. I figure it's because the program has to keep redrawing the image border when dragged around, and is exacerbated by the fact that I have two of the imageborder frames in my application. How can I remedy this? I've tried using a hard-drawn image on a Canvas instead of the image border, but it's suboptimal because that prevents resizing the window.
> 
> >
> 
> 
> 
> This part I can't help with, as I'm not that familiar with tkinter in 
> 
> particular.  If I had to guess an approach, I'd tell you to create an 
> 
> object that represents the scaled border image, and then when it moves, 
> 
> you just reblit it.  And if/when the scale changes, you then recreate 
> 
> the object at the new scale.  Most of the time you won't be scaling.
> 
> 
> 
> But what that means in tkinter calls, I don't know and don't have time 
> 
> tonight to figure out.
> 
> 
> 
> >
> 
> > The other performance issue I've found is that when the logic is running, the app doesn't redraw. Ordinarily this would be acceptable, but as part of my program, it loads data from a website, and during the load, the window completely freezes up and doesn't respond until the download is done; as I understand it, tkinter doesn't redraw until it is forced to by .update() or control is given back to the mainloop. How can I force a more frequent redraw rate?
> 
> >
> 
> 
> 
> Tkinter, like every other GUI I know of, is event driven.  You're not 
> 
> intended to do "logic is running" kinds of events.  Break up larger 
> 
> problems into little tasks, and daisy chain them, returning to the event 
> 
> loop after each little piece.
> 
> 
> 
> A second approach that works with some GUI's is to fire up the event 
> 
> loop at periodic intervals in your long function;  get it to do a few 
> 
> other events and then return to you.  This isn't recommended usually 
> 
> because it can get very messy.  And it may not even be possible in tkinter.
> 
> 
> 
> Third approach is to start another thread to do the "logic is running." 
> 
>   Make sure that thread never calls any GUI stuff, but just updates 
> 
> values that can be seen by the main thread and its GUI stuff.  When 
> 
> you're done, post a message to the GUI to tell it to redraw whichever 
> 
> parts are now changed.
> 
> 
> 
> 
> 
> -- 
> 
> DaveA

Thanks for the responses.

Yeah, I understand that tkinter isn't really designed for 'logic is running' style issues, but I do need to load that data, and sometimes, that can take a while. I am in fact experimenting with threading another process to update the window, yes.

[toc] | [prev] | [next] | [standalone]


#50774

FromDave Angel <davea@davea.name>
Date2013-07-16 22:21 -0400
Message-ID<mailman.4795.1374027719.3114.python-list@python.org>
In reply to#50773
On 07/16/2013 09:51 PM, fronagzen@gmail.com wrote:

If you are going to use googlegroups, then at least bypass its worst 
bugs, like double-spacing everything it quotes.
      http://wiki.python.org/moin/GoogleGroupsPython

>
> Yeah, I understand that tkinter isn't really designed for 'logic is running' style issues, but I do need to load that data, and sometimes, that can take a while. I am in fact experimenting
 >  with threading another process to update the window, yes.
         ---------         -------    -----------------
>

Those three words/phrases strike a real discord.

Multithreading is not the same as multiprocessing.  And you probably 
don't ever want to update a window with a different thread than the one 
that created it.  Not that it can't be done, at least in some languages, 
but that it's real rat-hole of problems.

The extra thread or process (with different problems to each) should be 
doing the "logic is running" but NOT the gui.



-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50775

Fromfronagzen@gmail.com
Date2013-07-16 20:04 -0700
Message-ID<a3e5a3bc-248b-4f87-b161-596c6fe77fba@googlegroups.com>
In reply to#50774
Noted on the quoting thing.

Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.

And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.

[toc] | [prev] | [next] | [standalone]


#50783

FromDave Angel <davea@davea.name>
Date2013-07-17 06:07 -0400
Message-ID<mailman.4799.1374055664.3114.python-list@python.org>
In reply to#50775
On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> Noted on the quoting thing.
>
> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
>
> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
>

update() is to be used when it's too awkward to return to mainloop.  In 
my second approach, you would periodically call it inside the processing 
loop.  But unless tkinter is unique among GUI's, it's unsafe to do that 
in any thread besides the GUI thread.



-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50784

Fromfronagzen@gmail.com
Date2013-07-17 04:08 -0700
Message-ID<ca48edea-c24a-430d-9ab6-0e4bed8ceee5@googlegroups.com>
In reply to#50783
On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> 
> > Noted on the quoting thing.
> 
> >
> 
> > Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
> 
> >
> 
> > And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
> 
> >
> 
> 
> 
> update() is to be used when it's too awkward to return to mainloop.  In 
> 
> my second approach, you would periodically call it inside the processing 
> 
> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that 
> 
> in any thread besides the GUI thread.
> 
> 
> 
> 
> 
> 
> 
> -- 
> 
> DaveA

Ok. Well, what I'm currently doing, based on advice from this thread, is to create a new thread that handles the downloading, as well as updating a variable for text display on the GUI, and in the main thread, just after the thread is created, a while loop that updates the GUI while the thread is running.

[toc] | [prev] | [next] | [standalone]


#50809

FromMichael Torrie <torriem@gmail.com>
Date2013-07-17 16:53 -0600
Message-ID<mailman.4817.1374101739.3114.python-list@python.org>
In reply to#50784
On 07/17/2013 05:08 AM, fronagzen@gmail.com wrote:
> Ok. Well, what I'm currently doing, based on advice from this thread,
> is to create a new thread that handles the downloading, as well as
> updating a variable for text display on the GUI, and in the main
> thread, just after the thread is created, a while loop that updates
> the GUI while the thread is running.

Not sure what you mean by "while loop."  In an event-driven paradigm,
one technique would be to set a timeout event that fires every so many
ms.  Then in the event callback, you update the widget according to the
new value of the variable.  At least this is how i'd do it in Qt or GTK.

[toc] | [prev] | [next] | [standalone]


#50785

Fromfronagzen@gmail.com
Date2013-07-17 04:10 -0700
Message-ID<ca274116-be7a-4eda-8e96-a47dd80966c1@googlegroups.com>
In reply to#50783
On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> 
> > Noted on the quoting thing.
> > Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
> > And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
> 
> update() is to be used when it's too awkward to return to mainloop.  In 
> my second approach, you would periodically call it inside the processing 
> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that 
> in any thread besides the GUI thread.
> 
> -- 
> 
> DaveA

Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.

[toc] | [prev] | [next] | [standalone]


#50787

FromDave Angel <davea@davea.name>
Date2013-07-17 07:42 -0400
Message-ID<mailman.4801.1374061383.3114.python-list@python.org>
In reply to#50785
On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
>>
>>> Noted on the quoting thing.
>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
>>
>> update() is to be used when it's too awkward to return to mainloop.  In
>> my second approach, you would periodically call it inside the processing
>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
>> in any thread besides the GUI thread.
>>
>> --
>>
>> DaveA
>
> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
>

I can't figure out what you're really doing, since each message from you 
says something different.  You don't need a separate while loop, since 
that's exactly what app.mainloop() is.

-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50789

Fromfronagzen@gmail.com
Date2013-07-17 06:18 -0700
Message-ID<f564a889-99f0-4e9c-841f-830356743252@googlegroups.com>
In reply to#50787
On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
> > On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
> >> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> >>> Noted on the quoting thing.
> >>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
> >>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
> >> update() is to be used when it's too awkward to return to mainloop.  In
> >> my second approach, you would periodically call it inside the processing
> >> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
> >> in any thread besides the GUI thread.
> >> DaveA
> > Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
> I can't figure out what you're really doing, since each message from you 
> says something different.  You don't need a separate while loop, since 
> that's exactly what app.mainloop() is.
> -- 
> 
> DaveA

Hm. My apologies for not being very clear. What I'm doing is this:

        self.loader_thread = Thread(target=self.loadpages,
                                    name="loader_thread")
        self.loader_thread.start()
        while self.loader_thread.isAlive():
            self.root_window.update()
            sleep(0.05)

Where loadpages is a function defined elsewhere.

[toc] | [prev] | [next] | [standalone]


#50796

FromDave Angel <davea@davea.name>
Date2013-07-17 13:38 -0400
Message-ID<mailman.4805.1374082807.3114.python-list@python.org>
In reply to#50789
On 07/17/2013 09:18 AM, fronagzen@gmail.com wrote:
> On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
>> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
>>> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
>>>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
>>>>> Noted on the quoting thing.
>>>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
>>>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
>>>> update() is to be used when it's too awkward to return to mainloop.  In
>>>> my second approach, you would periodically call it inside the processing
>>>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
>>>> in any thread besides the GUI thread.
>>>> DaveA
>>> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
>> I can't figure out what you're really doing, since each message from you
>> says something different.  You don't need a separate while loop, since
>> that's exactly what app.mainloop() is.
>> --
>>
>> DaveA
>
> Hm. My apologies for not being very clear. What I'm doing is this:
>
>          self.loader_thread = Thread(target=self.loadpages,
>                                      name="loader_thread")
>          self.loader_thread.start()
>          while self.loader_thread.isAlive():
>              self.root_window.update()
>              sleep(0.05)
>
> Where loadpages is a function defined elsewhere.
>

Presumably this fragment is from a method of some class you've written. 
  Is it an event handler, or is this happening before you finish setting 
up the GUI?  Somewhere at top-level, you're supposed to fall into a call 
to mainloop(), which doesn't return till the user cancels the app.



-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50812

Fromfronagzen@gmail.com
Date2013-07-17 17:44 -0700
Message-ID<78c6218b-2da8-41a0-9eb3-5432093b3f6b@googlegroups.com>
In reply to#50796
On Thursday, July 18, 2013 1:38:34 AM UTC+8, Dave Angel wrote:
> On 07/17/2013 09:18 AM, fronagzen@gmail.com wrote:
> > On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
> >> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
> >>> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
> >>>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> >>>>> Noted on the quoting thing.
> >>>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
> >>>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
> >>>> update() is to be used when it's too awkward to return to mainloop.  In
> >>>> my second approach, you would periodically call it inside the processing
> >>>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
> >>>> in any thread besides the GUI thread.
> >>>> DaveA
> 
> >>> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
> >> I can't figure out what you're really doing, since each message from you
> >> says something different.  You don't need a separate while loop, since
> >> that's exactly what app.mainloop() is.
> >> --
> >>
> >> DaveA
> >
> > Hm. My apologies for not being very clear. What I'm doing is this:
> >          self.loader_thread = Thread(target=self.loadpages,
> >                                      name="loader_thread")
> >          self.loader_thread.start()
> >          while self.loader_thread.isAlive():
> >              self.root_window.update()
> >              sleep(0.05)
> > Where loadpages is a function defined elsewhere.
> 
> Presumably this fragment is from a method of some class you've written. 
>   Is it an event handler, or is this happening before you finish setting 
> up the GUI?  Somewhere at top-level, you're supposed to fall into a call 
> to mainloop(), which doesn't return till the user cancels the app.
> -- 
> 
> DaveA
This is, indeed, an event handler from a class for my GUI. My entire GUI is a bit large, so I'll not copy the entire thing here, but it roughly goes:

class GUI(object):
    def __init__(self):
        [stuff]

    def init_button(self):
        self.execute = ttk.Button(self.input_frame, text='Tally',
                                  command=self.execute_now)
        self.execute.grid(column=1, row=2, sticky=(N, S, E, W), columnspan=4)

    def execute_now(self):
        [stuff]
        self.loader_thread = Thread(target=self.loadpages,
                                    name="loader_thread")
        self.loader_thread.start()
        while self.loader_thread.isAlive():
            self.root_window.update()
            sleep(0.05)
        [morestuff]

if __name__ == "__main__":
    APP = GUI()
    APP.root_window.mainloop()

[toc] | [prev] | [next] | [standalone]


#50813

FromDave Angel <davea@davea.name>
Date2013-07-17 21:07 -0400
Message-ID<mailman.4818.1374109662.3114.python-list@python.org>
In reply to#50812
On 07/17/2013 08:44 PM, fronagzen@gmail.com wrote:
> On Thursday, July 18, 2013 1:38:34 AM UTC+8, Dave Angel wrote:
>> On 07/17/2013 09:18 AM, fronagzen@gmail.com wrote:
>>> On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
>>>> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
>>>>> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
>>>>>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
>>>>>>> Noted on the quoting thing.
>>>>>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
>>>>>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
>>>>>> update() is to be used when it's too awkward to return to mainloop.  In
>>>>>> my second approach, you would periodically call it inside the processing
>>>>>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
>>>>>> in any thread besides the GUI thread.
>>>>>> DaveA
>>
>>>>> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
>>>> I can't figure out what you're really doing, since each message from you
>>>> says something different.  You don't need a separate while loop, since
>>>> that's exactly what app.mainloop() is.
>>>> --
>>>>
>>>> DaveA
>>>
>>> Hm. My apologies for not being very clear. What I'm doing is this:
>>>           self.loader_thread = Thread(target=self.loadpages,
>>>                                       name="loader_thread")
>>>           self.loader_thread.start()
>>>           while self.loader_thread.isAlive():
>>>               self.root_window.update()
>>>               sleep(0.05)
>>> Where loadpages is a function defined elsewhere.
>>
>> Presumably this fragment is from a method of some class you've written.
>>    Is it an event handler, or is this happening before you finish setting
>> up the GUI?  Somewhere at top-level, you're supposed to fall into a call
>> to mainloop(), which doesn't return till the user cancels the app.
>> --
>>
>> DaveA
> This is, indeed, an event handler from a class for my GUI. My entire GUI is a bit large, so I'll not copy the entire thing here, but it roughly goes:
>
> class GUI(object):
>      def __init__(self):
>          [stuff]
>
>      def init_button(self):
>          self.execute = ttk.Button(self.input_frame, text='Tally',
>                                    command=self.execute_now)
>          self.execute.grid(column=1, row=2, sticky=(N, S, E, W), columnspan=4)
>
>      def execute_now(self):
>          [stuff]
>          self.loader_thread = Thread(target=self.loadpages,
>                                      name="loader_thread")
>          self.loader_thread.start()

            self.root_window.after(100, self.test_thread)
            return

>          while self.loader_thread.isAlive():
>              self.root_window.update()

Nope - don't use that.  Instead, post an event on the queue, and return 
to the mainloop() from whence we came.

         def test_thread(self):
            if self.loader_thread.isAlive():
                self.root_window.after(100, self.test_thread)
                return
            [morestuff]

>              sleep(0.05)
>          [morestuff]
>
> if __name__ == "__main__":
>      APP = GUI()
>      APP.root_window.mainloop()
>

I probably don't have it quite right, but hopefully you'll get the idea. 
  self.test_thread() is now a new event that will get repeatedly 
invoked, to do the check on the thread status.  It returns rapidly 
unless the condition has occurred.

There are other things that should be done, like blocking the specific 
events that would create duplicate threads.

-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50824

Fromfronagzen@gmail.com
Date2013-07-17 21:38 -0700
Message-ID<5dd8666d-abc1-41e7-9050-a9b95fbe1e16@googlegroups.com>
In reply to#50813
On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
> On 07/17/2013 08:44 PM, fronagzen@gmail.com wrote:
> > On Thursday, July 18, 2013 1:38:34 AM UTC+8, Dave Angel wrote:
> >> On 07/17/2013 09:18 AM, fronagzen@gmail.com wrote:
> >>> On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
> >>>> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
> >>>>> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
> >>>>>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
> >>>>>>> Noted on the quoting thing.
> >>>>>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
> >>>>>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
> >>>>>> update() is to be used when it's too awkward to return to mainloop.  In
> >>>>>> my second approach, you would periodically call it inside the processing
> >>>>>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
> >>>>>> in any thread besides the GUI thread.
> >>>>>> DaveA
> >>>>> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
> >>>> I can't figure out what you're really doing, since each message from you
> >>>> says something different.  You don't need a separate while loop, since
> >>>> that's exactly what app.mainloop() is.
> >>>> --
> >>>> DaveA
> 
> >>> Hm. My apologies for not being very clear. What I'm doing is this:
> >>>           self.loader_thread = Thread(target=self.loadpages,
> >>>                                       name="loader_thread")
> >>>           self.loader_thread.start()
> >>>           while self.loader_thread.isAlive():
> >>>               self.root_window.update()
> >>>               sleep(0.05)
> >>> Where loadpages is a function defined elsewhere.
>
> >> Presumably this fragment is from a method of some class you've written.
> >>    Is it an event handler, or is this happening before you finish setting
> >> up the GUI?  Somewhere at top-level, you're supposed to fall into a call
> >> to mainloop(), which doesn't return till the user cancels the app.
> >> --
> >> DaveA
> 
> > This is, indeed, an event handler from a class for my GUI. My entire GUI is a bit large, so I'll not copy the entire thing here, but it roughly goes:
> > class GUI(object):
> >      def __init__(self):
> >          [stuff]
> >      def init_button(self):
> >          self.execute = ttk.Button(self.input_frame, text='Tally',
> >                                    command=self.execute_now)
> >          self.execute.grid(column=1, row=2, sticky=(N, S, E, W), columnspan=4)
> >      def execute_now(self):
> >          [stuff]
> >          self.loader_thread = Thread(target=self.loadpages,
> >                                      name="loader_thread")
> >          self.loader_thread.start()
>             self.root_window.after(100, self.test_thread)
>             return
> >          while self.loader_thread.isAlive():
> >              self.root_window.update()
> Nope - don't use that.  Instead, post an event on the queue, and return 
> to the mainloop() from whence we came.
>          def test_thread(self):
>             if self.loader_thread.isAlive():
>                 self.root_window.after(100, self.test_thread)
>                 return
>             [morestuff]
> >              sleep(0.05)
> >          [morestuff]
> > if __name__ == "__main__":
> >      APP = GUI()
> >      APP.root_window.mainloop()
> I probably don't have it quite right, but hopefully you'll get the idea. 
>   self.test_thread() is now a new event that will get repeatedly 
> invoked, to do the check on the thread status.  It returns rapidly 
> unless the condition has occurred.
> There are other things that should be done, like blocking the specific 
> events that would create duplicate threads.
> -- 
> 
> DaveA

I see, though it should be noted that your method doesn't actually block the rest of the even handler code from running, had to fiddle with it a bit to get that to work. May I ask what exactly is the rationale behind implementing it like this, though?

[toc] | [prev] | [next] | [standalone]


#50826

FromDave Angel <davea@davea.name>
Date2013-07-18 00:52 -0400
Message-ID<mailman.4822.1374123162.3114.python-list@python.org>
In reply to#50824
On 07/18/2013 12:38 AM, fronagzen@gmail.com wrote:
> On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
>> On 07/17/2013 08:44 PM, fronagzen@gmail.com wrote:
>>> On Thursday, July 18, 2013 1:38:34 AM UTC+8, Dave Angel wrote:
>>>> On 07/17/2013 09:18 AM, fronagzen@gmail.com wrote:
>>>>> On Wednesday, July 17, 2013 7:42:45 PM UTC+8, Dave Angel wrote:
>>>>>> On 07/17/2013 07:10 AM, fronagzen@gmail.com wrote:
>>>>>>> On Wednesday, July 17, 2013 6:07:22 PM UTC+8, Dave Angel wrote:
>>>>>>>> On 07/16/2013 11:04 PM, fronagzen@gmail.com wrote:
>>>>>>>>> Noted on the quoting thing.
>>>>>>>>> Regarding the threading, well, first, I'm not so much a programmer as someone who knows a bit of how to program.
>>>>>>>>> And it seems that the only way to update a tkinter window is to use the .update() method, which is what I was experimenting with. Start up a new thread that just loops the .update() with a 1ms sleep until the download is done. It seems to work, actually.
>>>>>>>> update() is to be used when it's too awkward to return to mainloop.  In
>>>>>>>> my second approach, you would periodically call it inside the processing
>>>>>>>> loop.  But unless tkinter is unique among GUI's, it's unsafe to do that
>>>>>>>> in any thread besides the GUI thread.
>>>>>>>> DaveA
>>>>>>> Yes, based on advice from this thread, I'm doing that. From my main thread, I create a thread that handles the download while updating a variable that the mainloop displays as a text output, and in that mainloop, I have a while loop that updates the GUI until the downloading is done.
>>>>>> I can't figure out what you're really doing, since each message from you
>>>>>> says something different.  You don't need a separate while loop, since
>>>>>> that's exactly what app.mainloop() is.
>>>>>> --
>>>>>> DaveA
>>
>>>>> Hm. My apologies for not being very clear. What I'm doing is this:
>>>>>            self.loader_thread = Thread(target=self.loadpages,
>>>>>                                        name="loader_thread")
>>>>>            self.loader_thread.start()
>>>>>            while self.loader_thread.isAlive():
>>>>>                self.root_window.update()
>>>>>                sleep(0.05)
>>>>> Where loadpages is a function defined elsewhere.
>>
>>>> Presumably this fragment is from a method of some class you've written.
>>>>     Is it an event handler, or is this happening before you finish setting
>>>> up the GUI?  Somewhere at top-level, you're supposed to fall into a call
>>>> to mainloop(), which doesn't return till the user cancels the app.
>>>> --
>>>> DaveA
>>
>>> This is, indeed, an event handler from a class for my GUI. My entire GUI is a bit large, so I'll not copy the entire thing here, but it roughly goes:
>>> class GUI(object):
>>>       def __init__(self):
>>>           [stuff]
>>>       def init_button(self):
>>>           self.execute = ttk.Button(self.input_frame, text='Tally',
>>>                                     command=self.execute_now)
>>>           self.execute.grid(column=1, row=2, sticky=(N, S, E, W), columnspan=4)
>>>       def execute_now(self):
>>>           [stuff]
>>>           self.loader_thread = Thread(target=self.loadpages,
>>>                                       name="loader_thread")
>>>           self.loader_thread.start()
>>              self.root_window.after(100, self.test_thread)
>>              return
>>>           while self.loader_thread.isAlive():
>>>               self.root_window.update()
>> Nope - don't use that.  Instead, post an event on the queue, and return
>> to the mainloop() from whence we came.
>>           def test_thread(self):
>>              if self.loader_thread.isAlive():
>>                  self.root_window.after(100, self.test_thread)
>>                  return
>>              [morestuff]
>>>               sleep(0.05)
>>>           [morestuff]
>>> if __name__ == "__main__":
>>>       APP = GUI()
>>>       APP.root_window.mainloop()
>> I probably don't have it quite right, but hopefully you'll get the idea.
>>    self.test_thread() is now a new event that will get repeatedly
>> invoked, to do the check on the thread status.  It returns rapidly
>> unless the condition has occurred.
>> There are other things that should be done, like blocking the specific
>> events that would create duplicate threads.
>> --
>>
>> DaveA
>
> I see, though it should be noted that your method doesn't actually block the rest of the even handler code from running, had to fiddle with it a bit to get that to work. May I ask what exactly is the rationale behind implementing it like this, though?
>

Simply because your goal is normally to have other events working.  For 
example, a user might resize the window while you're doing your network 
stuff.  This way all events are fired from the one place, and you can 
uniformly decide which ones to block for the special cases.  And you 
don't wind up with the GUI's internal code in a knot.  As I said at the 
beginning, I'm not that familiar with tkinter, but the same principles 
apply to all of them.

Sometimes these variations are equivalent, and sometimes there are 
problems.  For example, you might be testing on Linux, and then later 
when you try it on Windows, suddenly things don't work.  The closer you 
can conform to the standard way of using the GUI manager, the less 
likely you are to come up with strange problems, now or later.

-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#50840

FromChristian Gollwitzer <auriocus@gmx.de>
Date2013-07-18 09:20 +0200
Message-ID<ks84kp$cr8$1@dont-email.me>
In reply to#50824
Am 18.07.13 06:38, schrieb fronagzen@gmail.com:
> On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
>> Nope - don't use that.  Instead, post an event on the queue, and return
>> to the mainloop() from whence we came.
>>           def test_thread(self):
>>              if self.loader_thread.isAlive():
>>                  self.root_window.after(100, self.test_thread)
>>                  return
>

> I see, though it should be noted that your method doesn't actually
> block the rest of the even handler code from running, had to fiddle
> with it a bit to get that to work. May I ask what exactly is the
> rationale behind implementing it like this, though?
>

Exactly this is the goal of it. Event handlers are supposed to run in as 
short time as possible, and should never block. The reason is that you 
want the events to be processed in the order they come in, such that he 
user can still move the window, resize it, iconify/maximize etc.

That said, the code still looks odd to me. I have used the Tk with 
multithreading in the past, but directly from Tcl, and not from Python.
The basic idea is to have the background thread (which does the work) 
signal the main thread about its status, i.e. in the worker thread:

for i in range(50):
   some_odd_computation()
   signal('progress', i)

signal('finished')

and in the main thread you bind() to the events fired from the worker 
thread. That way you don't run any periodic polling.

I fear that Tkinter has a shortcoming which does not allow this pattern 
to be implemented. The tricky thing is to implement this signal() 
function, which must post an event to another thread. From the C level, 
there is Tcl_ThreadQueueEvent() which does this. It arranges for a C 
function to be run from the event loop of another thread. From Tcl, 
thread::send does this. To use it from Tkinter, it would be necessary to 
create a Tcl interpreter in the worker thread *without* loading Tk.

Some day I should dive into the innards of Tkinter to see if this is 
possible. Then you could implement signal() simply by

def signal(sig, data=''):
	tclinterp.eval('thread::send -async $mainthread {event generate . 
<<%s>> -data {%s}'%sig%data)

and in the main thread bind() to the virtual events.

	Christian

[toc] | [prev] | [next] | [standalone]


#50848

Fromfronagzen@gmail.com
Date2013-07-18 02:10 -0700
Message-ID<8bd3de87-3f7d-48a7-ab1c-b55700c9178d@googlegroups.com>
In reply to#50840
On Thursday, July 18, 2013 3:20:28 PM UTC+8, Christian Gollwitzer wrote:
> Am 18.07.13 06:38, schrieb fronagzen@gmail.com:
> > On Thursday, July 18, 2013 9:07:24 AM UTC+8, Dave Angel wrote:
> >> Nope - don't use that.  Instead, post an event on the queue, and return
> >> to the mainloop() from whence we came.
> >>           def test_thread(self):
> >>              if self.loader_thread.isAlive():
> >>                  self.root_window.after(100, self.test_thread)
> >>                  return
> > I see, though it should be noted that your method doesn't actually
> > block the rest of the even handler code from running, had to fiddle
> > with it a bit to get that to work. May I ask what exactly is the
> > rationale behind implementing it like this, though?
> Exactly this is the goal of it. Event handlers are supposed to run in as 
> short time as possible, and should never block. The reason is that you 
> want the events to be processed in the order they come in, such that he 
> user can still move the window, resize it, iconify/maximize etc.
> That said, the code still looks odd to me. I have used the Tk with 
> multithreading in the past, but directly from Tcl, and not from Python.
> The basic idea is to have the background thread (which does the work) 
> signal the main thread about its status, i.e. in the worker thread:
> for i in range(50):
>    some_odd_computation()
>    signal('progress', i)
> signal('finished')
> and in the main thread you bind() to the events fired from the worker 
> thread. That way you don't run any periodic polling.
> I fear that Tkinter has a shortcoming which does not allow this pattern 
> to be implemented. The tricky thing is to implement this signal() 
> function, which must post an event to another thread. From the C level, 
> there is Tcl_ThreadQueueEvent() which does this. It arranges for a C 
> function to be run from the event loop of another thread. From Tcl, 
> thread::send does this. To use it from Tkinter, it would be necessary to 
> create a Tcl interpreter in the worker thread *without* loading Tk.
> Some day I should dive into the innards of Tkinter to see if this is 
> possible. Then you could implement signal() simply by
> def signal(sig, data=''):
> 	tclinterp.eval('thread::send -async $mainthread {event generate . 
> <<%s>> -data {%s}'%sig%data)
> and in the main thread bind() to the virtual events.
> 	Christian
Ah, I see. Thank you for your help!

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.python


csiph-web