简体   繁体   English

在 tkinter 画布对象的查看区域周围创建“障碍”

[英]Creating "barriers" around the viewing area of a tkinter canvas object

Okay, so I have sort of a unique situation here, so bear with me.好的,所以我在这里有一种独特的情况,所以请耐心等待。 I want to be able to create so called "barriers" around the viewing area (the part of the canvas visible to the user) of a tkinter canvas object.我希望能够在 tkinter 画布对象的查看区域(用户可见的画布部分)周围创建所谓的“障碍”。 For example, take a look at the screenshots below (based on the MCVE at the end):例如,看看下面的截图(基于最后的 MCVE):

问题

As you can see in the image above, the line currently goes outside the viewing area of the canvas when the user reaches the end.正如您在上图中所看到的,当用户到达终点时,线条当前会超出画布的查看区域。 However, that is not what I want.然而,这不是我想要的。 Instead, I want that whenever the user reaches the end of the canvas's visible area, a "barrier" gets hot, and upon contact, a carriage return occurs , and the line(s) continue(s) on from there.相反,我希望每当用户到达画布可见区域的末端时,“障碍”就会变热,并且在接触时发生回车,并且行从那里继续。 So instead of the above, what I really want is this:因此,我真正想要的是:

应该发生什么

Here is the MCVE I used to take the above screenshots:这是我用来截取上述屏幕截图的 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()

Is it possible to add this ability to the MCVE above using tkinter?是否可以使用 tkinter 将此功能添加到上面的 MCVE 中? If so, how would I get started on trying to implement it?如果是这样,我将如何开始尝试实施它?

I am not sure what you are actually trying to do (especially trying to constrain drawing in the displayed region while you provide a very large canvas with scrollbars).我不确定您实际要做什么(特别是在您提供带有滚动条的非常大的画布时试图限制显示区域中的绘图)。

For the simplest case, all you need is a bound value and to test xold against it对于最简单的情况,您只需要一个绑定值并针对它测试xold

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

If you want to take into account the current displayed area, you have to combine information from canvas scrollregion and xview methods.如果要考虑当前显示的区域,则必须结合来自 canvas scrollregionxview方法的信息。 The first return the bounds of the canvas and former the relative position of the displayed aera in the scrollregion.第一个返回画布的边界,并在滚动区域中形成显示区域的相对位置。

    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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM