Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 画布绝对和相对坐标,增量像素检索_Python_Python 3.x_Tkinter_Tkinter Canvas - Fatal编程技术网

Python 画布绝对和相对坐标,增量像素检索

Python 画布绝对和相对坐标,增量像素检索,python,python-3.x,tkinter,tkinter-canvas,Python,Python 3.x,Tkinter,Tkinter Canvas,在这个测试脚本中,我画了一个正方形,可以用鼠标滚轮放大。 如果我在单元格内单击鼠标右键,我会得到正确的单元格坐标(不是x和y,而是列和行):这正是我希望它在后台写入控制台的内容。 相反,如果我通过按下鼠标左键并将其拖动到其他位置来移动画布,则坐标不再正确 我从哪里获得delta x和delta y(或偏移量)以返回正确的信息 供参考: 1) get_pos()是执行检查并生成结果的方法。 2) 以下代码已经在运行Python3.5.2的Ubuntu16.10(最新更新)上进行了测试 import

在这个测试脚本中,我画了一个正方形,可以用鼠标滚轮放大。 如果我在单元格内单击鼠标右键,我会得到正确的单元格坐标(不是x和y,而是列和行):这正是我希望它在后台写入控制台的内容。 相反,如果我通过按下鼠标左键并将其拖动到其他位置来移动画布,则坐标不再正确

我从哪里获得delta x和delta y(或偏移量)以返回正确的信息

供参考: 1) get_pos()是执行检查并生成结果的方法。 2) 以下代码已经在运行Python3.5.2的Ubuntu16.10(最新更新)上进行了测试

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
    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 = 1

    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

    zoom = self.zoom
    if self.drawn() and 1 != zoom:
        if self.zoom < 1:
            self.zoom = zoom = 1
            print('no zooming below 1.')
        else:
            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:', self.zoom, '  col, row:', 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 = 9

    self.zoom += 1
    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 -= 1
    if self.zoom < 1:
        print("Can't go below one.")
        self.zoom = 1
        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)

    print('x1, y1, x2, y2:', x1, y1, x2, y2,
          '  bbox:', self.bbox('maze'))
    if not (x1 <= x <= x2 and y1 <= y <= y2):
        print('Here we are out of bounds.')
        return None, None

    scale = zoom * 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 'canvas' not 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()
