简体   繁体   中英

python tkinter button binding in canvas grid and adding scrollbar to canvas

How can I get the scrollbar to show up on canvas.

# python dashboard

import tkinter as tk
from tkinter import *

#======================{{{
class AutoScrollbar(Scrollbar):
    def set(self, lo, hi):
        if float(lo) <= 0.0 and float(hi) >= 1.0:
            self.tk.call("grid", "remove", self)
        else:
            self.grid()
        Scrollbar.set(self, lo, hi)
    def pack(self, **kw):
        raise TclError("cannot use pack with this widget")
    def place(self, **kw):
        raise TclError("cannot use place with this widget")
#====}}}


#===================={{{
class Dashboard():
    def __init__(self, root):
        self.root=root
        root.title("Dashboard View")

        canvasContainer = tk.Frame(root)
        self.canvas=tk.Canvas(canvasContainer, width=1000, height=700,background='#002B36')

        canvasContainer.grid(row=0,column=3)

        frame = Frame(self.root, bd=2, relief=SUNKEN)
        frame.grid(row=0,column=0, sticky="nw")

        b1=Button(frame,text="Status", command=lambda color="#DC322F", filename="dashboard_content.txt" : self.contents(color,filename)).grid(row = 0,column = 0, sticky = "we")
        b2=Button(frame,text="Processes", command=lambda color="#859900", filename="process.log" : self.contents(color,filename)).grid(row = 0,column = 1, sticky = "we")
        b3=Button(frame,text="Links", command=lambda color="#B58900", filename="links.log" : self.contents(color,filename)).grid(row = 1,column = 0, sticky = "we")
        b4=Button(frame,text="Traffic", command=lambda color="#268BD2", filename="version.log" : self.contents(color,filename)).grid(row = 1,column = 1, sticky = "we")
        b5=Button(frame,text="App Version", command=lambda color="#D33682", filename="version.log" : self.contents(color,filename)).grid(row = 2,column = 0, sticky = "we")
        b6=Button(frame,text="Archive/Purge", command=lambda color="#93A1A1", filename="cleanup.log" : self.contents(color,filename)).grid(row = 2,column = 1, sticky = "we")

#        self.contents("blue","dashboard_content.txt")
#        b1.bind("<ButtonPress-1>", lambda events, color="blue", filename="dashboard_content.txt" : self.contents(color,filename))

        vsb = AutoScrollbar(canvasContainer,orient=VERTICAL)
        hsb = AutoScrollbar(canvasContainer, orient=HORIZONTAL)
        vsb.grid(row=0, column=2, sticky="ns")
        hsb.grid(row=1, column=1, sticky="ew")
        self.canvas.grid(row=0,column=1,sticky="news")
        self.canvas.config(yscrollcommand=vsb.set, xscrollcommand=hsb.set, scrollregion=self.canvas.bbox("all"))

        vsb.config(command=self.canvas.yview)
        hsb.config(command=self.canvas.xview)

        canvasContainer.grid_rowconfigure(0, weight=1)
        canvasContainer.grid_columnconfigure(0, weight=1)

        self.canvas.update_idletasks()
#        Grid.columnconfigure(self.root,1,weight=1, minsize=100)

    def contents(self, color="blue", filename="dashboard_content.txt"):
        fhandle = open(filename)
        lines = fhandle.read()
        fhandle.close()
        self.canvas.delete("all")
        text1=self.canvas.create_text(0, 0, fill=color, anchor=NW)
        self.canvas.itemconfig(text1, text=lines)

#===========}}}

if __name__== '__main__':
    root=tk.Tk()
    board=Dashboard(root)
    root.mainloop()

If I don't have the contents function, the scrollbar appears. How Can I have a scrollbar around canvas in this case.

You have several problems in your code. The biggest problem is that you are trying to solve too many problems at once.

If you are just starting out, you need to solve layout problems one at a time. It appears you want two major areas in your GUI -- a panel of buttons, and a canvas with scrollbars. So, start by creating two frames, one for each. Give them distinctive colors so you can see what is what. Make sure this two areas are fully functional before trying anything else By that I mean, make sure they resize appropriately when you resize the window.

So, start with the following simple program. Notice that there are no buttons and no canvas. We're just creating the basic scaffolding of the GUI.

import Tkinter as tk

class Dashboard():
    def __init__(self, root):
        self.root=root
        root.title("Dashboard View")

        # the width, height and colors are temporary,
        # until we have more of the GUI working.
        buttonPanel = tk.Frame(root, background="green", width=200, height=200)
        canvasPanel = tk.Frame(root, background="pink", width=500, height=500)

        # because these two panels are side-by-side, pack is the
        # best choice:
        buttonPanel.pack(side="left", fill="y")
        canvasPanel.pack(side="right", fill="both", expand=True)

        # fill in these two areas:
        self._create_buttons(buttonPanel)
        self._create_canvas(canvasPanel)

    def _create_buttons(self, parent):
        pass

    def _create_canvas(self, parent):
        pass

if __name__== '__main__':
    root=tk.Tk()
    board=Dashboard(root)
    root.mainloop()

Does that behave the way you expect? I'll assume so. Now, as long as the buttons go in the left, and the canvas and scrollbars go on the right, we no longer have to worry about the two areas interacting with each other.

Now, create the canvas:

    def _create_canvas(self, parent):
        self.canvas=tk.Canvas(parent, width=1000, height=700,background='#002B36')
        vsb = tk.Scrollbar(parent, command=self.canvas.yview, orient="vertical")
        hsb = tk.Scrollbar(parent, command=self.canvas.xview, orient="horizontal")
        self.canvas.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)

        vsb.grid(row=0, column=0, sticky="ns")
        hsb.grid(row=1, column=0, sticky="ew")
        self.canvas.grid(row=0, column=1, sticky="nsew")

        parent.grid_rowconfigure(0, weight=1)
        parent.grid_columnconfigure(1, weight=1)

Run the program again. Do you see the scrollbars? Is everything still working properly when you resize the window?

The next step would be to add the buttons:

    def _create_buttons(self, parent):

        b1=tk.Button(parent,text="Status", command=lambda: self._contents("#DC322F", "dashboard_content.txt"))
        b2=tk.Button(parent,text="Processes", command=lambda: self._contents("#859900", "process.log"))
        b3=tk.Button(parent,text="Links", command=lambda: self._contents("#B58900", "links.log"))
        b4=tk.Button(parent,text="Traffic", command=lambda: self._contents("#268BD2", "version.log"))
        b5=tk.Button(parent,text="App Version", command=lambda: self._contents("#D33682", "version.log"))
        b6=tk.Button(parent,text="Archive/Purge", command=lambda: self._contents("#93A1A1", "cleanup.log"))

        b1.grid(row = 0,column = 0, sticky = "we")
        b2.grid(row = 0,column = 1, sticky = "we")
        b3.grid(row = 1,column = 0, sticky = "we")
        b4.grid(row = 1,column = 1, sticky = "we")
        b5.grid(row = 2,column = 0, sticky = "we")
        b6.grid(row = 2,column = 1, sticky = "we")

Run the program again, and make sure there are still no layout problems.

See where this is going? Solve just one problem at a time. Organize your code in sections. Collect all of your layout commands in one place so you can better visualize what widgets go together.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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