Related
I have this code in tkinter, all in one file, where I have a main window that has a frame as a menu and another frame that is the main screen. The menu calls other frames that are defined with their respective content. What I want to do is to pass each one of these frames, as inicio_page() to another file so that the code is not so long and also to be able to call them to the main file and that it is still functional.
Actually an example would be like this
from tkinter import *
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Test")
app_width = 1300
app_height = 720
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
x = (screen_width /2) - (app_width / 2)
y = (screen_height /3) - (app_height / 3)
self.geometry(f"{app_width}x{app_height}+{int(x)}+{int(y)}")
self.minsize(width=1300, height=720)
self.maxsize(width=1920, height=1080)
backg = PhotoImage(file="img/trineside.png")
backg1 = PhotoImage(file="img/prueba4.png")
def delete_pages():
for frame in main_frame.winfo_children():
frame.destroy()
def indicate(lb, page):
hide_indicators()
lb.config(bg="white")
delete_pages()
page()
def hide_indicators():
page1_indicate.config(bg="#124e6b")
page2_indicate.config(bg="#124e6b")
menu_frame = tk.Frame(self, bg="#124e6b", highlightbackground="black", highlightthickness=1)
menu_frame.pack(side=tk.LEFT)
menu_frame.pack_propagate(False)
menu_frame.configure(width=195, height=1020)
background_menuframe= Label(menu_frame, image=backg)
background_menuframe.place(x=0, y=0, relwidth=1, relheight=1)
inicio_btn = tk.Button(menu_frame, text="Page1", font=("Bold", 18), fg="white", bd=0, bg="#124e6b", padx=56, activebackground='#124e6b', command=lambda: indicate(page1_indicate, inicio_page))
inicio_btn.place(x=10, y=100)
page1_indicate = tk.Label(menu_frame, text="", bg="#124e6b")
page1_indicate.place(x=3, y=100, width=5, height=43)
#########################################################
clientes_btn = tk.Button(menu_frame, text="Page2", font=("Bold", 18), fg="white", bd=0, bg="#124e6b",padx=40, command=lambda: indicate(page2_indicate, page_2))
clientes_btn.place(x=10, y=150)
page2_indicate = tk.Label(menu_frame, text="", bg="#124e6b")
page2_indicate.place(x=3, y=150, width=5, height=43)
#########################################################
main_frame = tk.Frame(self, highlightbackground="black", highlightthickness=1)
background_mainframe= Label(main_frame, image=backg1)
background_mainframe.place(x=0, y=0, relwidth=1, relheight=1)
main_frame.pack(side=tk.LEFT)
main_frame.pack_propagate(False)
main_frame.configure(height=1020, width=1750)
lb = tk.Label(main_frame, text="Try", font=("bold", 50))
lb.pack(pady=100)
def inicio_page():
background_mainframe= Label(main_frame, image=backg1)
background_mainframe.place(x=0, y=0, relwidth=1, relheight=1)
inicio_frame = tk.Frame(main_frame)
titulo_principal = tk.Label(main_frame,text="INICIO", font=("Bold", 15), bg="#031f3f", fg="white", height="2")
titulo_principal.pack(fill=tk.X)
inicio_frame.pack(pady=80)
#frames
f1_frame = tk.Frame(inicio_frame, bg="yellow", width=600, height=150)
f1_frame.pack()
f2_frame = tk.Frame(inicio_frame, width=500, height=400)
f2_frame.pack()
box1 = tk.Frame(f2_frame, height=20,width=250)
box1.grid(row=0, column=0)
box2 = tk.Frame(f2_frame, height=20,width=250)
box2.grid(row=0, column=1)
btn_logs = Button(box1,text="Abrir Logs",width=18)
btn_logs.pack(pady=20,padx=80)
btn_informes = Button(box2,text="Abrir Informes", width=18)
btn_informes.pack(pady=20,padx=80)
textof1 = Label(f1_frame, text="")
textof1.pack()
if __name__ == "__main__":
app = App()
app.mainloop()
What I did was to pass the inicio_page() function to another file and modify the button command to call the new class. My problem is that when I click on the button it does not show me the content that is in the InicioPage class.
I leave an example of what I tried.
from tkinter import *
import tkinter as tk
from frame_inicio import InicioPage
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Test")
app_width = 1300
app_height = 720
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
x = (screen_width /2) - (app_width / 2)
y = (screen_height /3) - (app_height / 3)
self.geometry(f"{app_width}x{app_height}+{int(x)}+{int(y)}")
self.minsize(width=1300, height=720)
self.maxsize(width=1920, height=1080)
backg = PhotoImage(file="img/trineside.png")
backg1 = PhotoImage(file="img/prueba4.png")
def delete_pages():
for frame in main_frame.winfo_children():
frame.destroy()
menu_frame = tk.Frame(self, bg="#124e6b", highlightbackground="black", highlightthickness=1)
menu_frame.pack(side=tk.LEFT)
menu_frame.pack_propagate(False)
menu_frame.configure(width=195, height=1020)
background_menuframe= Label(menu_frame, image=backg)
background_menuframe.place(x=0, y=0, relwidth=1, relheight=1)
inicio_btn = tk.Button(menu_frame, text="Inicio", font=("Bold", 18), fg="white", bd=0, bg="#124e6b", padx=56, activebackground='#124e6b', command=lambda: delete_pages() and InicioPage(main_frame))
inicio_btn.place(x=10, y=100)
page1_indicate = tk.Label(menu_frame, text="", bg="#124e6b")
page1_indicate.place(x=3, y=100, width=5, height=43)
#########################################################
clientes_btn = tk.Button(menu_frame, text="Page2", font=("Bold", 18), fg="white", bd=0, bg="#124e6b",padx=40, command=lambda: indicate(page2_indicate, page_2))
clientes_btn.place(x=10, y=150)
page2_indicate = tk.Label(menu_frame, text="", bg="#124e6b")
page2_indicate.place(x=3, y=150, width=5, height=43)
#########################################################
main_frame = tk.Frame(self, highlightbackground="black", highlightthickness=1)
background_mainframe= Label(main_frame, image=backg1)
background_mainframe.place(x=0, y=0, relwidth=1, relheight=1)
main_frame.pack(side=tk.LEFT)
main_frame.pack_propagate(False)
main_frame.configure(height=1020, width=1750)
lb = tk.Label(main_frame, text="Try", font=("bold", 50))
lb.pack(pady=100)
frame_inicio.py
from tkinter import *
import tkinter as tk
class InicioPage:
def __init__(self, main_frame):
self.frame = tk.Frame(main_frame)
backg1 = PhotoImage(file="img/prueba4.png")
background_mainframe= Label(main_frame, image=backg1)
background_mainframe.place(x=0, y=0, relwidth=1, relheight=1)
inicio_frame = tk.Frame(main_frame)
titulo_principal = tk.Label(main_frame,text="INICIO", font=("Bold", 15), bg="#031f3f", fg="white", height="2")
titulo_principal.pack(fill=tk.X)
inicio_frame.pack(pady=80)
#frames
f1_frame = tk.Frame(self.frame, bg="yellow", width=600, height=150)
f1_frame.pack()
f2_frame = tk.Frame(self.frame, width=500, height=400)
f2_frame.pack()
box1 = tk.Frame(f2_frame, height=20,width=250)
box1.grid(row=0, column=0)
box2 = tk.Frame(f2_frame, height=20,width=250)
box2.grid(row=0, column=1)
btn_logs = Button(box1,text="Abrir Logs",width=18)
btn_logs.pack(pady=20,padx=80)
btn_informes = Button(box2,text="Abrir Informes", width=18)
btn_informes.pack(pady=20,padx=80)
You aren't instantiating the class InicioPage anywhere I can see. You'll need to create an instance of InicioPage with the desired parent like so:
from frame_inicio import InicioPage
... # other code has been omitted for brevity
# FYI, widgets that are defined within a class should be prefixed with 'self.'
# e.g.: 'self.main_frame = tk.Frame', 'self.main_frame.pack()', etc.
main_frame.pack(side=tk.LEFT)
self.start_page = InicioPage(main_frame) # instantiate the class object to use it
Note that for the expression delete_pages() and InicioPage(main_frame), InicioPage(main_frame) will never be executed because delete_pages() returns None which is evaluated as False in the expression.
Either return True from delete_pages() or change and to or in the expression.
Got from #JRiggles's example.
In line 49 change this:
clientes_btn = tk.Button(menu_frame, text="Page2", font=("Bold", 18), fg="white", bd=0, bg="#124e6b",padx=40, command=lambda: InicioPage(page2_indicate))
to:
clientes_btn = tk.Button(menu_frame, text="Page2", font=("Bold", 18), fg="white", bd=0, bg="#124e6b",padx=40, command=lambda: InicioPage(main_frame))
frame_inicio.py.
Add this self.frame.mainloop() to bottom
Screenshot:
Screenshot when pressed page 2 button:
I'm working on GUI project and I'm trying to configure a button color and text but it gives me an error..
here is a sample of my code:
from tkinter import*
from tkinter import ttk
#root
root = Tk()
root.geometry('640x520')
#Canvas
myCanvas = Canvas(root, width=350, height=300, bd=0, highlightthickness=0)
myCanvas.pack(fill='both', expand=True)
def qu1():
global myCanvas
myCanvas.itemconfig(Q1,bg='green',text= 'Done')
Q1 = Button(root, width=15, height=10, bg='#F3C4B7',fg='white', text='1', command=qu1)
myCanvas.create_window(10,10, anchor='nw', window=Q1)
root.mainloop()
it gives me this error:
line 12, in qu1
myCanvas.itemconfig(Q1,bg='green',text= 'Done')
_tkinter.TclError: invalid boolean operator in tag search expression
Already stated:
itemconfig applies to Canvas objects
You can do:
from tkinter import*
root = Tk()
root.geometry('640x520')
myCanvas = Canvas(root, width=350, height=300, bd=0, highlightthickness=0)
myCanvas.pack(fill='both', expand=True)
buttonBG = myCanvas.create_rectangle(0, 0, 100, 30, fill="grey40", outline="grey60")
buttonTXT = myCanvas.create_text(50, 15, text="click")
def qu1(event):
myCanvas.itemconfig(buttonBG, fill='red')
myCanvas.itemconfig(buttonTXT, fill='white')
myCanvas.tag_bind(buttonBG, "<Button-1>", qu1)
myCanvas.tag_bind(buttonTXT, "<Button-1>", qu1)
root.mainloop()
Or change the button itself:
from tkinter import*
root = Tk()
root.geometry('640x520')
myCanvas = Canvas(root, width=350, height=300, bd=0, highlightthickness=0)
myCanvas.pack(fill='both', expand=True)
def qu1():
Q1.configure(bg="#234")
Q1 = Button(root, width=15, height=10, bg='#F3C4B7',fg='white', text='1', command=qu1)
myCanvas.create_window(10,10, anchor='nw', window=Q1)
root.mainloop()
I'm making a game in my high school computer science class and the score is supposed to increase every time the a key is pressed.
from Tkinter import *
root = Tk()
score = 0
canvas = Canvas(root, height=600, width=600, relief=RAISED, bg='brown')
canvas.grid()
canvas.grid(row=0, column=1)
img = PhotoImage(file='C:\\Users\\s27538750\\Desktop\\Create_Task\\Bench-
Press.gif')
img2 = PhotoImage(file='C:\\Users\\s27538750\\Desktop\\Create_Task\\Bench-
Press-Up.gif')
canvas.create_image(300, 300, image=img)
canvas.create_text(300, 50, text= 'SWOLE PEEP SIMULATOR!', font=0)
from Tkinter import *
def key(event):
global score
canvas.create_image(300, 300, image=img2)
score += 1
canvas.create_text(70, 50, text= score)
def callback(event):
canvas.focus_set()
canvas.bind("a", key)
canvas.bind("<Button-1>", callback)
canvas.pack()
def key(event):
canvas.create_image(300, 300, image=img)
canvas.bind("b", key)
canvas.create_text(50, 50, text= 'Score: ')
root.mainloop()
While that part of the code works, when the score is updated the previous score
numbers remain on the GUI.
I'm not able to test it, but the following code should work:
from Tkinter import *
root = Tk()
score = 0
canvas = Canvas(root, height=600, width=600, relief=RAISED, bg='brown')
canvas.grid()
canvas.grid(row=0, column=1)
img = PhotoImage(file='C:\\Users\\s27538750\\Desktop\\Create_Task\\Bench-
Press.gif')
img2 = PhotoImage(file='C:\\Users\\s27538750\\Desktop\\Create_Task\\Bench-
Press-Up.gif')
canvas.create_image(300, 300, image=img)
canvas.create_text(300, 50, text= 'SWOLE PEEP SIMULATOR!', font=0)
from Tkinter import *
def key(event):
global score
canvas.create_image(300, 300, image=img2)
score += 1
canvas.itemconfig(score_text, text = score)
def callback(event):
canvas.focus_set()
canvas.bind("a", key)
canvas.bind("<Button-1>", callback)
canvas.pack()
def key(event):
canvas.create_image(300, 300, image=img)
canvas.bind("b", key)
score_text = canvas.create_text(50, 50, text= 'Score: ')
root.mainloop()
I'm creating a cookie clicker app using Tkinter. I want to have a progress bar in my program that fills up every time the cookie is clicked 100 times. I have created the progress bar using import ttk, however I don't know how to make the progress bar update whenever the button is pressed.
Here is my code so far:
from Tkinter import *
from Tkinter import Canvas
import ttk
window1 = Tk()
window1.title("Cookie Clicker")
window1.config(background="dodger blue")
window1.geometry("254x370")
clicks = 0
def cookie_clicks():
global clicks
clicks = clicks + 1
print("{0}".format(clicks))
if clicks == 1:
lbl1.configure(text="{0} Cookie!".format(clicks))
else:
lbl1.configure(text="{0} Cookies!".format(clicks))
cookie = Button(window1, highlightbackground="dodger blue", borderwidth=0, cursor="hand2", command=cookie_clicks)
photo = PhotoImage(file="imageedit_3_3213999137.gif")
cookie.config(image=photo, width="250", height="250")
cookie.place(x=0, y=90)
w = Canvas(window1, width=254, height=75, highlightbackground="gray")
w.pack()
w.create_rectangle(10, 10, 80, 80, outline="gray", fill="gray", width=100000)
w2 = Canvas(window1, width=0.1, height=250, highlightbackground="dodger blue")
w2.place(x=0, y=85)
w3 = Canvas(window1, width=0.1, height=250, highlightbackground="dodger blue")
w3.place(x=249, y=85)
w4 = Canvas(window1, width=250, height=0.1, highlightbackground="dodger blue")
w4.place(x=0, y=88)
w5 = Canvas(window1, width=250, height=0.1, highlightbackground="dodger blue")
w5.place(x=0, y=338)
lbl1 = Label(window1, bg="gray", fg="dodger blue", text="{0} Cookies!".format(clicks), font=("kavoon", 20))
lbl1.place(x=75, y=45)
lbl2 = Label(window1, bg="gray", fg="dodger blue", text="Cookie Clicker", font=("kavoon", 30))
lbl2.place(x=20, y=0)
pb = ttk.Progressbar(window1, orient='horizontal', mode='determinate')
pb.pack()
window1.mainloop()
Any help would be appreciated!
Without changing your code much, you can do:
def cookie_clicks():
global clicks, pb
clicks = clicks + 1
pb.step(1)
print("{0}".format(clicks))
if clicks == 1:
lbl1.configure(text="{0} Cookie!".format(clicks))
else:
lbl1.configure(text="{0} Cookies!".format(clicks))
It is not great to use global variables. You should look into encapsulating your app in a class.
I need to draw two arrows from the blue and green box pointing to the yellow box. I tried drawing diagonal lines using create_line but it didn't work. can anyone please suggest any ways I could draw these arrows.
the error message when using create_line is: AttributeError: '_tkinter.tkapp' object has no attribute 'create_line'
from tkinter import *
import tkinter as tk
window = Tk()
window.geometry("900x500")
window.configure(background='red')
window.title("Theoretical")
label1 = Label(window, text="Hess' cycle of combustion", fg="black", bg="red", font=("Comic Sans MS", 20))
label1.pack()
text1 = Text(window, width=20, height = 1, bg= "blue")
text1.place(x=200, y=100)
window.create_line(0, 0, 200, 100)
window.create_line(0, 100, 200, 0, fill="white")
text2 = Text(window, width=20, height = 1, bg= "green")
text2.place(x=520, y=100)
text3 = Text(window, width=20, height = 1, bg= "yellow")
text3.place(x=370, y=250)
## arrow = Label(window, width=13,height = 1, text = "-------------->", bg= "lawn green", font=("Helvetica", 20))
## arrow.place(x= 330, y=90)
global textbox
textbox = Text(window, width=400, height=10)
textbox.place(x=0, y= 365)
tkinter lines have an arrow option; however, as pointed out in te comments,create_line is a Canvas method: you must therefore use a tk.Canvas object to draw lines:
This minimum example shows you how:
import tkinter as tk
window = tk.Tk()
canvas = tk.Canvas(window)
canvas.pack()
canvas.create_line(0, 0, 200, 100, arrow=tk.LAST)
window.mainloop()
Please note that to avoid "hard to fix" problems and unexpected behavior, it is usually recommended not to import modules in the main namespace (i/e do not from tkinter import *), and not to mix geometry managers ((i/e do not use .place and .pack in the same app)
Edit:
In order to place widgets on a canvas, you must use the Canvas.create_window() method:
import tkinter as tk
window = tk.Tk()
window.geometry("600x600")
canvas = tk.Canvas(window, width=600, height=600)
label_1 = tk.Label(window, text = "from here", anchor = tk.W)
label_1.configure(width = 10, activebackground = "#33B5E5", relief = tk.FLAT)
label_1_window = canvas.create_window(280, 0, anchor=tk.NW, window=label_1)
label_2 = tk.Label(window, text = "to there", anchor = tk.W)
label_2.configure(width = 10, activebackground = "#33B5E5", relief = tk.FLAT)
label_2_window = canvas.create_window(280, 310, anchor=tk.NW, window=label_2)
canvas.pack()
canvas.create_line(300, 40, 300, 300, arrow=tk.LAST)
window.mainloop()