tkinter askopenfilenames() closes GUI on 2nd activation - python

the following is working first pass around. Select file/s, activate the view button and def, view files. all good.
When trying to select another file/s, during the selection process, the GUI closes abruptly.
I tried to figure out of the variable needs to be reset, but that did not change.
after all the imports:
root = tk.Tk()
root.title("Motion GUI")
root.minsize(width=1000, height=700)
root.maxsize(width=1400, height = 900)
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0,weight=1)
WidgetFrame = ttk.Frame(mainframe, borderwidth=2,relief='ridge',height = 60)
WidgetFrame.grid(column=0,row=0, sticky="E,W")
def CreateWidgets():
link_Label = Label(WidgetFrame, text ="Select File(s): ", bg = "#E8D579")
link_Label.grid(row = 1, column = 0, pady = 5, padx = 5)
WidgetFrame.sourceText = Entry(WidgetFrame, width = 50, textvariable = sourceLocation)
WidgetFrame.sourceText.grid(row = 1, column = 1, pady = 5, padx = 5, columnspan = 2)
source_browseButton = Button(WidgetFrame, text ="Browse", command = SourceBrowse, width = 15)
source_browseButton.grid(row = 1, column = 3, pady = 5, padx = 5)
viewButton = Button(WidgetFrame, text ="View File(s)", command = ViewFile, width = 15)
viewButton.grid(row = 3, column = 0, pady = 5, padx = 5)
def SourceBrowse():
WidgetFrame.files_list = list(filedialog.askopenfilenames(initialdir ="/mnt/data/Motion_Data/Motion_Clips",title="Press shift key plus Left mouse click to select multiple files"))
def ViewFile():
# plays all selected files one by one, keeps speed selected in 1st clip unless changed..
files_list = WidgetFrame.files_list
for f in files_list:
player.playlist_append(f)
player.playlist_pos = 0
player.wait_for_playback
sourceLocation = StringVar()
destinationLocation = StringVar()
file_list = StringVar()
CreateWidgets()
root.mainloop()
What am I missing?

