Is it possible to trigger a function when the mouse stop moving?
For example, I have a scale, and I want to trigger a function when I still holding a button and stop dragging. I used 'ButtonRelease-1' but I had to release a mouse button to be able to trigger a function, it's not what I want.
Hope you guys can help me.
Thank you in advance.
No, you can't bind to "mouse stopped moving". However, you can bind to <B1-Motion>, and with each callback set a timer to run in the future. If the mouse hasn't moved within that time the function will be called. Within that function you could use event_generate to generate a custom <<MouseStopped>> event. If the mouse moves before the timer expires, reset the timer.
You get the exactly the same effect as if you bound to the mouse not moving.
Related
First scene with first mouse press
That first onMousePress function makes the background change.
Second scene with second mouse press
This second onMousePress function is planned to make the barrels disappear but it just kind of replaces the first onMousePress and makes it so that's the only one that works. Also ignore the 2 and the fact that it actually makes a rectangle, the 2 made it not work so I can click on the future tp and the rect is for testing purposes
You can set flag of first click and some small wait time. If the event is triggered second time it is double click, otherwise it is single click when time runs out. You need to set wait time in parallel thread or use something like timer. And don't forget to reset your flag everytime.
I am programming in Python and I have a few questions that I can't find the answer to anywhere (please read all questions as they build up to my last question):
1.What Does the .mainloop() really do? I read the all the answers in Stack Overflow, I also checked the documentations explanation.
2.Does the .mainloop() always have to be at the end of a turtle program?
3.I have used .mainloop() before. My question is, if I have the f.f.g code:
import turtle
screen = turtle.Screen()
alex = turtle.Turtle()
tess = turtle.Turtle()
def yes(x, y):
alex.onclick(yes)
print("Hello World")
tess.onclick(yes)
turtle.mainloop()
Why does alex get an action event when the function yes() is run? I know it does because the function is called, but what is actually happening? I mean the statement turtle.mainloop() is run before tess is clicked, and tess's action event is waited for in the event loop, so how does alex's event get in the event loop since its statement is run after turtle.mainloop() is run?
1.What Does the .mainloop() really do?
Turtle's mainloop() calls tkinter's mainloop() which calls Tk's Tk_MainLoop() which is surprisingly simple:
void
Tk_MainLoop(void)
{
while (Tk_GetNumMainWindows() > 0) {
Tcl_DoOneEvent(0);
}
}
It handles events, one at a time, in an infinite loop while there are any main windows open. The events processed include keyboard input, button clicks, window reshapes, file I/O, network activity, timers, display refreshes and any other registered callbacks.
An excellent, one page description of mainloop can be found in the introduction to Chapter 15. Anatomy of the MainLoop in the O'Reily book Mastering Perl/Tk by Steve Lidie and Nancy Walsh. Although it's a Perl/Tk book, the information regarding mainloop is valid for Python as well. You can find this material on-line but I won't include a link here as I don't know which, if any, of the online copies are legitimately posted. But you've enough information to search for it.
2.Does the .mainloop() always have to be at the end of a turtle program?
No. It should be part of a well designed program but isn't required. Most standalone programs will include it (or something that calls it like .done() or .exitonclick()) as the graphics window will close on completion without it. But some situations, eg. IDLE perhaps, don't need it to keep the graphics visible. A common error I find in beginner's turtle programs is creating an infinite loop of turtle activity ahead of calling mainloop() and then wondering why various events don't fire.
If you plan to have Tk process keyboard, mouse and timer events for you, then calling .mainloop() is how you get that started. In most Python/Tk programs, it's the last statement but there can be other code after it that gets executed when all the Tk windows have all closed down.
We can think of turtle programming as writing plug-in code for Tk's main loop. After we set things up, subsequent activity will be done by call back functions we've registered via on*() functions.
3.I have used mainloop() before. My question is, if I have the f.f.g code: ... Why does alex get an action event when the function
yes() is run
When your program runs, turtles Alex and Tess are piled atop each other in the center of the window. When you click on this turtle stack, the event goes to Tess, who's both on top and has an event handler. In her event handler, Tess installs an event handler on Alex. The act of installing an event handler on Alex causes Alex to move in front of Tess, rising to the top of the stack. From now on, when you click on the turtle stack, Alex handles the events and they no longer reach Tess. We can see this clearly if we give them different colors and different event handlers:
import turtle
alex = turtle.Turtle(shape="turtle")
alex.color("blue")
tess = turtle.Turtle(shape="turtle")
tess.color("pink")
def tess_handler(x, y):
alex.onclick(alex_handler)
print("Tess clicked")
def alex_handler(x, y):
print("Alex clicked")
tess.onclick(tess_handler)
turtle.mainloop()
Clicking on the turtle stack produces:
> python3 test.py
Tess clicked
Alex clicked
Alex clicked
Alex clicked
Alex clicked
Alex clicked
Alex clicked
You could move Alex and Tess to different locations in the window and then click on them to confirm that Alex doesn't start receiving events until the first time Tess is clicked.
So mainloop() is an infinite loop that basically blocks the execution of your code at a certain point. You call it once (and only once).
so lets say:
while true:
circle.draw()
sumden.mainloop()
print "circle is being drawn"
time.sleep(0.1)
You will never see the output and print statement because there is no loop.
Using time.sleep in my wxPython code just after re-positioning a bitmapbutton caused my button to go totally blank. Just a white space was left in the region where the button should have been. Can any one please explain the reason and suggest any solution? Here's my code:
import wx
import time
class gui(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'New Window',pos=(0,0),size=wx.DisplaySize())
panel=wx.Panel(self)
self.SetBackGroundColour('green')
self.pic=wx.BitmapButton(self,-1,wx.Image("Candle.jpg",wx.BITMAP_TYPE_ANY).ConvertToBitmap(),pos=(700,300))
self.Bind(wx.EVT_BUTTON,self.position,self.pic)
def positon(self,event):
self.pic.Hide()
self.pic=wx.BitmapButton(self,-1,wx.Image("Candle.jpg",wx.BITMAP_TYPE_ANY).ConvertToBitmap(),pos=(700,300))
time.sleep(2)
self.pic.Hide()
if __name__=='__main__':
app=wx.PySimpleApp()
frame=gui(None,-1)
frame.Show()
app.MainLoop()
Well there's no wonder your button goes blank, you've pretty much programmed it to do so.
self.pic.Hide() => hides the button
self.pic=wx.BitmapButton(self,-1,wx.Image("Candle.jpg",wx.BITMAP_TYPE_ANY).ConvertToBitmap(),pos=(700,300)) => displays the button once again
time.sleep(2) => takes a brake for 2 seconds
self.pic.Hide() => hides the button again
The conclusion is, your button won't show up. So I don't see what's the problem, as it does exactly what you programmed it to.
time.sleep() blocks wx's mainloop and makes the GUI unresponsive for however long you've told it to sleep. There are several alternatives. You can use a wx.Timer or use threads (or similar). I think using a Timer makes more sense in your use case though.
well it depends, was time sleep used in the button's event ?, cause I believe if it was it's because of that. The button waits for the event it triggered to end so it would go back to its initial state.
sleep is blocking, so execution is stuck in your position method for two seconds and is unable to return to the MainLoop to process other events, like painting your changes to the screen. After the two seconds are up the image is hidden, but was never drawn.
To get the effect you want you'll have to start a timer, and bind the timer to a handler which can show the StaticBitmap again.
By the way you can also call Show again rather than creating a new control, and it's parent should also be the panel, not the frame.
I want to detect pressing the "snapshot" button on the top of a webcam in linux. The button has this entry in /dev:
/dev/input/by-id/usb-PixArt_Imaging_Inc._USB2.0_UVC_VGA-event-if00
I am using the "rel" wrapper, at the moment, because it handles exceptions better. Before the following code executes, self.s.cam_btn is assigned the /dev entry for the button.
rel.override()
rel.init()
rel.read(self.s.cam_btn, self.snap)
rel.dispatch()
self.snap() is the callback. It captures a screen shot from mplayer and feeds the image to an OCR program. Everything mostly works until the callback returns. Here is the problem:
If self.snap() returns nothing, the program stops and will not service any more button events. If self.snap() returns 1, the program continues servicing the same button event in an infinite loop, rather than waiting for a new event. Documentation for pyevent is a little sparse so any help gratefully received.
Clinton
Never used pyevent, but would try rescheduling the event at the end of the handler:
def snap(self):
# ... code ...
rel.read(self.s.cam_btn, self.snap)
return False
I am writing a python app using Tkinter for buttons and graphics and having trouble getting a timer working, what I need is a sample app that has three buttons and a label.
[start timer] [stop timer] [quit]
When I press the start button a function allows the label to count up from zero every 5 seconds, the stop button stops the timer and the quit button quits the app.
I need to be able to press stop timer and quit at any time, and the time.sleep(5) function locks everything up so I can't use that.
currently i'm using threading.timer(5,do_count_function) and getting nowhere !
I'm a vb.net programmer, so python is a bit new to me, but hey, i'm trying.
Check the .after method of your Tk() object. This allows you to use Tk's timer to fire events within the gui's own loop by giving it a length of time and a callback method.