自学内容网 自学内容网

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)!