Tkinter中光标(cursor)功能的补充介绍
在python的tkinter包,即用于给程序做GUI的包里,有一个功能叫cursor,就是可以让鼠标的光标在界面上有条件地改变形状。Tkinter Cursors已经对这个功能进行了基本介绍,也给出了一个例子,让光标在一定范围内变形。
import tkinter as tk
root = tk.Tk()
root.geometry("300x300")
def change_cursor(event):
if event.x in range(100, 300):
root.config(cursor="watch")
else:
root.config(cursor="")
root.bind("<Motion>", change_cursor)
root.mainloop()
以上是链接的网页中的代码。在该程序中,当光标位置的横向坐标(x)在100像素~300像素之间时,光标为watch形状,否则为正常的箭头形状。
所以在这里我按照该思路设计一个程序,把该功能实现得更漂亮。
程序代码如下:
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Cursor')
root.geometry("300x300")
outsideCursorFrame = LabelFrame(root, text='outside cursor')
insideCursorFrame = LabelFrame(root, text='inside cursor')
outsideCursorFrame.grid(row=0, column=0)
insideCursorFrame.grid(row=0, column=1)
cursorOutsideVar = StringVar(value="arrow")
cursorOutside1 = Radiobutton(outsideCursorFrame, text="Normal", value="arrow", variable=cursorOutsideVar)
cursorOutside2 = Radiobutton(outsideCursorFrame, text="Hand", value='hand1', variable=cursorOutsideVar)
cursorOutside3 = Radiobutton(outsideCursorFrame, text="Pencil", value="pencil", variable=cursorOutsideVar)
cursorOutside1.pack()
cursorOutside2.pack()
cursorOutside3.pack()
cursorInsideVar = StringVar(value="arrow")
cursorInside1 = Radiobutton(insideCursorFrame, text="Normal", value="arrow", variable=cursorInsideVar)
cursorInside2 = Radiobutton(insideCursorFrame, text="Hand", value='hand1', variable=cursorInsideVar)
cursorInside3 = Radiobutton(insideCursorFrame, text="Pencil", value="pencil", variable=cursorInsideVar)
cursorInside1.pack()
cursorInside2.pack()
cursorInside3.pack()
def change_cursor(e):
if e.x in range(100,200):
root.config(cursor=cursorInsideVar.get())
else:
root.config(cursor=cursorOutsideVar.get())
root.bind('<Motion>', change_cursor)
root.mainloop()
在该程序中我设计了两个框架(LabelFrame),每一个框架里都有三个单选按钮(RadioButton),用于选择内部和外部的光标形状。cursorInsideVar表明光标的横坐标在100~200之间的光标形状,而cursorOutsideVar表明光标的横坐标在该范围以外的光标形状。
结果如下:
一、问题分析
在这里可以发现,当光标在窗口的Frame以外时,遵守选择的两种光标形状。但当光标在Frame上时,光标形状却一直都是范围外的“Hand”,即使其位置在整个窗口的横坐标确属100~200像素范围内。
为了分析原因,我们在函数change_cursor(e)的开始处,加一句日志打印句,打印光标的坐标值:
print("the cursor's position is %s"%str(e))
此时随着光标移动,光标的坐标被打印。从打印的值可看到,光标在Frame上时,即便其横坐标位置已经超过100,但系统检测到的位置只有20左右。这是因为该位置检测的结果是相对于Frame的位置,而不是在整个窗口中的位置。
二、解决方式
那么,如何判断光标是否是在Frame中,还是在Frame外但仍在窗口内呢?这里有一篇文章介绍了一种方法:tkinter中当鼠标移动到指定控件时,进行文字提醒的控件和点击鼠标右键时,弹出菜单栏的控件的设计与实现_python tkinter在界面指定区域点击鼠标时显示菜单-CSDN博客
注意这篇文章中,有这两句代码:
widget.bind('<Enter>', enter)
widget.bind('<Leave>', leave)
这两句代码,就是让光标刚好进入和离开某个组件时,触发函数。
这里,我用这个方法,实现当光标在Frame上时,显示另一种光标形状的逻辑。
新代码如下:
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Cursor')
root.geometry("300x300")
outsideCursorFrame = LabelFrame(root, text='outside cursor')
insideCursorFrame = LabelFrame(root, text='inside cursor')
outsideCursorFrame.grid(row=0, column=0)
insideCursorFrame.grid(row=0, column=1)
cursorOutsideVar = StringVar(value="arrow")
cursorOutside1 = Radiobutton(outsideCursorFrame, text="Normal", value="arrow", variable=cursorOutsideVar)
cursorOutside2 = Radiobutton(outsideCursorFrame, text="Hand", value='hand1', variable=cursorOutsideVar)
cursorOutside3 = Radiobutton(outsideCursorFrame, text="Pencil", value="pencil", variable=cursorOutsideVar)
cursorOutside1.pack()
cursorOutside2.pack()
cursorOutside3.pack()
cursorInsideVar = StringVar(value="arrow")
cursorInside1 = Radiobutton(insideCursorFrame, text="Normal", value="arrow", variable=cursorInsideVar)
cursorInside2 = Radiobutton(insideCursorFrame, text="Hand", value='hand1', variable=cursorInsideVar)
cursorInside3 = Radiobutton(insideCursorFrame, text="Pencil", value="pencil", variable=cursorInsideVar)
cursorInside1.pack()
cursorInside2.pack()
cursorInside3.pack()
InFrame1 = BooleanVar(value=False)
InFrame2 = BooleanVar(value=False)
def enter1(e):
InFrame1.set(True)
def enter2(e):
InFrame2.set(True)
def leave1(e):
InFrame1.set(False)
def leave2(e):
InFrame2.set(False)
outsideCursorFrame.bind('<Enter>', enter1)
outsideCursorFrame.bind('<Leave>', leave1)
insideCursorFrame.bind('<Enter>', enter2)
insideCursorFrame.bind('<Leave>', leave2)
def change_cursor(e):
if InFrame1.get() or InFrame2.get():
root.config(cursor='circle')
elif e.x in range(100,200):
root.config(cursor=cursorInsideVar.get())
else:
root.config(cursor=cursorOutsideVar.get())
root.bind('<Motion>', change_cursor)
root.mainloop()
在这里,如果光标在两个Frame中的任何一个,就显示circle形状的光标。
结果如下:
原文地址:https://blog.csdn.net/weixin_41640959/article/details/143823010
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!