【问题标题】:Why is the “root.after ()” method not stoppable?为什么“root.after()”方法无法停止?
【发布时间】:2020-05-31 00:41:09
【问题描述】:

我正在尝试使用方向按钮制作一个简单的工具路径程序。它可以工作,但有时释放按钮是无效的,乌龟停止点击“主页”按钮。否则它就像我没有释放按钮一样持续运行。

代码如下:

from tkinter import *
from turtle import RawTurtle, TurtleScreen

def showPos():
    monitor.delete('1.0', END)
    monitor.insert(END, "X: " + str(tool.ycor()) +" Z: " + str(tool.xcor()))

def goHome():
    tool.home()
    showPos()
    stop_move()

def goUp():
    tool.sety(tool.ycor() + 10)

def goDown():
    tool.sety(tool.ycor() - 10)

def goRight():
    tool.setx(tool.xcor() + 10)

def goLeft():
    tool.setx(tool.xcor() - 10)

def stop_move():
    global jobid
    root.after_cancel(jobid)

def move(direction):
    global jobid

    if direction == "-X":
        goDown()

    if direction == "+X":
        goUp()    

    if direction == "-Z":
        goLeft()

    if direction == "+Z":
        goRight()    

    jobid = root.after(10, move, direction)
    showPos()

jobid = None

root = Tk()
root.title("CNC Lathe")

canvas = Canvas(root, width=800, height=600)
canvas.pack()

screen = TurtleScreen(canvas)
screen.bgcolor("black")
screen.register_shape("wnmg.gif")

tool = RawTurtle(screen, shape="wnmg.gif")
tool.pencolor("white")

monitor = Text(root, height=1, width=16, font="Helvetica")
monitor.pack()

topFrame = Frame(root)
topFrame.pack()
middleFrame = Frame(root)
middleFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack()

for direction in ("-X", "+X", "-Z", "+Z"):
    if direction == "+X":
        button = Button(topFrame, text=direction)
        button.pack()

    if direction == "-X":
        button = Button(bottomFrame, text=direction)
        button.pack()

    if direction == "-Z":
        button = Button(middleFrame, text=direction)
        button.pack(side=LEFT)

    if direction == "+Z":
        button = Button(middleFrame, text=direction)
        button.pack(side=RIGHT)   

    button.bind('<ButtonPress-1>', lambda event, direction=direction: move(direction))
    button.bind('<ButtonRelease-1>', lambda event: stop_move())

Button(middleFrame, text="Home", command=goHome).pack()

root.mainloop()

我尝试在“root.after_cancel()”方法之后将变量“jobid”设置为“None”,但没有任何改变。有时这似乎没有检测到按钮的释放。有谁知道解决办法吗?

【问题讨论】:

  • “似乎没有检测到按钮的释放”:可以,但是您需要一个条件来停止进一步调用root.after(10, move, direction) .

标签: python python-3.x events button tkinter


【解决方案1】:

我试图让您的代码与您的jobid 模型一起工作,虽然我可以改进它,但缺陷最终浮出水面——我无法确切说明原因。您必须考虑到,在您的实施中,jobid 并不总是代表待处理的工作,它可能是已成功解雇的工作。

另一个需要考虑的问题是:

jobid = root.after(10, move, direction)

10ms 时间必须大于执行move() 方法所需的时间,加上反应时间。也就是说,如果您无法在不重复出现的情况下绘制最小尺寸的框(10 x 10),那么您这次需要再次增加。

下面是我使用简单的状态变量而不是作业 ID 对您的代码进行的返工(加上一些其他更改。)它似乎解决了问题:

from tkinter import *
from turtle import RawTurtle, TurtleScreen

def showPos():
    monitor.delete('1.0', END)
    monitor.insert(END, "X: " + str(tool.ycor()) + " Z: " + str(tool.xcor()))

def goHome():
    tool.home()
    showPos()

def goUp():
    tool.sety(tool.ycor() + 10)

def goDown():
    tool.sety(tool.ycor() - 10)

def goRight():
    tool.setx(tool.xcor() + 10)

def goLeft():
    tool.setx(tool.xcor() - 10)

pressing = False

def start_move(event):
    global pressing

    event.widget.unbind('<ButtonPress-1>')  # unbind event handler inside handler(s)

    pressing = True

    move(event)

def stop_move(event):
    global pressing

    pressing = False

    event.widget.bind('<ButtonPress-1>', start_move)

def move(event):
    if not pressing:
        return

    direction = event.widget['text']

    if direction == '-X':
        goDown()
    elif direction == '+X':
        goUp()    
    elif direction == '-Z':
        goLeft()
    elif direction == '+Z':
        goRight()    

    showPos()

    root.after(75, move, event)

root = Tk()
root.title("CNC Lathe")

canvas = Canvas(root, width=800, height=600)
canvas.pack()

screen = TurtleScreen(canvas)
screen.bgcolor('black')
# screen.register_shape("wnmg.gif")

# tool = RawTurtle(screen, shape="wnmg.gif")
tool = RawTurtle(screen, shape='turtle')
tool.pencolor('white')

monitor = Text(root, height=1, width=16, font='Helvetica')
monitor.pack()

topFrame = Frame(root)
topFrame.pack()
middleFrame = Frame(root)
middleFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack()

for direction in ('-X', '+X', '-Z', '+Z'):
    if direction == '+X':
        button = Button(topFrame, text=direction)
        button.pack()

    if direction == '-X':
        button = Button(bottomFrame, text=direction)
        button.pack()

    if direction == '-Z':
        button = Button(middleFrame, text=direction)
        button.pack(side=LEFT)

    if direction == '+Z':
        button = Button(middleFrame, text=direction)
        button.pack(side=RIGHT)   

    button.bind('<ButtonPress-1>', start_move)
    button.bind('<ButtonRelease-1>', stop_move)

Button(middleFrame, text="Home", command=goHome).pack()

root.mainloop()

我将光标更改为乌龟,因为我没有您的 "wnmg.gif" 图像可使用。

【讨论】:

  • 非常感谢您的帮助!我尝试了修改,发现它解决了问题,即使我保持在 10 毫秒的间隔(但我将增量减少到 1)。再次非常感谢!
猜你喜欢
  • 2021-11-05
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多