将tkinter作为tk导入
将tkinter.ttk导入为ttk
类GriddedMazeCanvas(tk.Canvas):
def几乎居中(自、列、行):
宽度=int(自身['width'])
高度=整数(自['height'])
cell\u dim=自身设置['cell\u dim']
行数=行数%高度
cols=cols%宽度
w=cols*单元尺寸
h=行*单元尺寸
如果self.zoom<0:
raise VALUERROR('缩放为负:',self.zoom)
zoom=self.zoom
如果self.draw()和1!=缩放:
w*=缩放
h*=缩放
h_shift=(宽度-w)//2
v_shift=(高度-h)//2
返回[h_移位,v_移位,
h_shift+w,v_shift+h]
定义初始化(self,*args,**kwargs):
如果“设置”不在kwargs中:
raise VALUERROR(“'settings'未通过。”)
设置=kwargs['settings']
del kwargs[“设置”]
super()
self.config(highlightthickness=0)
self.settings=设置
self.bind_事件()
def draw_迷宫(自身、列、行):
self.cols=cols
self.rows=行
如果self.not_draw():
self.cells={}
self.cell\u dim=self.settings['cell\u dim']
self.border\u thickness=self.settings['border\u thickness']
self.zoom=1
self.delete(tk.ALL)
迷宫,坐标=self.\u绘图\u迷宫(cols,rows,fix=False)
直线=自绘制网格(坐标)
返回迷宫、线路
定义绘制迷宫(self、cols、rows、fix=True):
数据=自我设置
to_max=数据['to_max']
边框厚度=数据[“边框厚度”]
poligon_color=数据['poligon_color']
poligon\u border\u color=数据['poligon\u border\u color']
coords=self.几乎居中(列、行)
如果修复:
#修正消失的西北边界
如果to_max==cols:
坐标[0]+=1
如果to_max==行:
坐标[1]+=1
迷宫=自我。创建矩形(*坐标,
填充=poligon\u颜色,
轮廓=poligon\u边框\u颜色,
宽度=边框厚度,
tag='maze')
返回迷宫,coords
定义绘制网格(自、坐标):
数据=自我设置
poligon\u border\u color=数据['poligon\u border\u color']
单元尺寸=数据['cell尺寸']
如果coords为无:
如果self.not_draw():
raise VALUERROR('迷宫仍未初始化')
x1,y1,x2,y2=自几乎居中(self.cols,self.rows)
其他:
x1,y1,x2,y2=坐标
zoom=self.zoom
如果self.draw()和1!=缩放:
如果self.zoom<1:
self.zoom=zoom=1
打印('不在1以下缩放')
其他:
单元尺寸*=缩放
行=[]
对于枚举中的i,x(范围(x1,x2,单元格尺寸)):
线=自身。创建线(x,y1,x,y2,
填充=poligon\u边框\u颜色,
标签=('grid','grid_hl{}'。格式(i)))
行。追加(行)
对于枚举中的i,y(范围(y1,y2,单元格_-dim)):
线=自身。创建线(x1,y,x2,y,
填充=poligon\u边框\u颜色,
标签=('grid','grid_vl_{}'。格式(i)))
行。追加(行)
回程线
def绘制(自):
return hasattr(self,“cells”)
未绘制def(自):
返回非自绘制()
def绑定_事件(自):
self.bind(“”,self.onZoomIn)
self.bind(“”,self.onZoomOut)
self.bind(“”,self.onScrollStart)
self.bind(“”,self.onScrollMove)
self.tag_bind('maze','',self.onMouseRight)
def onScrollStart(自身、事件):
打印(event.x、event.y、self.canvasx(event.x)、self.canvasy(event.y))
自我扫描标记(事件x、事件y)
def onMouseRight(自身、事件):
列,行=自身获取位置(事件)
打印('zoom:',self.zoom,'col,row:',col,row)
def onScrollMove(自身、事件):
增量=事件x,事件y
自扫描绘图(*增量,增益=1)
def onZoomIn(自身,事件):
如果self.not_draw():
回来
最大缩放=9
self.zoom+=1
如果self.zoom>最大缩放:
打印(“无法超出”,最大缩放)
self.zoom=最大缩放
回来
打印('放大'、event.num、event.x、event.y、self.zoom)
self.draw_迷宫(self.cols、self.rows)
def onZoomOut(自身、事件):
如果self.not_draw():
回来
self.zoom-=1
如果self.zoom<1:
打印(“不能低于1”)
self.zoom=1
回来
打印('缩小'、event.num、event.x、event.y、self.zoom)
self.draw_迷宫(self.cols、self.rows)
def get_位置(自身、事件):
x、 y=事件.x,事件.y
cols,rows=self.cols,self.rows
单元格尺寸,缩放=self.cell尺寸,self.zoom
x1,y1,x2,y2=自几乎居中(列,行)
打印('x1,y1,x2,y2:',x1,y1,x2,y2,
'bbox:',self.bbox('maze'))
如果不是(x1看a,我学会了如何找到我要找的δx和δy

因此,解决方案是:

    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)

        # the following line stores deltax and deltay into x0, y0 
        x0, y0 = int(self.canvasx(0)), int(self.canvasy(0))

        # then it is trivial to compute the solution
        xa, ya = x1 - x0, y1 - y0
        xb, yb = x2 - x0, y2 - y0

        if not (xa <= x <= xb and ya <= y <= yb):
            print('Here we are out of bounds.')
            return None, None

        scale = zoom * cell_dim

        col = (x - xa) // scale
        row = (y - ya) // scale

        return col, row
def get_pos(自身,事件):
x、 y=事件.x,事件.y
cols,rows=self.cols,self.rows
单元格尺寸,缩放=self.cell尺寸,self.zoom
x1,y1,x2,y2=自几乎居中(列,行)
#下一行将deltax和deltay存储到x0、y0中
x0,y0=int(self.canvasx(0)),int(self.canvasy(0))
#那就是琐事了