Write text into canvas python tkinter - python

I have all the gui configurations and all that stuff in my main.py and my algorithms to draw bubble sort and merge sort in another .py file. I'm trying to write the print functions into my canvas but I'm not sure how to do it, can anyone help? I tried using a ListBox() but it messes up the main canvas for some reason.
This is my code for my main file:
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from bubbleSort import bubbleSort
from mergeSort import mergeSort
tk = Tk()
tk.title('Examen Final')
tk.maxsize(900, 600)
tk.config(bg = 'black')
algoritmo = StringVar()
data = []
def dibujar(data, color):
c.delete("all")
cHeight = 380
cWidth = 600
algoWidth = cWidth / (len(data) + 1)
algoHeight = cWidth / (len(data) + 1)
offset = 20
spacing = 10
tamData = [i / max(data) for i in data]
for i, height in enumerate(tamData):
x0 = i * algoWidth + offset + spacing
y0 = cHeight - height * 50
x1 = (i+1) * algoWidth + offset
y1 = cHeight
c.create_oval(x0,y0,x1,y1, fill = color[i])
c.create_text(x0+2,y0, anchor = SW, text=str(data[i]))
tk.update_idletasks()
def Ordenar():
print("Se selecciono: " + algoritmo.get())
print("Iniciando algoritmo")
global data
if menu.get() == 'MERGE SORT':
mergeSort(data, dibujar)
elif menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar)
dibujar(data, ['green' for x in range(len(data))])
def agregar():
global data
input = int(inputVal.get())
inputVal.delete(0, END)
try:
print("valor input:")
print(input)
data.append((input))
print(str(data))
dibujar(data, ['red' for x in range(len(data))])
except:
messagebox.showerror("Error", "Ingrese un valor numerico")
def limpiar():
global data
data = []
c.delete("all")
print(data)
box = Frame(tk, width = 600, height = 200, bg = 'black' )
box.grid(row = 0, column = 0, padx=10, pady=5)
c = Canvas(tk, width = 600, height = 380, bg = 'grey')
c.grid(row = 1, column = 0, padx=10, pady=5)
c2 = Canvas(tk, width = 200, height = 380, bg = 'grey')
c2.grid(row = 1, column = 1, padx=10, pady=5)
label = Label(box, text='Lista Algoritmos: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=0,column=0, padx=5, pady=5, sticky = W)
menu = ttk.Combobox(box, textvariable = algoritmo, values=['BUBBLE SORT', 'MERGE SORT', 'HASH TABLES', 'ARBOL AVL', 'ARBOLES ROJO Y NEGRO'])
menu.grid(row=0, column=1, padx=5, pady=5)
menu.current(0)
botonStart = Button(box, text = 'Ordenar', command = Ordenar, bg = 'lime green')
botonStart.grid(row = 0, column = 2, padx = 5, pady = 5)
label = Label(box, text='Insertar valor: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=1,column=0, padx = 5, pady = 5, sticky = W)
inputVal = Entry(box)
inputVal.grid(row=1,column=1, padx = 5, pady = 5, sticky = W)
botonAdd = Button(box, text = 'Agregar', command = agregar, bg = 'lime green')
botonAdd.grid(row = 1, column = 2, padx = 5, pady = 5, sticky = W)
botonClear = Button(box, text = 'Limpiar', command = limpiar, bg = 'lime green')
botonClear.grid(row = 1, column = 3, padx = 5, pady = 5, sticky = W)
tk.mainloop()
and this is my bubbleSort.py
import time
def bubbleSort(data, dibujar):
for _ in range(len(data)-1):
for j in range(len(data)-1):
if data[j] > data[j+1]:
print(("El numero " + str(data[j]) + " es mayor que " + str(data[j+1])))
data[j],data[j+1] = data[j+1], data[j]
print(("Intercambiando de lugar " + str(data[j]) + " con " + str(data[j+1])))
dibujar(data,
[
'green'
if x == j or x == j+1
else 'red' for x in range(len(data))
]
)
time.sleep(1)
dibujar(data, ['green' for x in range(len(data))])

You can just pass in c2 to the function on the other file. So first define the parameter:
def bubbleSort(data, dibujar, cnv):
cnv.create_text(100,100,text='Trial Text')
....
Now each time you call this function, pass on c2 to it.
if menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar, c2)
I did notice that you are using dynamic points for calculation, if so, make those points global, inside the function, then pass those onto the function by creating more parameter, while keeping in mind that the points have to defined before the function is called.

Related

Scrollable Frame with grid not sticking to the border and not working

I would like to make a scrollable Frame.
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
self.metrics = []
self.content = ttk.Frame(root)
self.v = Scrollbar(root, orient = "vertical")
self.class_label = Label(self.content, text = "labels")
self.A_label = Label(self.content, text = "A")
self.A_entry = Entry(self.content, width = 5)
self.A_input = self.A_entry.get()
self.A_hint = Label(self.content, text = "A")
self.B_label = Label(self.content, text = "B")
self.B_entry = Entry(self.content, width = 5)
self.B_input = self.B_entry.get()
self.B_hint = Label(self.content, text = "B")
self.C = Label(self.content, text = "C")
self.space = Label(self.content, text = "")
self.D_label = Label(self.content, text = "D")
self.D_entry = Entry(self.content, width = 5)
self.D_hint = Label(self.content, text = "D")
self.E_label = Label(self.content, text = "E")
self.E_entry = Entry(self.content, width = 5)
self.E_hint = Label(self.content, text = "D")
self.F_label = Label(self.content, text = "F")
self.F_entry = Entry(self.content, width = 5)
self.F_hint = Label(self.content, text = "F")
self.G_label = Label(self.content, text = "G")
self.G_entry = Entry(self.content, width = 5)
self.G_hint = Label(self.content, text = "G")
self.H_label = Label(self.content, text = "H")
self.H_entry = Entry(self.content, width = 5)
self.H_hint = Label(self.content, text = "H")
self.I_label = Label(self.content, text = "I")
self.I_entry = Entry(self.content, width = 5)
self.I_hint = Label(self.content, text = "I")
self.J_label = Label(self.content, text = "J")
self.J_entry = Entry(self.content, width = 5)
self.J_hint = Label(self.content, text = "J")
self.K_label = Label(self.content, text = "K")
self.K_entry = Entry(self.content, width = 5)
self.K_hint = Label(self.content, text = "K")
self.space2 = Label(self.content, text = "")
self.L_label = Label(self.content, text = "L")
self.L_entry = Entry(self.content, width = 5)
self.content.grid(row = 0, column = 0)
self.v.grid(row = 0, column = 1, sticky = NS)
self.class_label.grid(row = 0, column = 0)
self.A_label.grid(row = 1, column = 0)
self.A_entry.grid(row = 1, column = 1)
self.A_hint.grid(row = 1, column = 3, sticky = "w")
self.B_label.grid(row = 2, column = 0)
self.B_entry.grid(row = 2, column = 1)
self.B_hint.grid(row = 2, column = 3, sticky = "w")
self.C.grid(row = 3, column = 3, sticky = "w")
self.space.grid(row = 4, column = 0)
self.D_label.grid(row = 6, column = 0)
self.D_entry.grid(row = 6, column = 1)
self.D_hint.grid(row = 6, column = 3, sticky = "w")
self.E_label.grid(row = 7, column = 0)
self.E_entry.grid(row = 7, column = 1)
self.E_hint.grid(row = 7, column = 3, sticky = "w")
self.F_label.grid(row = 8, column = 0)
self.F_entry.grid(row = 8, column = 1)
self.F_hint.grid(row = 8, column = 3, sticky = "w")
self.G_label.grid(row = 9, column = 0)
self.G_entry.grid(row = 9, column = 1)
self.G_hint.grid(row = 9, column = 3, sticky = "w")
self.H_label.grid(row = 10, column = 0)
self.H_entry.grid(row = 10, column = 1)
self.H_hint.grid(row = 10, column = 3, sticky = "w", columnspan = 2)
self.I_label.grid(row = 11, column = 0)
self.I_entry.grid(row = 11, column = 1)
self.I_hint.grid(row = 11, column = 3, sticky = "w", columnspan = 2)
self.J_label.grid(row = 12, column = 0)
self.J_entry.grid(row = 12, column = 1)
self.J_hint.grid(row = 12, column = 3, sticky = "w", columnspan = 2)
self.K_label.grid(row = 13, column = 0)
self.K_entry.grid(row = 13, column = 1)
self.K_hint.grid(row = 13, column = 3, sticky = "w", columnspan = 2)
self.space2.grid(row = 14, column = 0)
self.L_label.grid(row = 19, column = 0)
self.L_entry.grid(row = 19, column = 1)
root.mainloop()
if __name__ == '__main__':
root = Tk()
root.title("title")
new_window = MainWindow()
In this first example, the button in the scrollbar does appear but it can't scroll and when I change the window's size, the scrollbar doesn't move.
If I'm not mistaken, I need to create a canvas within my frame and put everything inside this canvas. However, I read that I'm also supposed to put an inner frame inside the canvas. How am I supposed to do it?
So I tried this:
from tkinter import *
from tkinter import ttk
options = ["A", "B", "C", "D", "E", "F", "G", "H"]
root = Tk()
root.title("random software")
content = ttk.Frame(root)
vscrollbar = Scrollbar(content, orient=VERTICAL)
scrollable_canvas = Canvas(content)
inner_frame = Frame(scrollable_canvas)
A_label = Label(content, text = "A")
A_entry = Entry(content, width = 5)
A_hint = Label(content, text = "lorem")
B_label = Label(content, text = "B")
B_entry = Entry(content, width = 5)
B_hint = Label(content, text = "ipsum")
C_label = Label(content, text = "C")
C_entry = Entry(content, width = 5)
C_hint = Label(content, text = "dolor")
D_label = Label(content, text = "D")
D_entry = Entry(content, width = 5)
D_hint = Label(content, text = "sit")
E_label = Label(content, text = "E")
E_entry = Entry(content, width = 5)
E_hint = Label(content, text = "amet")
F_label = Label(content, text = "F")
F_entry = Entry(content, width = 5)
F_hint = Label(content, text = "consectetur")
G_label = Label(content, text = "G")
G_entry = Entry(content, width = 5)
G_hint = Label(content, text = "adipiscing")
H_label = Label(content, text = "H")
H_entry = Entry(content, width = 5)
H_hint = Label(content, text = "elit")
selected_option = StringVar()
selected_option.set(options[0])
option_label = OptionMenu(content, selected_option, *options)
content.grid(row = 1, column = 0)
vscrollbar.grid(row = 1, column = 1, sticky = NS)
option_label.grid(row = 5, column = 1)
A_label.grid(row = 6, column = 0)
A_entry.grid(row = 6, column = 1)
A_hint.grid(row = 6, column = 3, sticky = "w")
B_label.grid(row = 7, column = 0)
B_entry.grid(row = 7, column = 1)
B_hint.grid(row = 7, column = 3, sticky = "w")
C_label.grid(row = 8, column = 0)
C_entry.grid(row = 8, column = 1)
C_hint.grid(row = 8, column = 3, sticky = "w")
D_label.grid(row = 9, column = 0)
D_entry.grid(row = 9, column = 1)
D_hint.grid(row = 9, column = 3, sticky = "w")
E_label.grid(row = 10, column = 0)
E_entry.grid(row = 10, column = 1)
E_hint.grid(row = 10, column = 3, sticky = "w")
F_label.grid(row = 11, column = 0)
F_entry.grid(row = 11, column = 1)
F_hint.grid(row = 11, column = 3, sticky = "w")
G_label.grid(row = 12, column = 0)
G_entry.grid(row = 12, column = 1)
G_hint.grid(row = 12, column = 3, sticky = "w")
H_label.grid(row = 13, column = 0)
H_entry.grid(row = 13, column = 1)
H_hint.grid(row = 13, column = 3, sticky = "w")
root.mainloop()
In this case, the scrollbar isn't extended from top to bottom, it doesn't appear on the right side of the window and when I change the window's size the scrollbar doesn't move. Why isn't it extended on the right side (like the first case) and how to make the scrollbar scrollable?
I saw a few answers with pack but I would like to continue using grid.
Edit:
Based on the answer from Ovski, I managed to get this:
from tkinter import *
from tkinter import ttk
options = ["A", "B", "C", "D", "E", "F", "G", "H"]
root = Tk()
root.title("random software")
content = ttk.Frame(root)
scrollable_canvas = Canvas(content)
vscrollbar = ttk.Scrollbar(content, orient=VERTICAL, command = scrollable_canvas.yview)
scrollable_canvas.configure(yscrollcommand=vscrollbar.set)
scrollable_canvas.bind('<Configure>',
lambda e: scrollable_canvas.configure(scrollregion = scrollable_canvas.bbox("all")))
inner_frame = Frame(scrollable_canvas)
scrollable_canvas.create_window((0, 0), window = inner_frame, anchor = "nw")
A_label = Label(inner_frame, text = "A")
A_entry = Entry(inner_frame, width = 5)
A_hint = Label(inner_frame, text = "lorem")
B_label = Label(inner_frame, text = "B")
B_entry = Entry(inner_frame, width = 5)
B_hint = Label(inner_frame, text = "ipsum")
C_label = Label(inner_frame, text = "C")
C_entry = Entry(inner_frame, width = 5)
C_hint = Label(inner_frame, text = "dolor")
D_label = Label(inner_frame, text = "D")
D_entry = Entry(inner_frame, width = 5)
D_hint = Label(inner_frame, text = "sit")
E_label = Label(inner_frame, text = "E")
E_entry = Entry(inner_frame, width = 5)
E_hint = Label(inner_frame, text = "amet")
F_label = Label(inner_frame, text = "F")
F_entry = Entry(inner_frame, width = 5)
F_hint = Label(inner_frame, text = "consectetur")
G_label = Label(inner_frame, text = "G")
G_entry = Entry(inner_frame, width = 5)
G_hint = Label(inner_frame, text = "adipiscing")
H_label = Label(inner_frame, text = "H")
H_entry = Entry(inner_frame, width = 5)
H_hint = Label(inner_frame, text = "elit")
content.grid(row = 0, column = 1)
scrollable_canvas.grid(row = 0, column = 1)
vscrollbar.grid(row = 0, column = 2, sticky = "NS" + "E")
A_label.grid(row = 6, column = 0)
A_entry.grid(row = 6, column = 1)
A_hint.grid(row = 6, column = 3, sticky = "w")
B_label.grid(row = 7, column = 0)
B_entry.grid(row = 7, column = 1)
B_hint.grid(row = 7, column = 3, sticky = "w")
C_label.grid(row = 8, column = 0)
C_entry.grid(row = 8, column = 1)
C_hint.grid(row = 8, column = 3, sticky = "w")
D_label.grid(row = 9, column = 0)
D_entry.grid(row = 9, column = 1)
D_hint.grid(row = 9, column = 3, sticky = "w", columnspan = 2)
E_label.grid(row = 10, column = 0)
E_entry.grid(row = 10, column = 1)
E_hint.grid(row = 10, column = 3, sticky = "w")
F_label.grid(row = 11, column = 0)
F_entry.grid(row = 11, column = 1)
F_hint.grid(row = 11, column = 3, sticky = "w")
G_label.grid(row = 12, column = 0)
G_entry.grid(row = 12, column = 1)
G_hint.grid(row = 12, column = 3, sticky = "w")
H_label.grid(row = 13, column = 0)
H_entry.grid(row = 13, column = 1)
H_hint.grid(row = 13, column = 3, sticky = "w")
root.mainloop()
The idea behind this is that grid and pack should be combined to get the best result. In this case, using grid with a scrollbar wouldn't really work because the scrollbar would be stuck in its case. By putting every widget in a canvas, the canvas can be aligned using pack and the scrollbar will stick to the border.
Here is a working example of a frame, containing a canvas, containing an "inner_frame" holding a grid of labels.
Included a function that handles scroll events, but this only works if you have a single scrollable area as it locks the scrollwheel to the application, not the frame.
There is also a part (read the comments) to handle resizing of the window.
import tkinter as tk
# mouse wheel scrolling with reduced speed
def on_mouse_wheel(event):
canvas.yview('scroll', int(-1 * event.delta / 120), 'units')
root = tk.Tk()
root.bind('<MouseWheel>', on_mouse_wheel) # bind mousewheel to root, this only works if you have a single scroll area
window_width = 400
window_height = 200
table_columns = 4
table_rows = 30
root.geometry(f'{window_width}x{window_height}')
main_frame = tk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=1) # frame goes to the left
canvas = tk.Canvas(main_frame)
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
v_scroll = tk.Scrollbar(main_frame, orient=tk.VERTICAL, command=canvas.yview)
v_scroll.pack(side=tk.RIGHT, fill=tk.Y) # scrollbar goes to the right
canvas.configure(yscrollcommand=v_scroll.set)
canvas.bind(
'<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox(tk.ALL))
) # adjust scrolling area on resize
inside_frame = tk.Frame(canvas) # frame where you put your actual content
canvas.create_window((0, 0), window=inside_frame, anchor=tk.N) # adding the inside_frame to the canvas
# an example grid with some data
for y in range(table_rows):
for x in range(table_columns):
tk.Label(inside_frame, text=f'{y}:{x}', borderwidth=1, relief=tk.SOLID, width=10).grid(column=x, row=y)
root.mainloop()
This is the way I handle scrollbars for all my GUI applications and it seems to be the only way if you want to scroll widgets other then a textbox or a treeview.
Conclusion: Use the pack manager to arrange the main frame, canvas and inner frame and put all your content inside the inner frame with whatever window manager you like.
UPDATE: Your modified code from the first example
I removed ttk as it is not needed and refactored the coded a bit.
import tkinter as tk
class MainWindow:
def __init__(self, root: tk.Tk):
self.root = root
self.root.title("title")
self.root.geometry('100x200')
self.main_frame = tk.Frame(root)
self.main_frame.pack(fill=tk.Y, expand=1)
self.canvas = tk.Canvas(self.main_frame, width=100)
self.canvas.pack(side=tk.LEFT, fill=tk.Y)
self.v = tk.Scrollbar(self.main_frame, orient=tk.VERTICAL, command=self.canvas.yview)
self.v.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas.configure(yscrollcommand=self.v.set)
self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion=self.canvas.bbox(tk.ALL)))
self.inner_frame = tk.Frame(self.canvas)
self.canvas.create_window((0, 0), window=self.inner_frame, anchor=tk.NW)
self.class_label = tk.Label(self.inner_frame, text="labels")
self.A_label = tk.Label(self.inner_frame, text="A")
self.A_entry = tk.Entry(self.inner_frame, width=5)
self.A_input = self.A_entry.get()
self.A_hint = tk.Label(self.inner_frame, text="A")
self.B_label = tk.Label(self.inner_frame, text="B")
self.B_entry = tk.Entry(self.inner_frame, width=5)
self.B_input = self.B_entry.get()
self.B_hint = tk.Label(self.inner_frame, text="B")
self.C = tk.Label(self.inner_frame, text="C")
self.space = tk.Label(self.inner_frame, text="")
self.D_label = tk.Label(self.inner_frame, text="D")
self.D_entry = tk.Entry(self.inner_frame, width=5)
self.D_hint = tk.Label(self.inner_frame, text="D")
self.E_label = tk.Label(self.inner_frame, text="E")
self.E_entry = tk.Entry(self.inner_frame, width=5)
self.E_hint = tk.Label(self.inner_frame, text="D")
self.F_label = tk.Label(self.inner_frame, text="F")
self.F_entry = tk.Entry(self.inner_frame, width=5)
self.F_hint = tk.Label(self.inner_frame, text="F")
self.G_label = tk.Label(self.inner_frame, text="G")
self.G_entry = tk.Entry(self.inner_frame, width=5)
self.G_hint = tk.Label(self.inner_frame, text="G")
self.H_label = tk.Label(self.inner_frame, text="H")
self.H_entry = tk.Entry(self.inner_frame, width=5)
self.H_hint = tk.Label(self.inner_frame, text="H")
self.I_label = tk.Label(self.inner_frame, text="I")
self.I_entry = tk.Entry(self.inner_frame, width=5)
self.I_hint = tk.Label(self.inner_frame, text="I")
self.J_label = tk.Label(self.inner_frame, text="J")
self.J_entry = tk.Entry(self.inner_frame, width=5)
self.J_hint = tk.Label(self.inner_frame, text="J")
self.K_label = tk.Label(self.inner_frame, text="K")
self.K_entry = tk.Entry(self.inner_frame, width=5)
self.K_hint = tk.Label(self.inner_frame, text="K")
self.space2 = tk.Label(self.inner_frame, text="")
self.L_label = tk.Label(self.inner_frame, text="L")
self.L_entry = tk.Entry(self.inner_frame, width=5)
self.class_label.grid(row=0, column=0)
self.A_label.grid(row=1, column=0)
self.A_entry.grid(row=1, column=1)
self.A_hint.grid(row=1, column=3, sticky="w")
self.B_label.grid(row=2, column=0)
self.B_entry.grid(row=2, column=1)
self.B_hint.grid(row=2, column=3, sticky="w")
self.C.grid(row=3, column=3, sticky="w")
self.space.grid(row=4, column=0)
self.D_label.grid(row=6, column=0)
self.D_entry.grid(row=6, column=1)
self.D_hint.grid(row=6, column=3, sticky="w")
self.E_label.grid(row=7, column=0)
self.E_entry.grid(row=7, column=1)
self.E_hint.grid(row=7, column=3, sticky="w")
self.F_label.grid(row=8, column=0)
self.F_entry.grid(row=8, column=1)
self.F_hint.grid(row=8, column=3, sticky="w")
self.G_label.grid(row=9, column=0)
self.G_entry.grid(row=9, column=1)
self.G_hint.grid(row=9, column=3, sticky="w")
self.H_label.grid(row=10, column=0)
self.H_entry.grid(row=10, column=1)
self.H_hint.grid(row=10, column=3, sticky="w", columnspan=2)
self.I_label.grid(row=11, column=0)
self.I_entry.grid(row=11, column=1)
self.I_hint.grid(row=11, column=3, sticky="w", columnspan=2)
self.J_label.grid(row=12, column=0)
self.J_entry.grid(row=12, column=1)
self.J_hint.grid(row=12, column=3, sticky="w", columnspan=2)
self.K_label.grid(row=13, column=0)
self.K_entry.grid(row=13, column=1)
self.K_hint.grid(row=13, column=3, sticky="w", columnspan=2)
self.space2.grid(row=14, column=0)
self.L_label.grid(row=19, column=0)
self.L_entry.grid(row=19, column=1)
self.root.mainloop()
if __name__ == '__main__':
new_window = MainWindow(tk.Tk())

