2024-07-05 09:46:32 发布
网友
当我在画布上画一个矩形时,我知道它的坐标,绝对坐标(canvasx(),canvasy())和相对坐标(我传递的那些)。 然后,我可以使用canvas scan_mark()和scan_dragto()方法移动画布。 如何返回原始位置(在一个或多个scan_mark()/scan_dragto()调用之前)以重新居中用户可能丢失位置的矩形? 是否有重置视图命令/方法?我如何跟踪发生的变化?在
正如前面的评论@jasonharper,他的建议奏效了。对于其他可能有同样问题的人,我附上了一个工作示例,尽管它没有被清理得那么好,值得骄傲,它可能会让你看到放大和缩小,视图拖动和重置如何工作。在
import tkinter as tk import tkinter.ttk as ttk class GriddedMazeCanvas(tk.Canvas): def almost_centered(self, cols, rows): width = int(self['width']) height = int(self['height']) cell_dim = self.settings['cell_dim'] rows = rows % height cols = cols % width w = cols * cell_dim h = rows * cell_dim if self.zoom < 0: raise ValueError('zoom is negative:', self.zoom) zoom = self.zoom // 2 + 1 if self.drawn() and 1 != zoom: w *= zoom h *= zoom h_shift = (width - w) // 2 v_shift = (height - h) // 2 return [h_shift, v_shift, h_shift + w, v_shift + h] def __init__(self, *args, **kwargs): if 'settings' not in kwargs: raise ValueError("'settings' not passed.") settings = kwargs['settings'] del kwargs['settings'] super().__init__(*args, **kwargs) self.config(highlightthickness=0) self.settings = settings self.bind_events() def draw_maze(self, cols, rows): self.cols = cols self.rows = rows if self.not_drawn(): self.cells = {} self.cell_dim = self.settings['cell_dim'] self.border_thickness = self.settings['border_thickness'] self.zoom = 0 self.delete(tk.ALL) maze, coords = self._draw_maze(cols, rows, fix=False) lines = self._draw_grid(coords) return maze, lines def _draw_maze(self, cols, rows, fix=True): data = self.settings to_max = data['to_max'] border_thickness = data['border_thickness'] poligon_color = data['poligon_color'] poligon_border_color = data['poligon_border_color'] coords = self.almost_centered(cols, rows) if fix: # Fix for the disappearing NW borders if to_max == cols: coords[0] += 1 if to_max == rows: coords[1] += 1 maze = self.create_rectangle(*coords, fill=poligon_color, outline=poligon_border_color, width=border_thickness, tag='maze') return maze, coords def _draw_grid(self, coords): data = self.settings poligon_border_color = data['poligon_border_color'] cell_dim = data['cell_dim'] if coords is None: if self.not_drawn(): raise ValueError('The maze is still uninitialized.') x1, y1, x2, y2 = self.almost_centered(self.cols, self.rows) else: x1, y1, x2, y2 = coords if self.drawn() and 0 != self.zoom: if self.zoom < 0: self.zoom = 0 print('no zooming at negative values.') else: zoom = self.zoom // 2 + 1 cell_dim *= zoom lines = [] for i, x in enumerate(range(x1, x2, cell_dim)): line = self.create_line(x, y1, x, y2, fill=poligon_border_color, tags=('grid', 'grid_hl_{}'.format(i))) lines.append(line) for i, y in enumerate(range(y1, y2, cell_dim)): line = self.create_line(x1, y, x2, y, fill=poligon_border_color, tags=('grid', 'grid_vl_{}'.format(i))) lines.append(line) return lines def drawn(self): return hasattr(self, 'cells') def not_drawn(self): return not self.drawn() def bind_events(self): self.bind('<Button-4>', self.onZoomIn) self.bind('<Button-5>', self.onZoomOut) self.bind('<ButtonPress-1>', self.onScrollStart) self.bind('<B1-Motion>', self.onScrollMove) self.tag_bind('maze', '<ButtonPress-3>', self.onMouseRight) def onScrollStart(self, event): print(event.x, event.y, self.canvasx(event.x), self.canvasy(event.y)) self.scan_mark(event.x, event.y) def onMouseRight(self, event): col, row = self.get_pos(event) print('zoom, col, row:', self.zoom, col, row) def onScrollMove(self, event): delta = event.x, event.y self.scan_dragto(*delta, gain=1) def onZoomIn(self, event): if self.not_drawn(): return max_zoom = 16 self.zoom += 2 if self.zoom > max_zoom: print("Can't go beyond", max_zoom) self.zoom = max_zoom return print('Zooming in.', event.num, event.x, event.y, self.zoom) self.draw_maze(self.cols, self.rows) def onZoomOut(self, event): if self.not_drawn(): return self.zoom -= 2 if self.zoom < 0: print("Can't go below zero.") self.zoom = 0 return print('Zooming out.', event.num, event.x, event.y, self.zoom) self.draw_maze(self.cols, self.rows) def get_pos(self, event): x, y = event.x, event.y cols, rows = self.cols, self.rows cell_dim, zoom = self.cell_dim, self.zoom x1, y1, x2, y2 = self.almost_centered(cols, rows) if not (x1 <= x <= x2 and y1 <= y <= y2): print('Here we are out of bounds.') return None, None scale = (zoom // 2 + 1) * cell_dim col = (x - x1) // scale row = (y - y1) // scale return col, row class CanvasButton(ttk.Button): def freeze_origin(self): if not hasattr(self, 'origin'): canvas = self.canvas self.origin = canvas.xview()[0], canvas.yview()[0] def reset(self): canvas = self.canvas x, y = self.origin canvas.yview_moveto(x) canvas.xview_moveto(y) def __init__(self, *args, **kwargs): if not 'canvas' in kwargs: raise ValueError("'canvas' not passed.") canvas = kwargs['canvas'] del kwargs['canvas'] super().__init__(*args, **kwargs) self.config(command=self.reset) self.canvas = canvas root = tk.Tk() settings = {'cell_dim': 3, 'to_max': 200, 'border_thickness': 1, 'poligon_color': '#F7F37E', 'poligon_border_color': '#AC5D33'} frame = ttk.Frame(root) canvas = GriddedMazeCanvas(frame, settings=settings, width=640, height=480) button = CanvasButton(frame, text='Reset', canvas=canvas) button.freeze_origin() canvas.draw_maze(20, 10) canvas.grid(row=0, column=0, sticky=tk.NSEW) button.grid(row=1, column=0, sticky=tk.EW) frame.rowconfigure(0, weight=1) frame.grid() root.mainloop()
在最新的Ubuntu16.10上用Python3.4进行了测试 (事件:鼠标左键、鼠标右键、鼠标滚轮、按键) 高温
我看到的Tkinter文档似乎没有提到这一点,但是可以调用底层的Tk Canvas xview/yview方法来获取当前的滚动位置(实际上,作为两个元素的元组,第二个元素对您没有任何用处)。因此,以下方法应该有效(未经测试):
保存位置:
origX = yourcanvas.xview()[0] origY = yourcanvas.yview()[0]
恢复位置:
正如前面的评论@jasonharper,他的建议奏效了。对于其他可能有同样问题的人,我附上了一个工作示例,尽管它没有被清理得那么好,值得骄傲,它可能会让你看到放大和缩小,视图拖动和重置如何工作。在
在最新的Ubuntu16.10上用Python3.4进行了测试 (事件:鼠标左键、鼠标右键、鼠标滚轮、按键) 高温
我看到的Tkinter文档似乎没有提到这一点,但是可以调用底层的Tk Canvas xview/yview方法来获取当前的滚动位置(实际上,作为两个元素的元组,第二个元素对您没有任何用处)。因此,以下方法应该有效(未经测试):
保存位置:
恢复位置:
^{pr2}$相关问题 更多 >
编程相关推荐