python3tkinter.Canvas.move()方法在屏幕上生成工件
我正在尝试执行Stackoverflow答案之一中的代码。它是一个单窗口应用程序,有两个圆圈,可以用鼠标移动。 当我移动圆圈时,我看到了人工制品。看 程序代码:python3tkinter.Canvas.move()方法在屏幕上生成工件,python,tkinter,python-3.5,tkinter-canvas,artifacts,Python,Tkinter,Python 3.5,Tkinter Canvas,Artifacts,我正在尝试执行Stackoverflow答案之一中的代码。它是一个单窗口应用程序,有两个圆圈,可以用鼠标移动。 当我移动圆圈时,我看到了人工制品。看 程序代码: import tkinter as tk TOKENWIDTH = 10 class Example(tk.Frame): '''Illustrate how to drag items on a Tkinter canvas''' def __init__(self, parent): tk.Fr
import tkinter as tk
TOKENWIDTH = 10
class Example(tk.Frame):
'''Illustrate how to drag items on a Tkinter canvas'''
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# create a canvas
self.canvas = tk.Canvas(width=400, height=400, bg="white")
self.canvas.pack(fill="both", expand=True)
# this data is used to keep track of an
# item being dragged
self._drag_data = {"x": 0, "y": 0, "item": None}
# create a couple of movable objects
self._create_token((100, 100), "red")
self._create_token((200, 100), "black")
# add bindings for clicking, dragging and releasing over
# any object with the "token" tag
self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)
def _create_token(self, coord, color):
'''Create a token at the given coordinate in the given color'''
(x,y) = coord
self.canvas.create_oval(x-25, y-25, x+25, y+25,
outline="blue", fill=color, tags="token", width = TOKENWIDTH)
def on_token_press(self, event):
'''Begining drag of an object'''
# record the item and its location
self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
self.canvas.update_idletasks()
def on_token_release(self, event):
'''End drag of an object'''
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
self.canvas.update_idletasks()
def on_token_motion(self, event):
'''Handle dragging of an object'''
# compute how much the mouse has moved
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.canvas.move(self._drag_data["item"], delta_x, delta_y)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
self.canvas.update_idletasks()
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
将tkinter作为tk导入
宽度=10
类示例(tk.Frame):
''演示如何在Tkinter画布上拖动项目''
定义初始化(自身,父级):
tk.Frame.\uuuu init\uuuuu(自,父)
#创建画布
self.canvas=tk.canvas(宽度=400,高度=400,bg=“白色”)
self.canvas.pack(fill=“both”,expand=True)
#此数据用于跟踪
#正在拖动的项目
self._drag_data={“x”:0,“y”:0,“item”:None}
#创建两个可移动的对象
self.\u创建\u标记((100100),“红色”)
自我。创建令牌((200100),“黑色”)
#添加用于单击、拖动和释放的绑定
#任何带有“token”标记的对象
self.canvas.tag\u bind(“token”,self.on\u token\u press)
self.canvas.tag\u bind(“token”,“”,self.on\u token\u release)
self.canvas.tag\u bind(“token”,“”,self.on\u token\u运动)
def_create_令牌(self、coord、color):
''在给定坐标以给定颜色创建标记''
(x,y)=坐标
自我。画布。创建椭圆(x-25,y-25,x+25,y+25,
outline=“blue”,fill=color,tags=“token”,width=TOKENWIDTH)
令牌上的def按下(自身,事件):
''开始拖动对象''
#记录项目及其位置
self._drag_data[“item”]=self.canvas.find_closest(event.x,event.y)[0]
self._drag_data[“x”]=event.x
self._drag_data[“y”]=event.y
self.canvas.update_idletasks()
令牌释放时的def(自身、事件):
''对象的结束拖动''
#重置拖动信息
self._drag_data[“item”]=无
自拖动数据[“x”]=0
自身数据[“y”]=0
self.canvas.update_idletasks()
def on_token_运动(自身、事件):
''处理对象的拖动''
#计算鼠标移动了多少
delta_x=event.x-self._拖动_数据[“x”]
delta_y=event.y-self.\u拖动数据[“y”]
#将对象移动适当的量
self.canvas.move(self.\u拖动数据[“项”]、增量x、增量y)
#记录新位置
self._drag_data[“x”]=event.x
self._drag_data[“y”]=event.y
self.canvas.update_idletasks()
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(fill=“both”,expand=True)
root.mainloop()
代码具有在标准Canvas.create_oval()方法中使用的TOKENWIDTH
我做了一些实验,发现当TOKENWIDTH设置为6或更多时,代码在移动对象时会在画布上生成工件。如果TOKENWIDTH在1..5范围内,一切都很好
以下代码行没有帮助:
self.canvas.update_idletasks()
如何解决这些问题?有什么想法吗?
作为一种解决方法,我考虑将两个不同颜色的圆圈相互叠加,以形成圆形的“边框”效果。我尝试了
TOKENWIDTH
的各种值,但在Python 3.6.0上没有任何工件,运行在带有KDE窗口管理器的Debian派生Linux上。你在用什么操作系统?你是如何运行这个脚本的?您是直接从shell运行它,还是使用IDE运行它?我在OSX上也没有看到任何工件。顺便说一句,可以删除对update\u idletasks()
的调用。在这种情况下,它们是完全不必要的。@PM2Ring我在Win10、3.6.1上看到了工件,怀疑Dmitry也是。我强烈怀疑这是圆圈绘制算法中Windows特有的错误。(无论是在tk还是Windows图形原语中,我都不知道。)当运动的水平分量向左(deltax为负数)时,点来自右边缘的最后一个1像素投影,没有被正确擦除。在标记静止的情况下,最右边的像素列不会像应该的那样居中于水平轴上(与左边缘不同)。宽度为5时,不对称和圆点消失。要将画布放在框架上而不是根窗口上,请在画布调用中添加self
作为第一个参数。我也可以在Windows 7、3.6.1上看到工件。它们似乎只在将鼠标向左移动时出现,而将令牌移回工件上方(不向左移动时)会移除它们。当您为我将TOKENWIDTH
(圆圈轮廓的宽度)更改为7或以下时,瑕疵消失。当值为8+时,工件可见。我怀疑这与移动对象时的轮廓有关,至少在Windows上还有一些像素。因此,同时,尝试减少标记宽度。