here is the full code with all the buttons and functions. BTW, all the other Buttons and Functions do work without problems (that is: Copy/Move/Delete):
#!/usr/bin/python3
import os
import shutil
import tkinter as tk
from tkinter import *
from tkinter import filedialog, messagebox
from tkinter import ttk
import webbrowser
if os.environ.get('DISPLAY','') == "":
print('no display found.Using :0.0')
os.environ.__setitem__('DISPLAY',':0.0')
##### MPV.py HAS TO BE copied into the directory which imports mpv ######
import mpv
player = mpv.MPV(ytdl=True,input_default_bindings=True,input_vo_keyboard=True,osc=True)
media = open('mPlaylist.u3e', 'r').read().splitlines()
# Creating object of tk class
root = tk.Tk()
root.title("Motion GUI")
root.minsize(width=1000, height=700)
root.maxsize(width=1400, height = 900)
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0,weight=1)
WidgetFrame = ttk.Frame(mainframe, borderwidth=2,relief='ridge',height = 60)
WidgetFrame.grid(column=0,row=0, sticky="E,W")
# Setting the title and background color disabling the resizing property
root.geometry("830x420")
root.title("View/Copy/Move/Delete mkv's")
root.config(background = "gray")
def CreateWidgets():
WidgetFrame.link_Label = Label(WidgetFrame, text ="Select File(s): ", bg = "#E8D579")
WidgetFrame.link_Label.grid(row = 1, column = 0, pady = 5, padx = 5)
WidgetFrame.sourceText = Entry(WidgetFrame, width = 50, textvariable = sourceLocation)
WidgetFrame.sourceText.grid(row = 1, column = 1, pady = 5, padx = 5, columnspan = 2)
WidgetFrame.source_browseButton = Button(WidgetFrame, text ="Browse", command = SourceBrowse, width = 15)
WidgetFrame.source_browseButton.grid(row = 1, column = 3, pady = 5, padx = 5)
WidgetFrame.destinationLabel = Label(WidgetFrame, text ="Select The Destination : ", bg ="#E8D579")
WidgetFrame.destinationLabel.grid(row = 2, column = 0, pady = 5, padx = 5)
WidgetFrame.destinationText = Entry(WidgetFrame, width = 50, textvariable = destinationLocation)
WidgetFrame.destinationText.grid(row = 2, column = 1, pady = 5, padx = 5, columnspan = 2)
WidgetFrame.dest_browseButton = Button(WidgetFrame, text ="Browse", command = DestinationBrowse, width = 15)
WidgetFrame.dest_browseButton.grid(row = 2, column = 3, pady = 5, padx = 5)
WidgetFrame.viewButton = Button(WidgetFrame, text ="View File(s)", command = ViewFile, width = 15)
WidgetFrame.viewButton.grid(row = 3, column = 0, pady = 5, padx = 5)
WidgetFrame.copyButton = Button(WidgetFrame, text ="Copy File", command = CopyFile, width = 15)
WidgetFrame.copyButton.grid(row = 3, column = 1, pady = 5, padx = 5)
WidgetFrame.moveButton = Button(WidgetFrame, text ="Move File", command = MoveFile, width = 15)
WidgetFrame.moveButton.grid(row = 3, column = 2, pady = 5, padx = 5)
WidgetFrame.moveButton = Button(WidgetFrame, text ="Delete File(s)", command = DeleteFile, width = 15)
WidgetFrame.moveButton.grid(row = 3, column = 3, pady = 5, padx = 5)
WidgetFrame.MotionButton = Button(WidgetFrame, text="IP Streams",command=MotionHTTP, font="LUCIDA 12")
WidgetFrame.MotionButton.grid(row=3,column=5,pady=5,padx=5)
WidgetFrame.exitButton = Button(WidgetFrame, text="Quit", command=root.destroy, font="LUCIDA 12 bold")
WidgetFrame.exitButton.grid(row = 3, column = 6,pady = 5, padx = 5)
def MotionHTTP():
webbrowser.open("http://192.168.0.26:8080")
def SourceBrowse():
WidgetFrame.files_list = list(filedialog.askopenfilenames(initialdir ="/home/rainer/Videos",title="Press shift key plus Left mouse click to select multiple files"))
files_list = []
WidgetFrame.sourceText.insert('1', WidgetFrame.files_list)
def DestinationBrowse():
destinationdirectory = filedialog.askdirectory(initialdir ="/mnt/data/Motion_Data/Motion_Clips")
WidgetFrame.destinationText.insert('1', destinationdirectory)
def ViewFile():
# plays all selected files one by one, keeps speed selected in 1st clip unless changed..
files_list = WidgetFrame.files_list
for f in files_list:
print(f)
player.playlist_append(f)
player.playlist(files_list)
#player.playlist_pos = 0
player.wait_for_playback
playlist.close()
def CopyFile():
files_list = WidgetFrame.files_list
destination_location = destinationLocation.get()
# Looping through the files present in the list
shutil.copy(f, destination_location)
def MoveFile():
files_list = WidgetFrame.files_list
destination_location = destinationLocation.get()
for f in files_list:
shutil.move(f, destination_location)
def DeleteFile():
files_list = WidgetFrame.files_list
for f in files_list:
os.remove(f)
# Creating tkinter variable
sourceLocation = StringVar()
destinationLocation = StringVar()
files_list = StringVar()
#destinationLocation = StringVar(value='/home/rainer/Music')
#file_list = StringVar()
# Calling the CreateWidgets() function
CreateWidgets()
# Defining infinite loop
root.mainloop()

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

Adding scrollbar widget to Tkinter GUI results in errors