Checkbutton is not clickable after adding an image to it

I started working with tkinter recently and I have the following problem, I need to make the check box bigger but that is only possible with adding an image. The problem is that whenever I add an image to a button it becomes unclickable and the image is not displayed, here is my source code (part of a bigger project). My goal is to display some information and let the user decide which option he gets to keep using the check button. Any help is appreciated.
import tkinter as tk
import tkcalendar as tkc
LARGE_FONT = ("HELVETICA", 32, 'bold')
NORMAL_FONT = ("calibri", 18)
class ConstituireDosar(tk.Toplevel):
def __init__(self, controller):
tk.Toplevel.__init__(self)
self.update_idletasks()
# self.dosar = dosar
self.controller = controller
self.minsize(651, 569)
# self.maxsize(651, 569)
frame_titlu = tk.Frame(self)
frame_titlu.grid(row = 0, column = 0)
frame_continut = tk.Frame(self)
frame_continut.grid(row = 1, column = 0, sticky = "w")
frame_acte = tk.Frame(self)
frame_acte.grid(row = 2, column = 0)
titlu = tk.Label(frame_titlu, font = LARGE_FONT, text = "Constituire Dosar")
titlu.grid(row = 0 , column = 0, padx = 10, pady = 15)
data_emiterii = tk.Label(frame_continut, font = NORMAL_FONT,text = "Data emiterii documentului:")
data_emiterii.grid(row = 1, column = 0, padx = 10, pady = 5, sticky = "w")
self.cal = tkc.DateEntry(frame_continut, date_pattern = "DD/MM/YYYY", width = 20)
self.cal.grid(row = 2, column = 0, padx = 10, pady = 5, sticky = "w")
debitori_label = tk.Label(frame_continut, font = NORMAL_FONT, text = "Selecteaza debitorii.")
debitori_label.grid(row = 3, column = 0, padx = 10, pady = 5, sticky = "w")
debitori = []
tip_debitori = []
for i in range(2):
debitori.append("Person %s " % str(i))
tip_debitori.append("Person %s type" % str(i))
for i in range(len(debitori)):
print(debitori[i])
row_i = 4
self.vars_debitori = []
on_image = tk.PhotoImage(width=48, height=24)
off_image = tk.PhotoImage(width=48, height=24)
on_image.put(("green",), to=(0, 0, 23,23))
off_image.put(("red",), to=(24, 0, 47, 23))
for i in range(len(debitori)):
var = tk.IntVar(frame_continut, value = 0)
interior = debitori[i] + " - " + tip_debitori[i]
# Checkbutton(ws, image=switch_off, selectimage=switch_on, onvalue=1, offvalue=0, variable=cb1, indicatoron=False, command=switchState)
checkbuton = tk.Checkbutton (frame_continut, bd = 5, image = off_image, selectimage = on_image, indicatoron = False, onvalue = 1, offvalue = 0, variable = var, state = tk.ACTIVE, command = lambda: self.toggle(var))
checkbuton.grid(row = row_i, column = 0, padx = 20, pady = 5, sticky = "nw")
checkbuton.image = off_image
# checkbuton.select()
self.vars_debitori.append(var)
row_i += 1
self.vars_acte = []
acte = ["Acte de Procedura", "Incheiere de Admitere", "Cerere de Incuviintare", "Instiintare Creditor"]
for i in range(4):
v = tk.IntVar()
check = tk.Checkbutton(frame_acte, font = NORMAL_FONT, text = acte[i], variable = v)
check.grid(row = row_i, column = 0, padx = 10, pady = 5)
check.select()
self.vars_acte.append(v)
row_i += 1
emite_acte = tk.Button(frame_acte, font = NORMAL_FONT, text = "Emite acte.", command = self.emite_acte)
emite_acte.grid(row = row_i, column = 1, padx = 15, pady = 30, ipadx = 70, ipady = 10)
emite_acte.configure(bg = '#218838', fg = '#FFFFFF')
buton_cancel = tk.Button(frame_acte, font = NORMAL_FONT, text = "Cancel", command = lambda: self.destroy())
buton_cancel.grid(row = row_i, column = 0, padx = 15, pady = 30, ipadx = 70, ipady = 10)
buton_cancel.configure(bg = "red", fg = '#FFFFFF')
def emite_acte(self):
print(self.cal.get_date().strftime("%d/%m/%y"))
print(self.winfo_height(), self.winfo_width())
if __name__ == "__main__":
root = tk.Tk()
app = ConstituireDosar(root)
app.protocol("WM_DELETE_WINDOW", root.destroy)
root.withdraw()
root.mainloop()
I tried some options that I saw on the forum, in another file they worked fine but when I tried to implement it in the project itself the checkbutton is still unclickable and it doesn't display the images either. tkinter checkbutton different image I tried to replicate Bryan's answer, but no luck there. Also didn't receive any console error message.
As #furas pointed in the comments above, the problem got fixed with keeping the images as member variables of the class, also the button became clickable after removing the self.toggle(var) command from checkbutton

