2016-03-20 2 views
2

Хорошо, поэтому у меня есть уникальная ситуация здесь, так что несите меня. Я хочу иметь возможность создавать так называемые «барьеры» вокруг области просмотра (часть холста, видимого пользователю) объекта холста tkinter. Например, взгляните на скриншоты ниже (на основе MCVE в конце):Создание «барьеров» вокруг области просмотра объекта холста tkinter

Issue

Как вы можете видеть на картинке выше, линия в настоящее время идет вне область просмотра холста, когда пользователь достигает конца. Однако это не то, что я хочу. Вместо этого я хочу, чтобы всякий раз, когда пользователь достигает конца видимой области холста, «барьер» становится горячим, а при контакте происходит возврат каретки, и линия (и) продолжается оттуда. Таким образом, вместо того, чтобы выше, что я действительно хочу это:

What should be happening

Вот MCVE я взять выше скриншоты:

import tkinter as TK 

xold = None 
yold = None 

class canvas(TK.Frame): 
    def __init__(self, root, *args, **kwargs): 
     # Initialize a tkinter frame widget 
     TK.Frame.__init__(self, root, width = 800, height = 850, *args, **kwargs) 
     self.root = self.winfo_toplevel() 
     self.bg = "white" 
     self.width, self.height = 850, 800 
     self.canvwidth, self.canvheight = 10000, 10000 
     # Set up the canvas and its corresponding scrollbars 
     self.canvas = TK.Canvas(root, width=850, height=800, 
           bg=self.bg, borderwidth=0, highlightthickness = 5, highlightbackground = 'brown', highlightcolor = 'brown') 
     self.hscroll = TK.Scrollbar(root, command=self.canvas.xview, 
            orient=TK.HORIZONTAL) 
     self.vscroll = TK.Scrollbar(root, command=self.canvas.yview) 
     self.canvas.configure(xscrollcommand=self.hscroll.set, 
           yscrollcommand=self.vscroll.set) 
     self.rowconfigure(0, weight=1, minsize=0) 
     self.columnconfigure(0, weight=1, minsize=0) 
     # Add the scrollbars into the root window 
     self.canvas.grid(padx=1, pady=1, row=0, 
       column=0, rowspan=1, columnspan=1, sticky = 'news') 
     self.vscroll.grid(padx=1, pady=1, row=0, 
       column=1, rowspan=1, columnspan=1, sticky='news') 
     self.hscroll.grid(padx=1, pady=1, row=1, 
       column=0, rowspan=1, columnspan=1, sticky='news') 
     # Call the `reset` method of the canvas class 
     self.reset() 
     # Bind the `line` method to the 'l' key of the users keyboard (as an example of what I want) 
     self.root.bind('<l>', self.line) 

    def reset(self, canvwidth=None, canvheight=None, bg = None): 
     ############################################################################################################################### 
     # This adds the scrollbars themselves to the canvas and adapts them to the canvas's size (in this case, 10000 x 10000 pixels) # 
     ############################################################################################################################### 

     if canvwidth: 
      self.canvwidth = canvwidth 
     if canvheight: 
      self.canvheight = canvheight 
     if bg: 
      self.bg = bg 
     self.canvas.config(bg=bg, 
         scrollregion=(-self.canvwidth//2, -self.canvheight//2, 
             self.canvwidth//2, self.canvheight//2)) 
     self.canvas.xview_moveto(0.5*(self.canvwidth - self.width + 30)/
                   self.canvwidth) 
     self.canvas.yview_moveto(0.5*(self.canvheight- self.height + 30)/
                   self.canvheight) 

    def line(self, event): 
     ######################################################################################################## 
     # Create a short, horizontal, black line on every press of the user's 'l' key (as an example to go by) # 
     ######################################################################################################## 
     global xold, yold 
     if xold != None and yold != None: 
      pass 
     else:  
      xold, yold = 0, 0 
     self.canvas.create_line(xold, yold, xold+30, yold, smooth = TK.TRUE, width = 1, capstyle = TK.ROUND, joinstyle = TK.ROUND, fill = 'black') 
     xold = xold+30 
     yold = yold 

if __name__ == '__main__': 
    # Create a window, and provide that window to the canvas class as the root window 
    root = TK.Tk() 
    root.geometry('900x850') 
    canvas(root) 
    root.mainloop() 

Можно ли добавить эту способность MCVE выше, используя tkinter? Если да, то как мне приступить к его реализации?

ответ

1

Я не уверен, что вы на самом деле пытаетесь сделать (особенно пытаясь сдержать рисование в отображаемой области, пока вы предоставляете очень большой холст с полосами прокрутки).

Для простейшего случая, все, что вам нужно, это связано значение и испытать xold против

if xold > 440: 
    xold = -410 
    yold += 30 

Если вы хотите, чтобы принять во внимание текущую отображаемую область, вы должны объединить информацию из холста scrollregion и xview методов. Первые возвращают границы холста и прежнее относительное положение отображаемой аеры в области прокрутки.

scroll = list(map(int,self.canvas["scrollregion"].split())) 
    xview = self.canvas.xview() 
    leftbound = scroll[0] + xview[1] * (scroll[2]-scroll[0]) 
    if xold > leftbound: 
     rightbound = scroll[0] + xview[0] * (scroll[2]-scroll[0]) 
     xold = rightbound 
     yold += 30 
Смежные вопросы