I have written the following code to get the user input. But I am not able to add a scrollbar to it. I want to place a vertical scrollbar because I am not able to view all the input labels on my screen.
I first tried:
v = Scrollbar(root, orient='vertical')
v.config(command=root.yview)
It gave me the following error:
File "/Users/aaditya/Desktop/Blender_software/Blender_algo_exp/testing.py", line 235, in <module>
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
File "/opt/anaconda3/envs/blender_env/lib/python3.9/tkinter/__init__.py", line 2486, in grid_configure
self.tk.call(
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
After that I tried the following:
myscroll = Scrollbar(root)
myscroll.pack(side = RIGHT, fill = Y)
Which resulted in the following error:
AttributeError: '_tkinter.tkapp' object has no attribute 'yview'
How can I fix this?
This is my entire code:
# Driver code
if __name__ == "__main__" :
root = Tk()
# v = Scrollbar(root, orient='vertical')
# v.config(command=root.yview)
# myscroll = Scrollbar(root)
# myscroll.pack(side = RIGHT, fill = Y)
root.configure(background = 'light gray')
root.geometry("700x700")
root.title("Blender Software")
label1 = Label(root, text = "Total Quantity: ",
fg = 'black', bg = 'white')
label2 = Label(root, text = "Percentage of Solid Scrap : ",
fg = 'black', bg = 'white')
label3 = Label(root, text = "Cr min : ",
fg = 'black', bg = 'white')
label4 = Label(root, text = "Cr max : ",
fg = 'black', bg = 'white')
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
label2.grid(row = 2, column = 0, padx = 10, pady = 10)
label3.grid(row = 3, column = 0, padx = 10, pady = 10)
label4.grid(row = 4, column = 0, padx = 10, pady = 10)
# Create a entry box
# for filling or typing the information.
total_quantity = Entry(root)
per_solid_scrap = Entry(root)
Cr_min_input = Entry(root)
Cr_max_input = Entry(root)
# grid method is used for placing
# the widgets at respective positions
# in table like structure .
total_quantity.grid(row = 1, column = 1, padx = 10, pady = 10)
per_solid_scrap.grid(row = 2, column = 1, padx = 10, pady = 10)
Cr_min_input.grid(row = 3, column = 1, padx = 10, pady = 10)
Cr_max_input.grid(row = 4, column = 1, padx = 10, pady = 10)
button1 = Button(root, text = "Submit", bg = "red",
fg = "black", command = calculate_op)
button1.grid(row = 21, column = 1, pady = 10)
# Start the GUI
root.mainloop()
Pack and grid cannot be used at the same time. So since you called the pack for the scrollbar, you cannot manage the following widgets by grid anymore. An easy fix is to place the scrollbar with grid function instead. Apart from that, try using a function or class to make your code less lengthy because now it seems hard to read and purposeless.

Adding a tkcalendar DateEntry to a tkinter GUI

this my situation. I'm learning how to use python (I just started) to create a GUI with Tkinter. One requirement of my application is to be able to store "DateEntry", while investigating I came across with tkcalendar DateEntry. The problem is that DateEntry is created as a class but my already created window(GUI) is a class as well and I don't know how to combine the class DateEntry into my class client which creates a mainwindow, I think that's beyond my knowledge. I want a DateEntry to be displayed in another toplevel() window when the button "Fecha Check-in" is used. Can anyone explain how to do it?
this is the image
This is the code:
from tkcalendar import DateEntry
from datetime import date
from tkinter import ttk
from tkinter import *
import sqlite3
#year = datetime.date.today().year
#month = datetime.date.today().month
class client:
def __init__(self, window):
self.wind = window
self.wind.title('Start Bits CheckIn-CheckOut')
#self.wind.columnconfigure(0, weight = 1)
#self.wind.rowconfigure(0, weight = 1)
#self.wind.geometry("330x300")
frame_2 = Label(self.wind, text = 'Registro de huéspedes')
frame_2.grid(row = 0, column = 0, pady = 5)
#
frame = LabelFrame(self.wind, text = 'Datos personales', borderwidth=4, relief="raised")
frame.grid(row = 1, column = 0, columnspan = 10, pady = 2, sticky = W + E)
#
# #label ID
L_ID = Label(frame, text = 'Cédula: ').grid(row = 1, column = 0, padx = 1, pady = 1)
self.ID = Entry(frame, width = 25)
self.ID.focus()
self.ID.grid(row = 1, column = 1, columnspan = 2)
#label Nombre
L_name = Label(frame, text = 'Nombres: ').grid(row = 2, column =0, padx = 1, pady = 2)
self.nombre = Entry(frame, width = 25)
self.nombre.grid(row = 2, column = 1, columnspan = 2)
#label last
L_last = Label(frame, text = 'Apellidos: ').grid(row = 3, column = 0, padx = 1, pady = 2)
self.last = Entry(frame, width = 25)
self.last.grid(row = 3, column = 1, columnspan = 2)
#label contact phone
L_phone = Label(frame, text = 'Teléfono: ').grid(row = 4, column = 0, padx = 1, pady = 2)
self.phone = Entry(frame, width = 25)
self.phone.grid(row = 4, column = 1, columnspan = 2)
#label email
L_mail = Label(frame, text = 'Email: ').grid(row = 5, column = 0, padx = 1, pady = 2)
self.mail = Entry(frame, width = 25)
self.mail.grid(row = 5, column = 1, columnspan = 2)
#label CheckIn
L_ChkIN = Label(frame, text = 'Check-In: ').grid(row = 6, column = 0, padx = 1, pady = 5)
ttk.Button(frame, text = 'Fecha Check-In', command = self.fecha_In).grid(row = 6, column = 2)
#label CheckOut
L_ChkOut = Label(frame, text = 'Check-Out').grid(row = 7, column = 0, padx = 1, pady = 5)
#button registrar
ttk.Button(frame, text = 'Registrar' ).grid(row = 2, column = 6, padx = 10)
#button actualizar
ttk.Button(frame, text = 'Actualizar').grid(row = 4, column = 6, padx = 10)
def fecha_In(self):
self.fecha_in = Toplevel()
self.fecha_in.title = 'Fecha Check-In'
if __name__ == '__main__':
window = Tk()
style = ttk.Style(window)
style.theme_use('clam')
alien = PhotoImage(file = "Start Bits.png")
fondo = Label(window, image = alien).grid(row = 8, column = 0)
application = client(window)
window.mainloop()

tkinter window is blank after executing code

I'm starting to code with Python and on my first application I have reached a brick wall. Any help on why this code is not displaying the widgets will be greatly appreciated!
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class ImprintPlusApp:
def _init_(self, master):
self.frame_header = ttk.Frame(master)
self.frame_header.pack()
ttk.Label(self.header_frame, text = "Bienvenidos a Imprint Plus Manager")
self.frame_crearorden = ttk.Frame(master)
self.frame_crearorden.pack()
ttk.Label(self.frame_crearorden, text = "Nombre").grid(row = 0, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Email").grid(row = 2, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Numero Cel/Tel").grid(row = 4, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Información Adicional").grid(row = 6, column = 0, padx = 5)
self.entry_name = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_email = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_numtc = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_addinf = Text(self.frame_crearorden, width = 50, height = 10)
self.entry_name.grid(row = 0, column = 1, padx = 5)
self.entry_email.grid(row = 2, column = 1, padx = 5)
self.entry_numtc.grid(row = 4, column = 1, padx = 5)
self.entry_addinf.grid(row = 7, column = 0, columnspan = 2, padx = 5)
ttk.Button(self.frame_crearorden, text = "Submit", command = self.submit).grid(row = 8, columnspan = 1, padx = 5)
ttk.Button(self.frame_crearorden, text = "Clear", command = self.clear).grid(row = 8, columnspan = 0, padx = 5)
def submit(self):
print ("Nombre: {}".format(self.entry_name.get()))
print ("Email: {}".format(self.entry_name.get()))
print ("Num Cel/Tel: {}".format(self.entry_name.get()))
print ("Información Adicional: {}".format(self.entry_name.get(1.0, "end")))
self.clear()
messagebox.showinfo(tite = "Orden #", message = "Orden Guardada")
def clear(self):
self.entry_name.delete(0, "end")
self.entry_email.delete(0, "end")
self.entry_numtc.delete(0, "end")
self.entry_addinf.delete(1.0, "end")
def main():
root = Tk()
app = ImprintPlusApp()
root.mainloop()
if __name__ == '__main__':
main()
Everytime I launch the code I get a blank tkinter window.
This had a few problems.
You had an _init_ method, not an __init__ method, so the created object wasn't being initialized.
You have to send the root tkinter object to the application, with app = ImprintPlusApp(root).
You had a self.header_frame once instead of self.frame_header.
You had a columnspan = 0 (which is invalid) instead of columnspan = 1 (which doesn't really need to be specified).
I've made the above changes in the code below. It may still need debugging, as I don't know exactly what design you had in mind.
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class ImprintPlusApp:
def __init__(self, master):
self.frame_header = ttk.Frame(master)
self.frame_header.pack()
ttk.Label(self.frame_header, text = "Bienvenidos a Imprint Plus Manager")
self.frame_crearorden = ttk.Frame(master)
self.frame_crearorden.pack()
ttk.Label(self.frame_crearorden, text = "Nombre").grid(row = 0, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Email").grid(row = 2, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Numero Cel/Tel").grid(row = 4, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Información Adicional").grid(row = 6, column = 0, padx = 5)
self.entry_name = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_email = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_numtc = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_addinf = Text(self.frame_crearorden, width = 50, height = 10)
self.entry_name.grid(row = 0, column = 1, padx = 5)
self.entry_email.grid(row = 2, column = 1, padx = 5)
self.entry_numtc.grid(row = 4, column = 1, padx = 5)
self.entry_addinf.grid(row = 7, column = 0, columnspan = 2, padx = 5)
ttk.Button(self.frame_crearorden, text = "Submit", command = self.submit).grid(row = 8, columnspan = 1, padx = 5)
ttk.Button(self.frame_crearorden, text = "Clear", command = self.clear).grid(row = 8, columnspan = 1, padx = 5)
def submit(self):
print ("Nombre: {}".format(self.entry_name.get()))
print ("Email: {}".format(self.entry_name.get()))
print ("Num Cel/Tel: {}".format(self.entry_name.get()))
print ("Información Adicional: {}".format(self.entry_name.get(1.0, "end")))
self.clear()
messagebox.showinfo(tite = "Orden #", message = "Orden Guardada")
def clear(self):
self.entry_name.delete(0, "end")
self.entry_email.delete(0, "end")
self.entry_numtc.delete(0, "end")
self.entry_addinf.delete(1.0, "end")
def main():
root = Tk()
app = ImprintPlusApp(root)
root.mainloop()
if __name__ == '__main__':
main()

Categories