2016-03-20 10 views
2

Okay, also habe ich hier eine einzigartige Situation, also ertragen Sie mit mir. Ich möchte so genannte "Barrieren" um den Anzeigebereich (der Teil des Canvas sichtbar für den Benutzer) eines Tkinter-Canvas-Objekts erstellen können. Nehmen wir zum Beispiel einen Blick auf die Screenshots unten (bezogen auf das MCVE am Ende):Erstellen von "Barrieren" um den Sichtbereich eines Tkinter-Canvas-Objekts

Issue

Wie Sie im Bild oben sehen kann, die derzeit die Linie außerhalb der Sichtbereich geht der Leinwand, wenn der Benutzer das Ende erreicht. Aber das ist nicht was ich will. Stattdessen möchte ich, dass, wenn der Benutzer das Ende des sichtbaren Bereichs der Leinwand erreicht, eine "Barriere" heiß wird, und bei Kontakt ein Wagenrücklauf auftritt und die Linie (n) von dort fortfahren. Also statt der oben genannten, was ich wirklich will, ist dies:

What should be happening

Hier ist die MCVE ich die obigen Screenshots nehmen verwendet:

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() 

Ist es möglich, diese Fähigkeit hinzufügen der MCVE oben mit tkinter? Wenn ja, wie würde ich anfangen, es zu implementieren?

Antwort

1

Ich bin mir nicht sicher, was Sie tatsächlich versuchen (insbesondere versuchen, Zeichnung in der angezeigten Region zu beschränken, während Sie eine sehr große Leinwand mit Bildlaufleisten bereitstellen).

Für den einfachsten Fall, alles, was Sie ist ein gebundenes Wert benötigen und xold dagegen testen

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

Wenn Sie den aktuellen angezeigten Bereich berücksichtigen wollen, müssen Sie Informationen aus Leinwand kombinieren scrollregion und xview Methoden. Die ersten geben die Grenzen der Zeichenfläche und die relative Position der angezeigten Fläche in der Bildlaufregion zurück.

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 
Verwandte Themen