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?
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/.
