캔버스에 직사각형을 그릴 때 나는 절대 좌표 (canvasx(), canvasy())와 상대 좌표 (나는 통과 한 좌표)를 알고 있습니다. 그런 다음 캔버스 scan_mark() 및 scan_dragto() 메소드를 사용하여 캔버스를 이동할 수 있습니다. 사용자가 위치를 잃어 버렸을 수도있는 사각형을 다시 센터링하려면 이러한 scan_mark()/scan_dragto() 호출 중 하나 이상이 수행되기 전에 원래 위치로 어떻게 되돌릴 수 있습니까? 재설정보기 명령/방법이 있습니까? 발생한 변화를 어떻게 추적 할 수 있습니까?tkinter에서 캔버스의 뷰를 어떻게 재설정 할 수 있습니까?
0
A
답변
2
필자가 보았던 Tkinter 문서는이 점을 언급하지 않았지만 현재 Tk Canvas xview/yview 메서드는 매개 변수없이 호출하여 현재 스크롤 위치를 가져올 수 있습니다 (실제로는 두 요소의 튜플, 두 번째는 너에게 어떤 용도로도 사용되지 않는다). 그래서, 다음은 (테스트하지) 작동합니다 :
저장 위치 :
origX = yourcanvas.xview()[0]
origY = yourcanvas.yview()[0]
위치 복원 : 이전 코멘트 @jasonharper에서와 같이
yourcanvas.xview_moveto(origX)
yourcanvas.yview_moveto(origY)
+0
감사합니다. jasonharper. 이것은 내가 찾고 있었던 바로 그 것이다. 그것은 효과가 있었다. –
0
을, 그의 제안했다. 동일한 문제가있는 다른 사람들을 위해 작업 예제를 첨부하여 자랑스럽게 잘 정리하지는 못했지만 확대/축소 및보기 드래그 및 재설정이 작동하는 방식을 볼 수있는 방법을 제공 할 수 있습니다.
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()
파이썬 3.4로 테스트 최신 우분투 16.10 (이벤트 : MouseLeft, Mouseright,을 MouseWheel, ButtonPress) HTH
관련 문제
- 1. viewcontroller의 값을 어떻게 재설정 할 수 있습니까?
- 2. Java, 어떻게 JTextField를 재설정 할 수 있습니까?
- 3. JTextField를 어떻게 재설정 할 수 있습니까?
- 4. 다각형의 스타일을 어떻게 재설정 할 수 있습니까?
- 5. AmChart를 어떻게 재설정 할 수 있습니까?
- 6. PublisherAdView 레이아웃을 어떻게 재설정 할 수 있습니까?
- 7. DataTemplate의 ThemeResource를 어떻게 재설정 할 수 있습니까?
- 8. 어떻게 스크롤 뷰를 비활성화 할 수 있습니까?
- 9. "나쁜"뷰를 어떻게 식별 할 수 있습니까?
- 10. 어떻게 부분 뷰를 동적으로로드 할 수 있습니까?
- 11. 어떻게 웹 뷰를 표시 할 수 있습니까?
- 12. 어떻게 텍스트 뷰를 분할 할 수 있습니까?
- 13. 파이썬 tkinter에서 볼을 어떻게 활주시킬 수 있습니까?
- 14. 컬렉션 변경시이 백본보기를 어떻게 재설정 할 수 있습니까?
- 15. Tkinter에서 텍스트의 색을 어떻게 바꿀 수 있습니까?
- 16. 캔버스의 Tkinter에서 PIL 이미지를 여는 방법
- 17. Tkinter에서 캔버스의 스크롤 영역을 동적으로 변경하는 방법
- 18. tkinter에서 중간 프로그램 버튼을 어떻게 비활성화 할 수 있습니까?
- 19. Tkinter에서 위젯을 이름으로 검색 할 수 있습니까?
- 20. MigLayout을 "재설정"할 수 있습니까
- 21. ServicePointManager를 재설정 할 수 있습니까?
- 22. mySql의 auto_increment 필드를 재설정 할 수 있습니까?
- 23. (Emacs) 우연히 전환 된 키, 어떻게 재설정 할 수 있습니까?
- 24. 어떻게 작업 커밋을 특정 커밋으로 재설정 할 수 있습니까?
- 25. 양식을 제출할 때 특정 필드를 어떻게 재설정 할 수 있습니까?
- 26. C#에서 양식을 어떻게 재설정 할 수 있습니까?
- 27. 유닛 테스트간에 어떻게 cassandra 저널을 재설정 할 수 있습니까?
- 28. (PyQt) 전체 QTextEdit의 CharFormat을 어떻게 재설정 할 수 있습니까?
- 29. 어떻게 Runnable.postDelayed() 타이머를 취소하고 버튼 클릭시 재설정 할 수 있습니까?
- 30. JWT 토큰 만료 시간을 어떻게 재설정 할 수 있습니까?
가 처음 생성되면 캔버스의 그것의 좌표를 알고 있다면, 당신은 할 수 없었다 이러한 좌표를 저장하고 다시 설정하려는 경우 해당 값을 캔버스보기로 복원 할 수 있습니까? – davedwards
나는 내가 만든 객체의 좌표를 알고 있지만 원래의 뷰로 돌아가려면 전체 캔버스를 가로 및/또는 세로로 스크롤해야하는 양을 모릅니다. 이것이 제가 가진 문제입니다. 이 델타는 어디에 저장/사용 가능합니까? –