I am trying to use graphics.py to write a user graphics interface. The problem is that how can I capture the right click event? It seems that the function getMouse() could just returns where the mouse was left-clicked as a Point object.
from graphics import *
def main():
win = GraphWin("My Circle", 100, 100)
c = Circle(Point(50,50), 10)
c.draw(win)
win.getMouse() # pause for click in window
win.close()
main()
I want to know how can I capture the right-click event in the window, thanks.
I would recommend you try TkInter for a python GUI.
Here is an example that detects a right click:
from Tkinter import *
def showPosEvent(event):
print 'Widget=%s X=%s Y=%s' % (event.widget, event.x, event.y)
def onRightClick(event):
print 'Got right mouse button click:',
showPosEvent(event)
tkroot = Tk()
labelfont = ('courier', 20, 'bold')
widget = Label(tkroot, text='Hello bind world')
widget.config(bg='red', font=labelfont)
widget.config(height=5, width=20)
widget.pack(expand=YES, fill=BOTH)
widget.bind('<Button-3>', onRightClick)
widget.focus()
tkroot.title('Click Me')
tkroot.mainloop()
Related
I want to draw my turtle using arrow keys. And there's an option to change turtle pensize.
Here's my code:
from tkinter import *
from turtle import *
def ask():
someinputs = numinput('Test', 'Input size:', default=1, minval=0, maxval=999)
pensize(someinputs)
root = Tk()
Label(root, text='Settings:\n').pack()
Button(root, text='Pensize', command=ask).pack()
Label(root, text=' ').pack()
def up():
#anything here
fd(100)
def down():
#anything here
bk(100)
def left():
#anything here
lt(90)
fd(100)
def right():
#anything here
rt(90)
fd(100)
onkey(up, 'Up')
onkey(down, 'Down')
onkey(left, 'Left')
onkey(right, 'Right')
listen()
mainloop()
But after clicking the tkinter button to set the pensize, I can't use arrow keys to control anymore.
Can anyone help me, please? Also this doesn't work with turtle.textinput() too!
When you use the settings window, you take focus from the turtle window. The key events will only work when the turtle window has focus. Adapting this answer it is possible to get the underlying canvas and focus it by adding Screen().getcanvas().focus_force() to the end of ask:
def ask():
someinputs = numinput('Test', 'Input size:', default=1, minval=0, maxval=999)
pensize(someinputs)
Screen().getcanvas().focus_force()
Can you not add the listen method at the end of the ask function?
def ask():
someinputs = numinput('Test', 'Input size:', default=1, minval=0, maxval=999)
pensize(someinputs)
listen()
I am making a GUI in Tkinter, python, which can be navigated using a mouse cursor but no buttons/keys.
I am trying to solve a current problem of having the mouse left click without anyone pressing the physical mouse button or a key on the keyboard. I would like to have the mouse auto click after 2 seconds of inactivity.
For example i hover over a button and wait two seconds then the button is pressed.
I would like to say i have tried everything but i cant find anything to try. I thought about using the .invoke() function with a timing loop but i cant get it to run while my gui is open. ill show my gui code. Maybe i am doing something wrong, but if i place the .invoke function after the win.mainloop then it wont even run untill i close the gui tk window.
win = Tk()
# get the dimensions of the primary screen
app = wx.App(False)
w, h = wx.GetDisplaySize()
geometry = "%dx%d" % (w,h)
win.geometry(geometry)
win.attributes('-fullscreen', True)
win.config(cursor="circle")
# get the grid image
bg = Image.open('grid_image.png')
img = bg.resize((w, h))
grid_img=ImageTk.PhotoImage(img)
image_label = Label(win, image=grid_img)
image_label.place(x=0, y=0, relwidth=1, relheight=1)
# print an image of a green circle
gw = int(w/26)
gh = int(h/15)
g_circle = Image.open('green_circle.png')
g_img = g_circle.resize((gw,gh))
g_circle_image=ImageTk.PhotoImage(g_img)
g_label = Label(win, image=g_circle_image)
g_label.place(x=w/8, y=h/8)
g_btn = Button(win, image=g_circle_image, command=win.destroy)
g_btn.place(x=(w/8), y=(h/8))
# print an image of a blue circle
bw = int(w/26)
bh = int(h/15)
b_circle = Image.open('circle.png')
b_img = b_circle.resize((bw,bh))
b_circle_image=ImageTk.PhotoImage(b_img)
b_label = Label(win, image=b_circle_image)
b_label.place(x=(w/8)*5, y=(h/8)*5)
b_btn = Button(win, image=b_circle_image, command=win.destroy)
b_btn.place(x=(w/8)*5, y=(h/8)*5)
win.mainloop()
Any help with solving this would be much appreciated.
As you already seem to be confirming the option with tk.Button().invoke() you can use tk.Button.bind('<Enter>', _onhover) to detect the mouse over your button and tk.Button.bind('<Leave>', _onleave)
Define two functions like that:
def _onhover(event):
global _current_button
button = event.widget
_current_button = button
button.after(2000, lambda b=button: _invocation(b))
def _onleave(event):
global _current_button
_current_button = None
def _invocation(button):
if _current_button is button:
button.invoke()
I want to add a hover feature on a Tkinter button where if the user hovers the mouse cursor then description text displays. I also want to add some delay for that description to appear so that it would not be intrusive.
I can try using the "<Enter>" and "<Leave>" binding of the button to a function and make some "Label" appear in some corner of the app. But this approach may not be the most elegant.
This can be done very easily with tkinter. By adding Enter and Leave events to whatever you want to add a tooltip to, we can easily show/hide whatever we want, wherever we want. In my example I use a stripped-down tk.Toplevel so we can have a simple fade animation, and the tooltip wont be confined to the root window.
#widgets.py
import tkinter as tk, tkinter.ttk as ttk
from typing import Union
Widget = Union[tk.Widget, ttk.Widget]
class ToolTip(tk.Toplevel):
#amount to adjust fade by on every animation frame
FADE_INC:float = .07
#amount of milliseconds to wait before next animation state
FADE_MS :int = 20
def __init__(self, master, **kwargs):
tk.Toplevel.__init__(self, master)
#make window invisible, on the top, and strip all window decorations/features
self.attributes('-alpha', 0, '-topmost', True)
self.overrideredirect(1)
#style and create label. you can override style with kwargs
style = dict(bd=2, relief='raised', font='courier 10 bold', bg='#FFFF99', anchor='w')
self.label = tk.Label(self, **{**style, **kwargs})
self.label.grid(row=0, column=0, sticky='w')
#used to determine if an opposing fade is already in progress
self.fout:bool = False
def bind(self, target:Widget, text:str, **kwargs):
#bind Enter(mouseOver) and Leave(mouseOut) events to the target of this tooltip
target.bind('<Enter>', lambda e: self.fadein(0, text, e))
target.bind('<Leave>', lambda e: self.fadeout(1-ToolTip.FADE_INC, e))
def fadein(self, alpha:float, text:str=None, event:tk.Event=None):
#if event and text then this call came from target
#~ we can consider this a "fresh/new" call
if event and text:
#if we are in the middle of fading out jump to end of fade
if self.fout:
self.attributes('-alpha', 0)
#indicate that we are fading in
self.fout = False
#assign text to label
self.label.configure(text=f'{text:^{len(text)+2}}')
#update so the proceeding geometry will be correct
self.update()
#x and y offsets
offset_x = event.widget.winfo_width()+2
offset_y = int((event.widget.winfo_height()-self.label.winfo_height())/2)
#get geometry
w = self.label.winfo_width()
h = self.label.winfo_height()
x = event.widget.winfo_rootx()+offset_x
y = event.widget.winfo_rooty()+offset_y
#apply geometry
self.geometry(f'{w}x{h}+{x}+{y}')
#if we aren't fading out, fade in
if not self.fout:
self.attributes('-alpha', alpha)
if alpha < 1:
self.after(ToolTip.FADE_MS, lambda: self.fadein(min(alpha+ToolTip.FADE_INC, 1)))
def fadeout(self, alpha:float, event:tk.Event=None):
#if event then this call came from target
#~ we can consider this a "fresh/new" call
if event:
#indicate that we are fading out
self.fout = True
#if we aren't fading in, fade out
if self.fout:
self.attributes('-alpha', alpha)
if alpha > 0:
self.after(ToolTip.FADE_MS, lambda: self.fadeout(max(alpha-ToolTip.FADE_INC, 0)))
#main.py ~ EXAMPLE USAGE OOP
import tkinter as tk
from widgets import ToolTip
class Root(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#instantiate ToolTip
tt = ToolTip(self)
#create first button and bind a tooltip to it
btn = tk.Button(self, text='hover')
btn.grid(column=0, row=0)
tt.bind(btn, 'first button is hovered')
#create second button and bind a tooltip to it
btn2 = tk.Button(self, text='hover2')
btn2.grid(column=1, row=0)
tt.bind(btn2, 'second button is hovered')
if __name__ == "__main__":
root = Root()
root.title("ToolTip Example")
root.mainloop()
#main.py ~ EXAMPLE USAGE PROCEDURAL
import tkinter as tk
from widgets import ToolTip
if __name__ == "__main__":
root = tk.Tk()
root.title("ToolTip Example")
#instantiate ToolTip
tt = ToolTip(root)
#create first button and bind a tooltip to it
btn = tk.Button(root, text='hover')
btn.grid(column=0, row=0)
tt.bind(btn, 'first button is hovered')
#create second button and bind a tooltip to it
btn2 = tk.Button(root, text='hover2')
btn2.grid(column=1, row=0)
tt.bind(btn2, 'second button is hovered')
root.mainloop()
Here is a small snippet using Pmw (python mega widgets) for the tool tips.
Firstly start by installing it:
pip install Pmw
Then here is a snippet to understand what Pmw can do:
from tkinter import *
import Pmw
root = Tk()
Pmw.initialise(root) #initializing it in the root window
l = Label(root,text='Random Text')
l.pack()
b = Button(root,text='Hover me')
b.pack()
tooltip_1 = Pmw.Balloon(root) #Calling the tooltip
tooltip_1.bind(b,'This is the hover Text\nHope you get an idea of whats going on here.') #binding it and assigning a text to it
root.mainloop()
Hope this gives you a better idea. Keep in mind that Pmw could create a mess while converting the py to an exe later(if you have any intentions to). There is a way around in tho.
Cheers
I was trying to create a program inside tkinter that draws different patterns based on user input. I want a 'clear' button on my window that can clear everything on the window. I tried 'turtle.clear" and 'turtle.reset', they work but they open a new turtle window which I dont want and also that I am using tut = turtle.RawTurtle(). What can I do to try to fix this problem?
I use the following sample code:
from tkinter import *
from turtle import *
root = Tk()
tut = None
def reset_button():
tut.reset()
tut.hideturtle()
def draw_again():
tut.speed('fastest')
tut.color('blue', 'yellow')
tut.begin_fill()
while True:
tut.forward(200)
tut.left(170)
if abs(tut.pos()) < 1:
break
tut.end_fill()
button1 = Button(text = 'Reset', command = reset_button)
button1.pack()
button2 = Button(text = 'Draw', command = draw_again)
button2.pack()
canvas_Main = Canvas(root, bg='#ffffff', width = 500, height = 500)
canvas_Main.pack()
tut = RawTurtle(canvas_Main)
tut.speed('fastest')
tut.color('red', 'yellow')
tut.begin_fill()
while True:
tut.forward(200)
tut.left(170)
if abs(tut.pos()) < 1:
break
tut.end_fill()
root.mainloop()
guys, I'm currently making Chess in Python using Tkinter and wanted to know how to detect if an image is clicked?
This code adds a click function to each image I have stored within a dictionary
def MouseClickOnEachPiece(self, rows, columns, event):
global AllPieces
while True:
for ThePieces in AllPieces:
if board[rows][columns] == ThePieces:
self.canvas.bind('<Button-1>', MakeMove)
elif board[rows][columns] != ThePieces:
continue
This code is used to make the move
def MakeMove(self, rows, columns, event):
global AllPieces
print("You have clicked at: ", event.x , event.y)
while True:
for i in AllPieces:
if #the image is clicked : # -- What would i use to check if the image is clicked?
canvas.move(i, #themove )
If possible, you can use a button and place an image on the button instead.
from tkinter import *
from tkinter import ttk
root = Tk()
button = ttk.Button(root)
button.pack()
theImage = PhotoImage(file = "source")
button.config(image = theImage)