Home > Software engineering >  How to use Canvas upon/in/with Tkinter?
How to use Canvas upon/in/with Tkinter?

Time:10-19

I'm trying to draw a rectangle on the empty space, but everytime I create something with Canvas, it moves all the buttons down (img 2). I don't want the buttons created with tkinter to move when I use Canvas, is there a way I can do it?

img1

img2

Code:

from tkinter import *
from functools import partial

colors = {
    0:"#ab91ff", 1:"#d0a176", 2:"#ecce86", 3:"#ecff91", 4:"#fff991", 5:"#92ff9f", 6:"#f991ff", 7:"#91dfff",
    8:"#d2ff91", 9:"#b8ff91"
}
buttonsPos = {
    "H":[1, 1, colors[0]], "He":[1, 18, colors[7]],

    "Li":[2, 1,  colors[1]], "Be":[2, 2, colors[2]], "B":[2, 13, colors[5]], "C":[2, 14, colors[0]], "N":[2, 15, colors[0]],
    "O":[2, 16, colors[0]], "F":[2, 17, colors[6]], "Ne":[2, 18, colors[7]],

    #more data...

}

DEFAULT_BOLD = ("Helvetica", "15", "bold")

class GUI():
    def __init__(self):
        self.root = Tk()
        self.root.geometry("900x414")
        self.root.iconbitmap("./icon.ico")
        self.root.title("Tabla periódica de los elementos")
        self.root.resizable(False, False)
        self.c = Canvas(self.root)
        self.c.pack()
        self.c.create_rectangle(50, 150, 250, 50, fill="pink")
        self.buttonsFrame = self.createFButtons()
        self.buttons = self.createButtons(self.buttonsFrame)


    def do(self):
        pass

    def createButtons(self, frame):
        bs = []
        for k,v in buttonsPos.items():
            b = Button(frame, command=partial(self.do, str(k)), text=str(k), font=DEFAULT_BOLD, height=1, width=3,
                       borderwidth=4, bg=v[2])
            b.grid(row=v[0], column=v[1], sticky=NSEW)
            bs.append(b)
        return bs

    def createFButtons(self):
        frame = Frame(self.root, bg="#ebebeb")
        frame.pack(fill="both", expand="True")
        return frame

    def loop(self):
        self.root.mainloop()

if __name__ == "__main__":
    c = GUI()
    c.loop()

CodePudding user response:

You are creating canvas and buttons frame are 2 different widgets and packed one after another. you cant create any rectangle on top of the frame. so, creating a rectangle in canvas resizes the canvas widget that pushes the buttons frame down.

you can create canvas inside a buttons frame and position using absolute positioning with place command.

from tkinter import *
from functools import partial

colors = {
    0:"#ab91ff", 1:"#d0a176", 2:"#ecce86", 3:"#ecff91", 4:"#fff991", 5:"#92ff9f", 6:"#f991ff", 7:"#91dfff",
    8:"#d2ff91", 9:"#b8ff91"
}
buttonsPos = {
    "H":[1, 1, colors[0]], "He":[1, 18, colors[7]],

    "Li":[2, 1,  colors[1]], "Be":[2, 2, colors[2]], "B":[2, 13, colors[5]], "C":[2, 14, colors[0]], "N":[2, 15, colors[0]],
    "O":[2, 16, colors[0]], "F":[2, 17, colors[6]], "Ne":[2, 18, colors[7]],

    #more data...

}

DEFAULT_BOLD = ("Helvetica", "15", "bold")

class GUI():
    def __init__(self):
        self.root = Tk()
        self.root.geometry("900x414")
        self.root.title("Tabla periódica de los elementos")
        self.root.resizable(False, False)
        self.buttonsFrame = self.createFButtons()
        self.buttons = self.createButtons(self.buttonsFrame)

        self.c = Canvas(self.buttonsFrame, width=150, height=50)
        self.c.place(x=100, y=0)
        self.c.create_rectangle(0, 100, 150, 0, fill="pink")

    def do(self):
        pass

    def createButtons(self, frame):
        bs = []
        for k,v in buttonsPos.items():
            b = Button(frame, command=partial(self.do, str(k)), text=str(k), font=DEFAULT_BOLD, height=1, width=3,
                       borderwidth=4, bg=v[2])
            b.grid(row=v[0], column=v[1], sticky=NSEW)
            bs.append(b)
        return bs

    def createFButtons(self):
        frame = Frame(self.root, bg="#ebebeb")
        frame.pack(fill="both", expand="True")
        return frame

    def loop(self):
        self.root.mainloop()

if __name__ == "__main__":
    c = GUI()
    c.loop()

CodePudding user response:

You can play with the pack arguments passed to Canvas:

self.c = Canvas(self.root)
self.c.pack(...)

Another option would be using grid instead of pack, but you should modify the whole code (because grid and pack can't be together).

You can find useful information about Tkinter widgets here: https://coderslegacy.com/python/python-gui/. You can find a quick guide of Canvas here: https://coderslegacy.com/python/tkinter-canvas/.

  • Related