From: 7stud -- Date: 2008-04-14T19:22:40+09:00 Subject: Re: ruby/tk and loop delay Hidetoshi NAGAI wrote: > From: Ed Redman > Subject: ruby/tk and loop delay > Date: Mon, 14 Apr 2008 08:20:05 +0900 > Message-ID: <4ywMj.10891$682.6491@edtnps90> >> I have a Tk_button(shuffle) that shuffles the cards and places them on a >> canvas.The shuffle works fine but I would like to have a slight delay >> between between each card being displayed on the canvas. Below is the >> shuffle buttons command. I would like to delay the loop each time so >> their is a slight delay. I have tried putting Tk.after(time) >> { part around the loop} but it just delays the shuffle and is not >> visible. Not each card being displayed. I need a little direction >> on implementing such a loop > > On Tk, re-drawing widgets occurs when idle-tasks. > The callback operation for button click is only one event. > Tk doesn't call idle loop before finishing of the callback. > If you want to force idle loop, please call "Tk.update" or > "Tk.update_idletasks" at when you need. > > However, I don't recommend such long term operation on one callback. > Such callbacks may block callbacks for other events. > That is, you may get bad response of GUI. > > I think that Thread + TkTimer is better for your case. > ---------------------------------------------------------- > proc exchange{|nr, nm| > newhash[nr], newhasn[nm] = newhash[nm], newhasn[nr] > place[nr].image newhash[nr] > place[nm].image newhash[nm] > # Tk.update ### if you need > } > > # 100ms interval, 52 times > tm = TkTimer.new(100, 52){ exchange.call(rand(56), rand(56)) } > > shuffle.command{ > shuffle.state(:disable) > Thread.new{ tm.start.wait; shuffle.state(:normal) } > } > ---------------------------------------------------------- > On this code, the callback for clicking 'shuffle' button > will finish in short term. > And GUI can treat the next event soon, although 'shuffle' button > is disabled. > The thread created on the callback starts and waits the timer, > and enable 'shuffle' button when the timer is finished. > > # I should add the method to entry a proc executed at end of a timer. > # Then, a thread isn't required for such operataion. Isn't after() supposed to accomplish the same thing? Why doesn't after() work in my code in my previous post? I tried my own threading solution, but it didn't work--there was no delay when drawing lines to a Canvas widget: require 'tk' def do_press(e) widget = e.widget x = e.x y = e.y 10.times do |i| x += 10 TkcLine.new(widget, x, y, x+100, y+100) t = Thread.new do sleep(2) widget.update end end end root = TkRoot.new {title 'Canvas Test'} canvas = TkCanvas.new(root) canvas.pack canvas.bind('ButtonRelease-1', lambda {|e| do_press(e)}) Tk.mainloop -- Posted via http://www.ruby-forum.com/.