滚动条可见且可滑动,但不能用作滚动条

时间:2016-03-06 17:09:51

标签: python-2.7 canvas matplotlib tkinter scrollbar

#1,

所以我对编程总体上比较陌生,正在开发一个小项目,涉及通过matplotlib将数据直播到gui中,我或多或少地使用Tkinter创建了gui。无论如何,我必须输出的图形数量范围为1-18,具体取决于用户选择的选项。鉴于潜在的大量图表,我需要滚动条,为此我无耻地从另一个stackoverflow帖子中获取代码并尝试修改以适合我的程序。代码如下:

    #Create popup window for graph display
tlg = Toplevel()
tlg.geometry('400x400')
tlg.title('Live Data Stream')

#Set frame for canvas
frame=Frame(tlg,width=300,height=300)
frame.pack(fill=BOTH,expand=True) #allows dynamic resizing of frame/scrollbar

#Create a canvas on which to play scrollbar widget
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))

#Add horizontal and vertical scrollbars
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X) 
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)

#Pack and implement canvas
canvas.config(width=300,height=300,scrollregion=canvas.bbox("all"))
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)

#######################------- MatPlotLib Graph Creation --------#######################
tlglabel1 = Label(canvas, text='LIVE DATA STREAM', font=('VERDANA',12,'bold'),
                  bg='white').grid(row=0,padx=5,pady=5)

quadl = plt.figure(1,figsize=(5,5))
plt.clf()
quadlx=[1,2,3,4,5,6,7,8]
quadly=[3,4,5,2,3,4,1,6]
plt.plot(quadlx,quadly)
plt.gcf().canvas.draw()
canvasql = FigureCanvasTkAgg(quadl,canvas)
canvasql.get_tk_widget().grid(row=1,column=1)
toolbarql = NavigationToolbar2TkAgg(canvasql,canvas)
toolbarql.grid(row=2,column=1)

quadr = plt.figure(2,figsize=(5,5))
plt.clf()
quadrx=[1,2,3,4,5,6,7,8]
quadry=[3,4,5,2,3,4,1,6]
plt.plot(quadrx,quadry)
plt.gcf().canvas.draw()
canvasqr = FigureCanvasTkAgg(quadr,canvas)
canvasqr.get_tk_widget().grid(row=1,column=2,padx=10)
toolbarqr = NavigationToolbar2TkAgg(canvasqr,canvas)
toolbarqr.grid(row=2,column=2,padx=10)

我添加了两个测试图只是为了测试滚动条的功能,经过测试,它无法执行任何操作。老实说,我不知道该怎么做。我尝试用scrollregion=(0,0,500,500)替换第一个scrollregion=canvas.bbox('all')因为每个其他滚动条代码都有,但是它删除了我的画布并完全删除了我的滚动条。我尝试用hbar=Scrollbar(frame,orient=HORIZONTAL)替换hbar=Scrollbar(canvas,orient=HORIZONTAL),认为滚动条需要移动画布,但这只会使程序崩溃。我尝试将command = canvas.xviewcommand=canvas.yview更改为frame,而不是通过另一个论坛的推荐,但失败了。 Sooo,我被困住了。

1 个答案:

答案 0 :(得分:0)

请阅读mcve s。发布的代码的一半与问题无关,另一半则不完整。

滚动的框架需要一个外框,其中包含一个画布和一个或两个链接的滚动条以及放置在画布上的内框,以便它随画布移动。两者都可以是LabelFrame。以下是3.5 idlelib.configDialog中用于垂直滚动框架的代码。水平滚动条很容易添加。请注意,它有几种方法可以保持大小同步。

class VerticalScrolledFrame(Frame):
    """A pure Tkinter vertically scrollable frame.

    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows vertical scrolling
    """
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0,
                        yscrollcommand=vscrollbar.set, width=240)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)

        return