Python tkinter画布闪烁

时间:2020-01-05 18:44:09

标签: python-3.x tkinter tkinter-canvas

首先,我应该指出,我知道该网站上其他名称相似的帖子。我经历过这些问题,但据我所知,它们没有解决我的问题。我实际上会说我的问题要比大多数例子简单得多。

简单地说,我想创建一个透明的矩形,可以用来显示拖动选择区域。当我发现tkinter不能做到透明时,我决定只画四条线来创建矩形的外观,而不必在这两条线之间画任何东西。并不理想,但是对于我的小型项目而言,这已经足够了(尽管如果有人知道一个没有透明度和颜色渐变以及没有太多麻烦的事情的图书馆,我就会不知所措)。

所以我创建了我的画布。按下鼠标时,我保存了坐标,并在该坐标处创建了四行(有效地是一个像素矩形),并且在鼠标移动时,我使用了canvas.coords方法移动了这些线。鼠标悬停时,我使用canvas.delete删除了这些行。

代码似乎可以正常工作,但是(我认为是)问题是对画布的更新。如果我非常缓慢地单击并拖动,该矩形将显示为我想要的样子。如果我移动得更快(我应该澄清一下,我认为此拖动速度在正常使用范围内是正确的),则底部和右侧线条会消失,直到鼠标变慢或停止为止。如果我一直在疯狂地晃动鼠标,我可能已经了解了,但是这种情况发生的速度确实没有那么快。因此,线条非常明显地消失或闪烁,因为偶尔更新速度足以跟踪移动的鼠标。

基本上看起来很糟糕,但是有一些注意事项。因此,如果将鼠标向下和向右拖动(使框变大),则会发生这种情况。当我将其拖回起点以创建一个较小的框时,无论我尝试执行多快,都不会发生。我确定这是canvas小部件的一个怪癖,但我想知道如何修复它,或者人们是否只是继续使用其他库而不是tkinter(如果是,它们是什么?)

对于这种事情,代码是如此简单:

def OnLeftMouseDown(event):
    global InitialX, InitialY, Line1ID, Line2ID, Line3ID, Line4ID
    InitialX = event.x
    InitialY = event.y
    Line1ID = canvas.create_line(event.x, event.y, event.x, event.y, fill='green')
    Line2ID = canvas.create_line(event.x, event.y, event.x, event.y, fill='green')
    Line3ID = canvas.create_line(event.x, event.y, event.x, event.y, fill='green')
    Line4ID = canvas.create_line(event.x, event.y, event.x, event.y, fill='green')

def OnLeftMouseUp(event):
    canvas.delete(Line1ID)
    canvas.delete(Line2ID)
    canvas.delete(Line3ID)
    canvas.delete(Line4ID)

def OnLeftMouseMove(event):
    canvas.coords(Line1ID, InitialX, InitialY, InitialX, event.y)
    canvas.coords(Line2ID, InitialX, InitialY, event.x, InitialY)
    canvas.coords(Line3ID, event.x, InitialY, event.x, event.y)
    canvas.coords(Line4ID, InitialX, event.y, event.x, event.y)


root = tk.Tk()
root.geometry("1000x600")

global InitialX, InitialY
global Line1ID, Line2ID, Line3ID, Line4ID

canvas = tk.Canvas(root, width=800, height=600, bg='white')
canvas.pack()

canvas.bind("<ButtonPress-1>", OnLeftMouseDown)
canvas.bind("<B1-Motion>", OnLeftMouseMove)
canvas.bind("<ButtonRelease-1>", OnLeftMouseUp)

root.mainloop()

我在拖动画布上的其他项目时遇到了这个问题。我想要一系列视觉“节点”,它们只是包含信息的框架。以正常速度拖动它们会切断帧的最右侧和最底部。

编辑:我的操作系统是Windows7。我已经尝试过用户sciroccorics下面建议的代码,还尝试过将画布方法“ update_idletasks”添加到自己的代码中。没变化。我的程序具有闪烁,并且sciroccorics的代码具有相同的闪烁。 此外,我已经使用Microsoft Expression Encoder 4捕获了桌面以显示正在发生的事情。使用屏幕盖和该程序,我看不到任何轻拂/消失的线条(即使将记录器设置为以60fps录制)。尽管我可以使用手机记录看到的内容,所以我们可以在这里查看:Vimeo vid of flickering

1 个答案:

答案 0 :(得分:1)

这里是示例的最小版本,使用一个矩形而不是四行(我在画布上添加了一个蓝色圆圈,以表明该矩形是透明的)。在我(较旧)的笔记本电脑上,它没有显示任何闪烁或消失的边缘。您设备上的状态如何?

正如@stovfl所指出的那样,在Windows 10上,tkinter显示刷新的确确实效率要比在Windows 7上低得多(与以前在Linux / X11上一样,效率已经低得多)。我在鼠标移动回调中添加了<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=9"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Delivery App</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> </head> <body> <div class="container"> <table class="table"> <thead> <tr> <th scope="col">Id</th> <th scope="col">Tran id</th> <th scope="col">Assembly Instructions</th> <th scope="col">Miscalleanous</th> </tr> </thead> <tbody> {{ range . }} <tr> <th scope="row">{{.Id}}</th> <td>{{.TranId}}</td> <td>{{.Memo}}</td> <td>{{.AssemblyInstructions}}</td> <td>{{.AssemblingUnits}}</td> </tr> {{ end }} </tbody> </table> </div> <!-- /container --> </body> </html> ,因为它有时会改善刷新错误。您可以将其注释掉,并测试它是否有任何区别。

update_idletasks()