使用鼠标指针移动Python Turtle

3

我一直在尝试保存手写文本的图像,以用于我的手写文本识别项目。为此,我使用了Python turtle。我想通过移动鼠标来改变海龟(处于笔划位置)在画布上的坐标,并通过按住左键移动鼠标时让它写字(处于笔下位置)。但我无法实现这个功能。以下是我的代码。

import tkinter
import turtle

sc = tkinter.Tk()
sc.geometry("1000x1000+100+100")

fr4 = tkinter.Frame(sc, height=500, width=600, bd=4, bg="light green", takefocus="", relief=tkinter.SUNKEN)

fr4.grid(row=2, column=2, sticky=(tkinter.N, tkinter.E, tkinter.W, tkinter.S))

# Canvas
canvas = tkinter.Canvas(fr4, width=1920, height=1080)
canvas.pack()

# Turtle
turtle1 = turtle.RawTurtle(canvas)
turtle1.color("black")
turtle1.shape("turtle")
turtle1.speed(100000)

def drag_handler(x, y):
    turtle1.ondrag(None)  # disable event inside event handler
    turtle1.goto(x, y)
    turtle1.ondrag(drag_handler)  # reenable event on event handler exit

turtle1.ondrag(drag_handler)

sc.mainloop()

1
请比“我无法实现这个”更清楚地说明问题的本质。具体来说,您想要发生什么?如果有错误,请提供完整的回溯信息。请参阅如何创建一个最小、完整和可验证的示例 - undefined
如果你想用鼠标拖动乌龟,你的代码是有效的。 - undefined
1
@eyllanesc,请重新阅读他的描述。他希望标题始终跟踪鼠标,只有在按下左键时才留下轨迹。提供的代码可以拖动和绘制,但无法在鼠标按钮未按下时进行跟踪。 - undefined
1个回答

3
下面是我根据您所描述的实现方式所做的实现。我把它从Tk转移到了turtle中。但是,我引入了低级别的Tk调用来实现缺失的turtle onmove() 事件处理程序。一旦这个处理程序就位,就变成了管理运动、点击、释放和拖动的问题。请确保首先点击窗口的标题栏使其处于活动状态:
from turtle import Turtle, Screen

MOVING, DRAGGING = range(2)  # states

def move_handler(x, y):
    if state != MOVING:  # ignore stray events
        return

    onmove(screen, None)  # avoid overlapping events
    yertle.penup()
    yertle.setheading(yertle.towards(x, y))
    yertle.goto(x, y)
    onmove(screen, move_handler)

def click_handler(x, y):
    global state

    yertle.onclick(None)  # disable until release
    onmove(screen, None)  # disable competing handler

    yertle.onrelease(release_handler)  # watch for release event
    yertle.ondrag(drag_handler)  # motion is now dragging until release

    state = DRAGGING

def release_handler(x, y):
    global state

    yertle.onrelease(None)  # disable until click
    yertle.ondrag(None)  # disable competing handler

    yertle.onclick(click_handler)  # watch for click event
    onmove(screen, move_handler)  # dragging is now motion until click

    state = MOVING

def drag_handler(x, y):
    if state != DRAGGING:  # ignore stray events
        return

    yertle.ondrag(None)  # disable event inside event handler
    yertle.pendown()
    yertle.setheading(yertle.towards(x, y))
    yertle.goto(x, y)
    yertle.ondrag(drag_handler)  # reenable event on event handler exit

def onmove(self, fun, add=None):
    """
    Bind fun to mouse-motion event on screen.

    Arguments:
    self -- the singular screen instance
    fun  -- a function with two arguments, the coordinates
        of the mouse cursor on the canvas.

    Example:

    >>> onmove(turtle.Screen(), lambda x, y: print(x, y))
    >>> # Subsequently moving the cursor on the screen will
    >>> # print the cursor position to the console
    >>> screen.onmove(None)
    """

    if fun is None:
        self.cv.unbind('<Motion>')
    else:
        def eventfun(event):
            fun(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale)
        self.cv.bind('<Motion>', eventfun, add)

screen = Screen()
screen.setup(500, 600)
screen.screensize(1920, 1080)

yertle = Turtle('turtle')
yertle.speed('fastest')

state = MOVING

# Initially we track the turtle's motion and left button clicks
onmove(screen, move_handler)  # a la screen.onmove(move_handler)
yertle.onclick(click_handler)  # a click will turn motion into drag

screen.mainloop()
onmove() 事件的实现来自于我在 Python turtle中查找光标当前位置 的答案中,如果您访问时觉得有帮助,请随手点个赞。 (就像您的 drag_handler() 是从我在 Turtle freehand drawing 的答案中得到的一样,如果您还没有点赞,请随意点赞。)

这个实现在我鼠标移动缓慢时处于笔下位置时运行得很完美,但当它更加杂乱(像某人的书写)时,就会出现问题。有时候,海龟不会留下轨迹,有时候它只会在拖动的初始和最终位置之间画一条直线。 - undefined
1
@TheBeginner,我对代码进行了仪器化,并发现它生成了意外的动作事件,所以我添加了一个显式状态变量来过滤掉这些杂散的事件。现在绘制得更加清晰了 - 如果你需要完美的话,可以考虑使用信号量和锁定机制。 - undefined
非常好的解决方案!谢谢你。 - undefined
不知道# a la screen.onmove(move_handler)应该是什么意思。 - undefined
@AnnZen,我无法理解你的评论。onmove()代码以方法的形式编写,因此尽管我们通过onmove(screen, move_handler)将其作为函数调用,但它可以安装为screen的方法,并在子类中通过screen.onmove(move_handler)调用,或通过其他一些技巧来调用。 - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接