i am fairly new to coding and am having a problem with tkinter. I'm trying to add a calendar widget to a specific frame however, when i run the program, the calendar and my frame1 both pop up even though the calendar is suppose to be on frame2. Im sure im doing something stupid but for the life of me can't figure out what this is. Any help would be much appretiated.
import tkinter as tk
from tkinter import *
from tkcalendar import Calendar
root = Tk()
def show_frame(frame):
frame.tkraise()
def grad_date():
date.config(text = "Appointment date is: " + cal.get_date())
cal = Calendar(root, selectmode = 'day',year = 2022, month = 1,day = 29)
window = tk.Tk()
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
frame1 = tk.Frame(window)
frame2 = tk.Frame(window)
for frame in (frame1, frame2):
frame.grid(row=0,column=0,sticky='nsew')
##### frame 1 code
frame1_title= tk.Label(frame1, text='Home', bg='red')
frame1_title.pack(fill='x')
frame1_btn = tk.Button(frame1,text='Calendar', command=lambda:show_frame(frame2))
frame1_btn.pack()
##### frame 2 code
frame2_title= tk.Label(frame2, text='Calendar', bg='blue')
frame2_title.pack(fill='x')
cal.pack(pady = 20)
Button(root, text = "Confirm appointment date",
command = grad_date).pack(pady = 20)
date = Label(root, text = "")
date.pack(pady = 20)
frame2_btn = tk.Button(frame2, text='home', command=lambda:show_frame(frame1))
frame2_btn.pack()
show_frame(frame1)
window.mainloop()
Related
First: In code below i want to use instead of default rectangle button, images prepared by myslef.
This generates some problems (mayby with reference)? This button does not appear as image, also i am not able to use function (name: load_frame_insert()) after click.
Second: I wonder to have 2 bbtns:
Normal: assets/insert_data.png
OnClick: assets/insert_data2.png
Could you help me?
PS. Doesn't work after moving from up-down code to code with functions
import pyodbc
import pandas as pd
import os
import tkinter as tk
from PIL import ImageTk
# DB connector
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};'
'SERVER=onyx1905;'
'DATABASE=DW_15;'
'Trusted_Connection=yes')
# variables
name = os.getlogin()
cursor = conn.cursor()
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
global img_button_1
def image_button_1(size):
img = tk.PhotoImage(file="assets/insert_data.png")
img = img.subsample(size, size)
return img
#button img: insert_data
#button img: insert_data_on_click
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = ImageTk.PhotoImage(file="assets/xrdl_logo.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f" Hi {name}, please choose an action "),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
# btn code on 1st frame
tk.Button(
frame_main,
image=image_button_1(1),
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
).pack(pady=5)
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
conn.close()
other related topics but doesnt work
youtube tutorials
For the statement command=image_button_1(1), the image returned by image_button_1(1) will be garbage collected because there is no variable referencing it. That is why you get a button without image.
You need to save the reference of the image, for example using an attribute of the button as below:
image = image_button_1(1)
btn = tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
)
btn.pack(pady=5)
btn.image = image # save the reference of the image
I removed three libraries.
I removed image_button_1 function
Added image = tk.PhotoImage(file="p1.png")
Added variable for Button
Change 5 to 25 .pack(pady=25)
Removed lambda and brace bracket command=load_frame_insert
Snippet:
import os
import tkinter as tk
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = tk.PhotoImage(file="p2.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f"Hi please choose an action"),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
image = tk.PhotoImage(file="p1.png")
# btn code on 1st frame
btn= tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=load_frame_insert
)
btn.pack(pady=25)
btn.image = image
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
Screenshot:
Just a simple example of a problem I experienced:
from tkinter import *
root = Tk()
frame = Frame(root)
label = Label(frame, text = "Hey")
label.pack()
def packframe():
frame.pack()
def destroyframe():
frame.destroy()
pack_button = Button(root, text = "pack", command = packframe)
pack_button.pack()
des_button = Button(root, text = "destroy", command = destroyframe)
des_button.pack()
Once I press the destroy button, I cannot pack it back again on the screen with the pack_button. Im not sure why is it so, but I would appreciate both explanaition and a solution
I have a button that adds a DateEntry widget to a scrollable frame. Unfortunately, the frame is at the bottom of the window, so after adding a few rows, the dropdown calendar hides behind the task bar. Is there any way to change it, so the calendar opens above the field, rather than below?
Here is some test code
from tkinter import *
from tkinter import ttk
from tkcalendar import Calendar, DateEntry
master = Tk()
global rowNumForShiftReport
rowNumForShiftReport=0
shiftDateWidgetList=[]
def myfunction(event):
canvas2.configure(scrollregion=canvas2.bbox("all"), width=100, height=100)
def addEntry2():
global rowNumForShiftReport
rowNumForShiftReport = rowNumForShiftReport + 1
shiftDateWidgetList.append(DateEntry(frame2, state='readonly', width=15))
shiftDateWidgetList[-1].grid(row=rowNumForShiftReport, column=0)
rowNumForShiftReport+1
master.geometry('400x400')
btn_addField2 = ttk.Button(master, text="Add Entry",command=addEntry2)
btn_addField2.grid(row=0, column=1)
#lotFrame2 = Frame(master)
actualLabelFrame=ttk.LabelFrame(master, text="Shift Report", height=300, width=300)
actualLabelFrame.grid(row=0, column=0)
canvas2 = Canvas(actualLabelFrame,width=160)
frame2 = Frame(canvas2,width=160)
frame2.bind("<Configure>", myfunction)
canvas2.create_window((0, 0), window=frame2, anchor='nw')
scrollBar2 = ttk.Scrollbar(actualLabelFrame, orient="vertical", command=canvas2.yview)
canvas2.configure(yscrollcommand=scrollBar2.set)
scrollBar2.grid(row=0, column=2, sticky=N + S)
canvas2.grid(row=0, column=1)
mainloop()
You can achieve the goal by extending DateEntry and override its drop_down() function as below:
class MyDateEntry(DateEntry):
def drop_down(self):
"""Display or withdraw the drop-down calendar depending on its current state."""
if self._calendar.winfo_ismapped():
self._top_cal.withdraw()
else:
self._validate_date()
date = self.parse_date(self.get())
x = self.winfo_rootx()
y = self.winfo_rooty() + self.winfo_height()
if self.winfo_toplevel().attributes('-topmost'):
self._top_cal.attributes('-topmost', True)
else:
self._top_cal.attributes('-topmost', False)
# - patch begin: make sure the drop-down calendar is visible
if x+self._top_cal.winfo_width() > self.winfo_screenwidth():
x = self.winfo_screenwidth() - self._top_cal.winfo_width()
if y+self._top_cal.winfo_height() > self.winfo_screenheight()-30:
y = self.winfo_rooty() - self._top_cal.winfo_height()
# - patch end
self._top_cal.geometry('+%i+%i' % (x, y))
self._top_cal.deiconify()
self._calendar.focus_set()
self._calendar.selection_set(date)
Then replace all DateEntry(...) by MyDateEntry(...) in your code.
Note that it is based on tkcalendar v1.6.1.
I am trying to create the buttons using tkinter.
Here is my code
import tkinter as tk
def pressed():
print("button pressed!")
def create_layout(frame):
frame.pack(fill=None,expand=True)
mycolor = '#%02x%02x%02x' % (250, 250, 210)
root.configure(bg=mycolor)
bottomframe = tk.Frame(root)
bottomframe.pack( side = tk.LEFT )
button1 = tk.Button(frame, text="Button1", fg="black",command=pressed,anchor="w")
button1.pack( side = tk.LEFT)
button2 =tk.Button(frame, text="Button2", fg="black",command=pressed,anchor="w")
button2.pack( side = tk.LEFT )
root = tk.Tk()
root.geometry("250x150")
frame = tk.Frame(root)
create_layout(frame)
root.mainloop()
I have specified the anchor="w", and side="LEFT", but it does not seem to be work.
Output of the code:
Changing frame.pack(fill=None,expand=True) to frame.pack(fill=None,expand=True, anchor="w") will align the buttons to the left side.
I got this problem. when I write secretframe() I get a empty box any ideas to fix this? Also how can I put a little space between the 2 frames.
I'm new to tkinter and any tips is gladly appreciated.
import tkinter as tk
import time
import math
##----------Functions
root = tk.Tk()
def Pi():
pi = math.pi
x = list(str(pi))
map(int,x)
print(math.pi)
def Unfinished():
print("This Button is not finished")
def secretframe(frame):
secrett = tk.Toplevel()
sframe = tk.Frame(secrett, height="300", width="300", bg="PeachPuff")
sLabel = tk.Label(sframe, text="Secret")
sframe.grid
sLabel.grid
##Defining
##Frames
frame = tk.Frame(root, height="300", width="300", bg="Black")
Mframe = tk.Frame(root, height="300", width="300", bg="White")
##WIdgets
Label = tk.Label(frame, text="R1p windows", bg="Black", fg="White")
Label2 = tk.Label(Mframe, text="Math magic", bg="White", fg="Black")
Knapp = tk.Button(frame, text="ok(ADMIN)", fg="White", bg="Black", font="monospace")
PIKnapp = tk.Button(Mframe, text="Pi(WIP)(UNFINISHED)", bg="White", fg="Black", font="Times")
##Config and bindings
Knapp.config(command=Unfinished)
PIKnapp.config(command=Pi)
##Packing
## Frame 1
Label.grid()
frame.grid()
Knapp.grid()
## Frame 2
Label2.grid()
Mframe.grid()
PIKnapp.grid()
You've forgotten the brackets. Try:
sframe.grid ()
sLabel.grid ()