Prev: ctypes: delay conversion from c_char_p to string
Next: Hi, friends. I wanna ask if there is a function which is ableto take a list as argument and then return its top-k maximums?
From: Rotwang on 22 Apr 2010 11:55 James Mills wrote: > On Wed, Apr 21, 2010 at 8:45 PM, Rotwang <sg552(a)hotmail.co.uk> wrote: >> >> [...] >> >>From reading the documentation myself (pydoc)... > > It would seem your only option is to make a thread > out of this (not my preferred way - I was hoping it was > possible to poll the Tk event system...). Thanks, I don't know anything about threading at the moment but I'll look into it. BTW, another problem: whenever I call a widget.quit() method, the widget in question crashes. IDLE carries on working but the widget window stays there, not responding, and if I tell my OS to kill it then IDLE restarts. Is this a bug? I'm using Windows 7 and Python 2.6.4.
From: Rotwang on 22 Apr 2010 11:59 eb303 wrote: > On Apr 21, 12:45 pm, Rotwang <sg...(a)hotmail.co.uk> wrote: >> >> [...] >> > > Just run your program directly, either from a terminal or a DOS > console or by double-clicking on it in a file manager if the proper > file associations have been defined (they are by default on Windows). Thanks for the suggestion, but I think in this case that would defeat the point of the draw method (which is there so I can see what something looks like in between using the interpreter interactively to mess about with it).
From: Rotwang on 23 Apr 2010 07:58 eb303 wrote: > On Apr 22, 5:55 pm, Rotwang <sg...(a)hotmail.co.uk> wrote: >> >> [...] >> > > From my experience, mixing Tkinter with threads is a bad idea. As most > GUI toolkits, it really doesn't like to be manipulated from different > threads, so you might end up getting weird problems or even crashes. > > By the way, did you try to remove the line out.mainloop() from your > 'draw' function? I didn't. How do I get Python to display the draw window, other than by using mainloop()? > This is the line that blocks the IDLE GUI, since it > initiates a secondary event loop that will only exit when you do a > out.quit(), so that might be a solution. > >> BTW, another problem: whenever I call a widget.quit() method, the widget >> in question crashes. IDLE carries on working but the widget window stays >> there, not responding, and if I tell my OS to kill it then IDLE >> restarts. Is this a bug? I'm using Windows 7 and Python 2.6.4. > > The 'quit' method just exits the mainloop. It doesn't destroy the > widget. So if your application doesn't actually exit, the widget will > just stay there. If you want to destroy the it too, you have to call > explicitely widget.destroy(). That worked like a charm, thanks! Here's another problem I've run into today: I've just added a bit of code so that it's possible to resize the draw window and the contents will be resized automatically. The method now looks something like this: out = Tkinter.Tk() slave = Tkinter.Canvas(out, width = wh[0], height = wh[1]) slave.grid() # I put the canvas widget inside a tk widget instead of just # using the former because I want keypresses to do things, and # it doesn't seem to be possible to bind keyboard events to a # canvas # draw something slave.pack() def resize(b): wh[:] = [b.width, b.height] slave.config(width = wh[0], height = wh[1]) # resize the contents of slave out.bind('<Configure>', resize) out.mainloop() The trouble is, when I call the method the window it spawns slowly grows larger, until I move or resize it myself by grabbing one of the edges; after this everything works as intended. If I add the line "print wh" after "wh[:] = [b.width, b.height]", the output looks like this (the default value of wh is [640,480]: [644, 484] [648, 488] [648, 488] [648, 488] [652, 492] [652, 492] [652, 492] [656, 496] [656, 496] [656, 496] [660, 500] etc. My only guess as to why this is happening is that Tkinter is resizing out to be 4 pixels wider and taller than slave, and the line "slave.config(...)" consequently leads to resize being called again. But this doesn't explain why it stops happening when I resize the window intentionally, nor why the window apparently only gets larger every third time resize is called. The problem goes away if I replace "wh[:] = [b.width, b.height]" with wh[:] = [b.width - 4, b.height - 4] but this seems like a rather ad-hoc and ugly solution, and I'd rather understand what's going on. Can anyone help?
From: eb303 on 23 Apr 2010 09:40 On Apr 23, 1:58 pm, Rotwang <sg...(a)hotmail.co.uk> wrote: > eb303 wrote: > > On Apr 22, 5:55 pm, Rotwang <sg...(a)hotmail.co.uk> wrote: > > >> [...] > > > From my experience, mixing Tkinter with threads is a bad idea. As most > > GUI toolkits, it really doesn't like to be manipulated from different > > threads, so you might end up getting weird problems or even crashes. > > > By the way, did you try to remove the line out.mainloop() from your > > 'draw' function? > > I didn't. How do I get Python to display the draw window, other than by > using mainloop()? Well, mainloop doesn't actually display anything. It's just the event loop for tk. So since you run your program within IDLE, there is already one running. What does it do if you delete the mainloop() line? Doesn't your window appear at all? > > This is the line that blocks the IDLE GUI, since it > > initiates a secondary event loop that will only exit when you do a > > out.quit(), so that might be a solution. > > >> BTW, another problem: whenever I call a widget.quit() method, the widget > >> in question crashes. IDLE carries on working but the widget window stays > >> there, not responding, and if I tell my OS to kill it then IDLE > >> restarts. Is this a bug? I'm using Windows 7 and Python 2.6.4. > > > The 'quit' method just exits the mainloop. It doesn't destroy the > > widget. So if your application doesn't actually exit, the widget will > > just stay there. If you want to destroy the it too, you have to call > > explicitely widget.destroy(). > > That worked like a charm, thanks! > > Here's another problem I've run into today: I've just added a bit of > code so that it's possible to resize the draw window and the contents > will be resized automatically. The method now looks something like this: > > out = Tkinter.Tk() > slave = Tkinter.Canvas(out, width = wh[0], height = wh[1]) > slave.grid() > # I put the canvas widget inside a tk widget instead of just > # using the former because I want keypresses to do things, and > # it doesn't seem to be possible to bind keyboard events to a > # canvas > # draw something > slave.pack() (Hope this line is a mistake: gridding *and* packing slave will probably result in tk thinking for ages how it should display it in its parent ) > > def resize(b): > wh[:] = [b.width, b.height] > slave.config(width = wh[0], height = wh[1]) > # resize the contents of slave > You don't need at all to resize the slave explicitely. You should do the following: - Tell 'out' that its first row and first column should resize themselves when the window is resized by doing: out.grid_rowconfigure(1, weight=1) out.grid_columnconfigure(1, weight=1) - Make sure slave is actually put in the cell in first row and column, and that all its sides will stick to the cell borders: slave.grid(row=1, column=1, sticky='nswe') If you do that, the slave.config in the resize function shouldn't be needed anymore. > out.bind('<Configure>', resize) If using the grid options, better do a slave.bind( ) here, which will call the binding when the canvas is resized, which is obvioulsy when you want to update its contents. > out.mainloop() > > The trouble is, when I call the method the window it spawns slowly grows > larger, until I move or resize it myself by grabbing one of the edges; > after this everything works as intended. If I add the line "print wh" > after "wh[:] = [b.width, b.height]", the output looks like this (the > default value of wh is [640,480]: > > [644, 484] > [648, 488] > [648, 488] > [648, 488] > [652, 492] > [652, 492] > [652, 492] > [656, 496] > [656, 496] > [656, 496] > [660, 500] > etc. > > My only guess as to why this is happening is that Tkinter is resizing > out to be 4 pixels wider and taller than slave, and the line > "slave.config(...)" consequently leads to resize being called again. But > this doesn't explain why it stops happening when I resize the window > intentionally, nor why the window apparently only gets larger every > third time resize is called. The problem goes away if I replace "wh[:] = > [b.width, b.height]" with > > wh[:] = [b.width - 4, b.height - 4] > > but this seems like a rather ad-hoc and ugly solution, and I'd rather > understand what's going on. Can anyone help? You get the size for the outer window and apply it to the canvas inside it. Since the canvas has a border which is 2 pixels wide by default, this resizes the window containing it to take this border into account. So your binding is called again, and so on But using the options to grid described above, there should never be any need to resize the canvas explicitely. HTH - Eric -
From: Rotwang on 23 Apr 2010 15:44
eb303 wrote: > On Apr 23, 1:58 pm, Rotwang <sg...(a)hotmail.co.uk> wrote: >> >> [...] >> >> I didn't. How do I get Python to display the draw window, other than by >> using mainloop()? > > Well, mainloop doesn't actually display anything. It's just the event > loop for tk. So since you run your program within IDLE, there is > already one running. What does it do if you delete the mainloop() > line? Doesn't your window appear at all? No. >> [...] >> >> Here's another problem I've run into today: I've just added a bit of >> code so that it's possible to resize the draw window and the contents >> will be resized automatically. The method now looks something like this: >> >> out = Tkinter.Tk() >> slave = Tkinter.Canvas(out, width = wh[0], height = wh[1]) >> slave.grid() >> # I put the canvas widget inside a tk widget instead of just >> # using the former because I want keypresses to do things, and >> # it doesn't seem to be possible to bind keyboard events to a >> # canvas >> # draw something >> slave.pack() > > (Hope this line is a mistake: gridding *and* packing slave will > probably result in tk thinking for ages how it should display it in > its parent�) Not a mistake so much as a symptom of my inept, cargo-cult approach to programming. Needless to say you're correct that it shouldn't be there, though taking it out doesn't give a noticeable improvement in performance (perhaps because the canvas is the only thing there so there's no conflict). >> def resize(b): >> wh[:] = [b.width, b.height] >> slave.config(width = wh[0], height = wh[1]) >> # resize the contents of slave >> > > You don't need at all to resize the slave explicitely. You should do > the following: > - Tell 'out' that its first row and first column should resize > themselves when the window is resized by doing: > out.grid_rowconfigure(1, weight=1) > out.grid_columnconfigure(1, weight=1) > - Make sure slave is actually put in the cell in first row and column, > and that all its sides will stick to the cell borders: > slave.grid(row=1, column=1, sticky='nswe') > > If you do that, the slave.config in the resize function shouldn't be > needed anymore. Indeed! That works great. >> out.bind('<Configure>', resize) > > If using the grid options, better do a slave.bind(�) here, which will > call the binding when the canvas is resized, which is obvioulsy when > you want to update its contents. Right, though before you suggested making the sides of the canvas sticky, resizing the window didn't reconfigure slave. >> [...] >> > You get the size for the outer window and apply it to the canvas > inside it. Since the canvas has a border which is 2 pixels wide by > default, this resizes the window containing it to take this border > into account. So your binding is called again, and so on� But using > the options to grid described above, there should never be any need to > resize the canvas explicitely. Thanks very much for your help. |