TypeError: Iniciar() missing 1 required positional argument: 'data' and failed append

Im trying to append the input numbers to my array data everytime I click the button "agregar", however it seems like it only appends the value i just inserted and completely forgets about the previous append. I don't get any error messaged with that one. Also, when I click "iniciar" it should draw ovals with the values in data but I get the error
TypeError: Iniciar() missing 1 required positional argument: 'data'
I'm not sure what I'm doing wrong and would appreciate it if anyone could help.
from tkinter import *
from tkinter import ttk
from array import *
import random
tk = Tk()
tk.title('Bubble Sort')
tk.maxsize(900, 600)
tk.config(bg = 'black')
#Variables
algoritmo = StringVar()
#comandos
def dibujar(data):
c.delete("all")
cHeight = 380
cWidth = 600
#para escalar
algoWidth = cWidth / (len(data) + 1)
algoHeight = cWidth / (len(data) + 1)
offset = 20
spacing = 10
tamData = [i / max(data) for i in data]
for i, height in enumerate(tamData):
#top left
x0 = i * algoWidth + offset + spacing
y0 = cHeight - height * 50
#botom right
x1 = (i+1) * algoWidth + offset
y1 = cHeight
c.create_oval(x0,y0,x1,y1, fill = 'red')
c.create_text(x0+2,y0, anchor = SW, text=str(data[i]))
def Iniciar(data):
print("Se selecciono: " + algoritmo.get())
dibujar(a)
def agregar():
data = array('i', [1, 3, 5, 7, 9])
input = int(inputVal.get())
data.append((input))
print("valor input:")
print(input)
print(str(data))
def limpiar():
c.delete("all")
#Frame
box = Frame(tk, width = 600, height = 200, bg = 'black' )
box.grid(row = 0, column = 0, padx=10, pady=5)
c = Canvas(tk, width = 600, height = 380, bg = 'grey')
c.grid(row = 1, column = 0, padx=10, pady=5)
#UI
#Row-0
label = Label(box, text='Lista Algoritmos: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=0,column=0, padx=5, pady=5, sticky = W)
menu = ttk.Combobox(box, textvariable = algoritmo, values=['BUBBLE SORT', 'MERGE SORT', 'HASH TABLES', 'ARBOL AVL', 'ARBOLES ROJO Y NEGRO'])
menu.grid(row=0, column=1, padx=5, pady=5)
menu.current(0)
botonStart = Button(box, text = 'Iniciar', command = Iniciar, bg = 'lime green')
botonStart.grid(row = 0, column = 2, padx = 5, pady = 5)
#Row-1
label = Label(box, text='Insertar valor: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=1,column=0, padx = 5, pady = 5, sticky = W)
inputVal = Entry(box)
inputVal.grid(row=1,column=1, padx = 5, pady = 5, sticky = W)
botonAdd = Button(box, text = 'Agregar', command = agregar, bg = 'lime green')
botonAdd.grid(row = 1, column = 2, padx = 5, pady = 5, sticky = W)
botonClear = Button(box, text = 'Limpiar', command = limpiar, bg = 'lime green')
botonClear.grid(row = 1, column = 3, padx = 5, pady = 5, sticky = W)
tk.mainloop()
You are defining Iniciar here:
def Iniciar(data):
print("Se selecciono: " + algoritmo.get())
dibujar(a)
But when you call it below you aren't passing a data argument to it
botonStart = Button(box, text = 'Iniciar', command = Iniciar, bg = 'lime green')

tkinter, Image does not show up unless some function added

I have written a code for a basic game but the image and shape don't show up unless I add something like item.pack() or win.mainloop() [which doesn't really make sense] but then the lines below it don't run.
When I don't have anything, the buttons show up but the image doesn't show up.
import tkinter as tk
import random
from tkinter import messagebox
win = tk.Tk()
my_label = tk.Label(win, text="Color of the Baloon Game")
my_label.pack()
my_canvas = tk.Canvas(win, width=400, height=600)
my_canvas.pack()
background_image=tk.PhotoImage(file = "CS_Game_menu.png")
background_label = tk.Label(my_canvas, image=background_image)
background_label.photo = background_image
background_label.grid(row = 0, rowspan = 10, column = 0, columnspan = 10)
def drawCircle():
color = "green"
x1 = 265
y1 = 80
diameter = 90
my_canvas.destroy()
circle_button.destroy()
quit_button.destroy()
my_label.destroy()
my_label1 = tk.Label(win, text="What is the Color of the Baloon?", font="Purisa")
my_label1.pack()
my_canvas1 = tk.Canvas(win, width=400, height=600)
my_canvas1.pack()
image1 = r"CS_Game_baloon.png"
photo1 = tk.PhotoImage(file=image1)
item = my_canvas1.create_image(200, 350, image=photo1)
shape = my_canvas1.create_oval(x1, y1, x1 + diameter, y1 + diameter+20, fill=color)
item.pack()
game1_button = tk.Button(my_canvas1, text = "Green")
game1_button.grid(row= 8, column = 3)
game1_button["command"] = lambda: messagebox.showinfo("Congratulations!", "Correct Answer!")
game2_button = tk.Button(my_canvas1, text = "Blue")
game2_button.grid(row= 8, column = 5)
game2_button["command"] = lambda: messagebox.showinfo("Sorry!", "Incorrect Answer!")
game3_button = tk.Button(my_canvas1, text = "Red")
game3_button.grid(row= 8, column = 7)
game3_button["command"] = lambda: messagebox.showinfo("Sorry", "Incorrect Answer!")
circle_button = tk.Button(win, text="New Game")
circle_button.pack()
circle_button["command"] = drawCircle
quit_button = tk.Button(win, text="Quit")
quit_button.pack()
quit_button['command'] = win.destroy
You are using both the create_... methods and grid methods on your canvas object. It won't behave as you expected.
To achieve what you want, you can create a Frame, put your buttons in it, and then use create_window method on your canvas:
def drawCircle():
...
shape = my_canvas1.create_oval(x1, y1, x1 + diameter, y1 + diameter+20, fill=color)
frame = tk.Frame(my_canvas1)
game1_button = tk.Button(frame, text = "Green")
game1_button.grid(row= 8, column = 3)
game1_button["command"] = lambda: messagebox.showinfo("Congratulations!", "Correct Answer!")
game2_button = tk.Button(frame, text = "Blue")
game2_button.grid(row= 8, column = 5)
game2_button["command"] = lambda: messagebox.showinfo("Sorry!", "Incorrect Answer!")
game3_button = tk.Button(frame, text = "Red")
game3_button.grid(row= 8, column = 7)
game3_button["command"] = lambda: messagebox.showinfo("Sorry", "Incorrect Answer!")
my_canvas1.create_window(200,500,window=frame)
And of course, add win.mainloop() to the bottom of your program if you haven't already.

Python 3.6 tkinter says GROOVE is not defined

The below program was working fine few minutes back. I made a change,ran the code, made a small mistake, Spyder crashed and now it either cannot find Frame or Groove or something else. At the moment it says GROOVE not defined.
Tried writing it in lower case and with quotes. When I do with quotes it says: TclError: bad relief "Groove": must be flat, groove, raised, ridge, solid, or sunken. When I do lower or upper case without quotes says groove not defined.
from RiskFactorConversion import *
from tkinter import ttk, StringVar, Frame, Label, Tk, Entry
mainwindow = Tk()
mainwindow.title("Risk Factor Conversion")
datatype = StringVar()
dataconvention = StringVar()
mdlname = StringVar()
instancevalue = StringVar()
axisvalue = StringVar()
def g():
datatype = e1.get()
dataconvention = e2.get()
mdlname = e3.get()
instancevalue = e4.get()
r1 = rates.srtqualifier(mdlname,datatype,dataconvention,instancevalue)
l5["text"] =r1.makequalifier()
def f():
datatype = e5.get()
dataconvention = e6.get()
axisvalue = e8.get()
fx1 = fx.felixfxvol(datatype,dataconvention,axisvalue)
l11["text"] =fx1.fxvol()
def h():
datatype = en1.get()
dataconvention = en2.get()
fx2 = fx.murexfx(datatype,dataconvention)
la4["text"] =fx2.makequalifier()
#########Felix Frame####################################
frame1 = Frame(bg="white", colormap="new", padx = 10, relief=GROOVE, borderwidth=2)
frame1.grid(row = 0, column = 0)
l0 = Label(frame1, text= "FELIX Rates", pady =5, font = ('Georgia',14,'bold'), bg="white")
l0.grid(row = 0, column = 0,sticky= W )
l1 = Label(frame1, text= "Please provide Data Type:",bg="white", justify = "right",pady =5 )
l1.grid(row = 1, column = 0, sticky= E )
e1 = Entry(frame1,bd = 2, width =50, textvariable = datatype )
e1.grid(row = 1, column = 1)
e1.focus_set()
l2 = Label(frame1,bg="white", text= "Please provide Data Convention:",justify = "right", pady = 5)
l2.grid(row = 2, column = 0,sticky= E)
e2 = Entry(frame1,bd = 2, width =50, textvariable = dataconvention )
e2.grid(row = 2, column = 1)
l3 = Label(frame1,bg="white", text= "Please provide Model Type:", justify = "right",pady = 5)
l3.grid(row = 3, column = 0,sticky= E)
e3 = ttk.Combobox(frame1,width =45, textvariable = mdlname, state='readonly')
e3['values'] = ('IR_SABR','FX_LN','IR_LGM','IR_LMM','IR_SABR_FX_LN_GC','IR_SABR_GC','INFLATION_SABR')
e3.grid(row = 3, column = 1)
l4 = Label(frame1,bg="white", text= "Please provide Instance Name:", justify = "right",pady = 5)
l4.grid(row = 4, column = 0,sticky= E)
e4 = Entry(frame1,bd = 2, width =50, textvariable = instancevalue )
e4.grid(row = 4, column = 1)
bfelix = Button(frame1, text = "Press to get Qualifier Value", pady = 10, command = g)
bfelix.grid(row = 5, column = 0)
l5 = Label(frame1,bg="white", text= "" , justify = "right",pady = 5)
l5.grid(row = 5, column = 1)
################################################################
############FELIX FX############################################
frame2 = Frame(bg="white", colormap="new", padx = 10, relief=GROOVE, borderwidth=2)
frame2.grid(row = 0, column = 1)
l6 = Label(frame2, text= "FELIX FX", pady =5, font = ('Georgia',14,'bold'), bg="white")
l6.grid(row = 0, column = 0,sticky= W )
l7 = Label(frame2, text= "Please provide Data Type:",bg="white", justify = "right",pady =5 )
l7.grid(row = 1, column = 0, sticky= E )
e5 = Entry(frame2,bd = 2, width =50, textvariable = datatype)
e5.grid(row = 1, column = 1)
e5.focus_set()
l8 = Label(frame2,bg="white", text= "Please provide Data Convention:",justify = "right", pady = 5)
l8.grid(row = 2, column = 0,sticky= E)
e6 = Entry(frame2,bd = 2, width =50, textvariable = dataconvention )
e6.grid(row = 2, column = 1)
l10 = Label(frame2,bg="white", text= "Please provide axis 2 value:", justify = "right",pady = 5)
l10.grid(row = 3, column = 0,sticky= E)
e8 = Entry(frame2,bd = 2, width =50, textvariable = axisvalue )
e8.grid(row = 3, column = 1)
bfelixfx = Button(frame2, text = "Press to get Qualifier Value", pady = 10, command = f)
bfelixfx.grid(row = 4, column = 0)
l11 = Label(frame2,bg="white", text= "" , justify = "right",pady = 5)
l11.grid(row = 4, column = 1)
#####################################################################
############MUREX FX############################################
frame3 = Frame(bg="white", colormap="new", padx = 10, relief=GROOVE, borderwidth=2)
frame3.grid(row = 1, column = 1)
la = Label(frame3, text= "Murex FX", pady =5, font = ('Georgia',14,'bold'), bg="white")
la.grid(row = 0, column = 0,sticky= W )
la1 = Label(frame3, text= "Please provide Risk Factor Type:",bg="white", justify = "right",pady =5 )
la1.grid(row = 1, column = 0, sticky= E )
en1 = ttk.Combobox(frame3, width =45, textvariable = mdlname, state='readonly')
en1['values'] =('FX ATM VOLATILITY','FX BUTTERFLY 10D','FX BUTTERFLY 25D','FX RISK REVERSAL 10D','FX RISK REVERSAL 25D')
en1.grid(row = 1, column = 1)
en1.focus_set()
la2 = Label(frame3,bg="white", text= "Please provide Currency Pair:",justify = "right", pady = 5)
la2.grid(row = 2, column = 0,sticky= E)
en2 = Entry(frame3,bd = 2, width =50, textvariable = dataconvention )
en2.grid(row = 2, column = 1)
bmurexfx = Button(frame3, text = "Press to get Qualifier Value", pady = 10, command = h)
bmurexfx.grid(row = 4, column = 0)
la4 = Label(frame3,bg="white", text= "" , justify = "right",pady = 5)
la4.grid(row = 4, column = 1)
#####################################################################
mainwindow.mainloop()
Groove is a constant defined in Tkinter and since you are only importing specfic functions from Tkinter that doesn't include Groove, you need to add GROOVE to it or add
import tkinter as tk
and then set relief=tk.GROOVE

Categories