Why doesn't my style change the background of any of these objects? I got annoyed and just assigned them to everything. Also why does it make two windows? I see that it's something to do with style being different then the style in the object's options... I feel like it's also with my class, am I suppose to def _init_(self) it? the class?
import tkinter as tk
import tkinter.ttk as ttk
style = ttk.Style()
style.configure("color1.TFrame", foreground = "black", background = "red")
class main:
parent = tk.Tk()
n = ttk.Notebook(parent,style = "color1.TFrame")
f1 = ttk.Frame(n,style = "color1.TFrame") # first page tab
f2 = ttk.Frame(n,style = "color1.TFrame") # second page 2nd tab
window = f1
frame1 = ttk.Frame(window,style = "color1.TFrame")
frame1.grid(row = 1, column = 1, padx = 200, pady = 150)
frame2 = ttk.Frame(window)
frame2.grid(row = 2, column = 1,padx = 200, pady = 150)
main()
The reason why nothing seems to appear and your styles don't work is because you're not actually drawing all of your widgets.
You never tell the below widgets to actually draw on your window:
n
f1
f2
Additionally, a second window loads when you're calling ttk.Style() you haven't yet created a root window. This is explained much better than I could explain it here.
By changing your program to the below you can see that the styles do actually work:
import tkinter as tk
import tkinter.ttk as ttk
class main:
parent = tk.Tk()
style = ttk.Style()
style.configure("color1.TFrame", foreground = "black", background = "red")
n = ttk.Notebook(parent,style = "color1.TFrame")
n.pack()
f1 = ttk.Frame(n,style = "color1.TFrame") # first page tab
f2 = ttk.Frame(n,style = "color1.TFrame") # second page 2nd tab
window = f1
f1.pack()
f2.pack()
frame1 = ttk.Frame(window,style = "color1.TFrame")
frame1.grid(row = 1, column = 1, padx = 200, pady = 150)
frame2 = ttk.Frame(window)
frame2.grid(row = 2, column = 1,padx = 200, pady = 150)
main()
Arguably a better way of doing this would be something like the below:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
style = ttk.Style()
style.configure("color1.TFrame", foreground = "black", background = "red")
class main:
def __init__(self, root):
n = ttk.Notebook(root, style = "color1.TFrame")
f1 = ttk.Frame(n, style = "color1.TFrame")
f2 = ttk.Frame(n, style = "color1.TFrame")
n.pack()
f1.pack()
f2.pack()
frame1 = ttk.Frame(f1, style = "color1.TFrame")
frame2 = ttk.Frame(f1, style = "color1.TFrame")
frame1.grid(row = 1, column = 1, padx = 200, pady = 150)
frame2.grid(row = 2, column = 1,padx = 200, pady = 150)
main(root)
root.mainloop()
Although this is subjective and accomplishes the same goal.
Related
I'm trying to put a scrollbar on entry that created on canvas..
I've tried this code
from tkinter import *
root = Tk()
root.geometry('400x600')
root.resizable(0,0)
page = Canvas(root, width=400, height=600, bd=0, highlightthickness=0,scrollregion=(0,0,500,500))
MyImage1 = PhotoImage(file='Study With4.png')
CanvasImage = page.create_image(0,0,image= MyImage1, anchor='nw')
entry =Text(page,height=29,width =46,wrap=WORD,bg='#F8F8F8')
scroll = Scrollbar(entry, orient=VERTICAL)
scroll.pack(side=RIGHT, fill=Y)
scroll.config(command=page.yview)
page.config(yscrollcommand=scroll.set)
page.create_window(200,285, window=entry)
page.pack()
mainloop()
but it doesn't work and I don't know where is the problem.
I've made minimal changes to your code, the biggest is creating a Frame called "label"
to contain Text and Scrollbar then inserting that into Canvas window.
Your scroll object was not defined properly with confusion around page and entry objects.
from tkinter import *
root = Tk()
root.geometry('500x600')
root.resizable(0,0)
page = Canvas(
root, width = 500, height = 600, bd = 0,
highlightthickness = 0,scrollregion = (0,0,1000,1000))
page.pack(side = LEFT, fill = BOTH, expand = True)
MyImage1 = PhotoImage(file='Study With4.png')
CanvasImage = page.create_image(0, 0, image = MyImage1, anchor = NW)
label = Frame(root)
label.pack(fill = BOTH, expand = True)
entry = Text(label, height = 29, width = 46, wrap = NONE, bg = '#F8F8F8')
entry.pack(side = LEFT, fill = BOTH, expand = True)
scroll = Scrollbar(label, orient = VERTICAL)
scroll.pack(side=RIGHT, fill=Y)
scroll.config(command = entry.yview)
entry.config(yscrollcommand = scroll.set)
page.pack()
page.create_window(25, 25, window = label, anchor = NW)
mainloop()
Below is the main function I use in order to run two files of python but once I click on the buttuon my window freezes.Please tell me a way to perform multi threaading so that I can click both the buttons at once.
import pandas as pd
import numpy as np
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
import threading
import Test1
import Test2
# In[ ]:
def Load1():
Test1.func()
messagebox.showinfo( "Successful","Reconcilation Complete")
def Load2():
Test2.func()
try:
messagebox.showinfo( "Successful","Reconcilation Complete")
except Exception as inst:
messagebox.showinfo( "Unsuccessful",inst)
root = Tk()
root.geometry('375x100')
root.title("Reco")
root.configure(background="LightBlue2")
style = Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = Button(root, text = 'Tier Recon', command =threading.Thread(target=Load1).start )
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = Button(root, text = 'View Recon', command =threading.Thread(target=Load2).start)
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
root.mainloop()
I have assumed your Test1 and Test2 functions are somewhat infinite so I have created this as the format for my Test1.py and Test2.py:
# Test1.py / Test2.py
import tkinter as tk
def func():
while True:
root = tk.Tk()
root.mainloop()
Now with your code I would thoroughly recommend moving away from your current format and moving to Object Oriented Programming as it will save you many headaches in the future!
This here is the code I have written to make it work:
import tkinter as tk
import tkinter.ttk as ttk
import Test1
import Test2
class reco_win:
def __init__(self, master):
self.master = master
self.master.geometry('375x100')
self.master.configure(background="LightBlue2")
style = ttk.Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = ttk.Button(self.master, text = 'Tier Recon', command = lambda: self.master.after(1, self.load1))
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = ttk.Button(self.master, text = 'View Recon', command =lambda: self.master.after(1, self.load1))
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
def load1(self):
Test1.func()
def load2(self):
Test2.func()
def main():
root = tk.Tk()
reco_win(root)
root.mainloop()
if __name__ == '__main__':
main()
The important bit in this code:
self.master.after(1, self.load1)
What this line of code does is after 1 millisecond it will asynchronously start a new thread and execute the function Test1.func().
This means that you don't have to worry about the issues with managing the multithreading module in python and you can instead work on writing more code!
Hope this helps,
James
P.S.
If you are using a tk.Tk() window in your Test1/Test2.py you could instead use a tk.TopLevel window which would allow you to rewrite this code to read like so:
import tkinter as tk
import tkinter.ttk as ttk
import Test1
import Test2
class reco_win:
def __init__(self, master):
self.master = master
self.master.geometry('375x100')
self.master.configure(background="LightBlue2")
style = ttk.Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = ttk.Button(self.master, text = 'Tier Recon', command = self.load1)
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = ttk.Button(self.master, text = 'View Recon', command =self.load2)
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
def load1(self):
top = tk.Toplevel()
tk.Label(top, text="Hello").grid(row=0, column=0)
def load2(self):
top2 = tk.Toplevel()
tk.Label(top2, text="Hello 2").grid(row=0, column=0)
def main():
root = tk.Tk()
reco_win(root)
root.mainloop()
if __name__ == '__main__':
main()
I cannot for the life in me work out why this does not work. I am using TKinter to display an image in Python. The code I have written so far is shown here:
from tkinter import *
from tkinter import messagebox
def unlock():
root.withdraw()
def logout():
inside.destroy()
root.deiconify()
#######################
### ###
### unlock Form ###
### ###
#######################
inside = Tk()
inside.geometry("576x576")
inside.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside).grid(row =1, columnspan = 2)
label = Label(inside, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
exitButton = Button(inside, text = "Exit", width = 15, command = logout )
exitButton.grid(row = 3, column = 0,padx = 10, pady = 10)
#######################
### ###
### Main Form ###
### ###
#######################
root = Tk()
root.geometry("430x450")
root.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
label = Label(root, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
imageSafe = PhotoImage(file = "images/safe.gif")
imageLabel = Label(root,image = imageSafe).grid(row =1, columnspan = 2)
label = Label(root, text = "Enter the code", font = ("Arial",12)).grid(row = 2, column = 0)
unlockCode = Entry(root, width = 30)
unlockCode.grid(row = 2, column = 1,padx = 10, pady = 10)
exitButton = Button(root, text = "Exit", width = 15, command = exit).grid(row = 3, column = 0,padx = 10, pady = 10)
enterButton = Button(root, text = "Enter the VAULT", width = 15, command = unlock).grid(row = 3, column = 1,padx = 10, pady = 10)
The code doesn't do much at present, however it's something i'm working on. When I run the program it will display a picture of a safe (Great), and when I click the button it moves over to the next form.
image of safe working
On the new form the image, labels and buttons do not display, however, when the image code is removed it all works swimmingly.
Initially I thought about putting the root form within a function, however, whenever I place this code within a function it fails to load the image (ahhhh). Can these images not be placed within functions?
You need to keep a reference to the photo.
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside)
imageLabel.grid(row =1, columnspan = 2)
imageLabel.photo_ref = imageInside # keep a reference!
Thank you for your help.
I can confirm that this works, here's the code.
from tkinter import *
from tkinter import messagebox
def unlock():
root.withdraw()
def logout():
inside.destroy()
root.deiconify()
#######################
### ###
### unlock Form ###
### ###
#######################
inside = Toplevel()
inside.geometry("576x576")
inside.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside)
imageLabel.grid(row =1, columnspan = 2)
imageLabel.photo_ref = imageInside
label = Label(inside, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
exitButton = Button(inside, text = "Exit", width = 15, command = logout )
exitButton.grid(row = 3, column = 0,padx = 10, pady = 10)
#######################
### ###
### Main Form ###
### ###
#######################
root = Tk()
root.geometry("430x450")
root.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
label = Label(root, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
imageSafe = PhotoImage(file = "images/safe.gif")
imageLabel = Label(root,image = imageSafe).grid(row =1, columnspan = 2)
label = Label(root, text = "Enter the code", font = ("Arial",12)).grid(row = 2, column = 0)
unlockCode = Entry(root, width = 30)
unlockCode.grid(row = 2, column = 1,padx = 10, pady = 10)
exitButton = Button(root, text = "Exit", width = 15, command = exit).grid(row = 3, column = 0,padx = 10, pady = 10)
enterButton = Button(root, text = "Enter the VAULT", width = 15, command = unlock).grid(row = 3, column = 1,padx = 10, pady = 10)
I am trying to place an OptionMenu widget inside of a frame, which itself is inside of a notebook. From what I've found online, the code for doing this is roughly:
# add a drop down menu
hops = range(0,6)
self.selectedHop = StringVar(frame2)
self.selectedHop.set(hops[0])
self.hopOptions = OptionMenu(frame2, self.selectedHop, *hops)
self.hopOptions.grid(row=0, column=2, sticky=EW)
However, when I place this in my code in the code below (the chunk above is placed towards the bottom of it, and is labeled "PROBLEMATIC CODE..."), my app just freezes and I have to force quit it, and I have no error message to debug with. Any help would be appreciated.
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import subprocess
import sys
class ReportGUI:
def __init__(self, master):
self.master = master
master.title('Reporting')
master.resizable(True, True)
master.configure(background = '#b3e6cc')
master.minsize(width=800,height=700)
textcolor = "#003399"
self.style = ttk.Style()
self.style.configure('TFrame', background = '#e1d8b9')
self.style.configure('TButton', background = '#e1d8b9')
self.style.configure('TLabel', background = '#e1d8b9', font = ('Arial', 40))
self.style.configure('Header.TLabel', font = ('Arial', 30, 'bold'))
# step 1 - create notebook
self.notebook = ttk.Notebook(master)
self.notebook.pack()
# step 2 - create first frame to add to notebook
self.frame_logon = ttk.Frame(self.notebook)
# step 3 - add first frame to notebook and style it
self.notebook.add(self.frame_logon, text = 'Login')
self.frame_logon.config(padding = (20, 20, 20))
self.frame_logon.config(relief = RIDGE)
######### --- (1) LOGIN TAB ---- #########
label = ttk.Label(self.frame_logon, text = 'Administrative Reporting',
foreground=textcolor, style = 'Header.TLabel')
label.grid(row = 1, columnspan = 2)
# widget: username and password Label()
label2 = ttk.Label(self.frame_logon, text = 'Username:',
font = ('Arial', 17),foreground=textcolor)
label2.grid(row = 3, column = 0, padx = 5, sticky = 'sw')
label3 = ttk.Label(self.frame_logon, text = 'Password:',
font = ('Arial', 17),foreground=textcolor)
label3.grid(row = 3, column = 1, padx = 5, sticky = 'sw')
# widget: entry boxes Entry()
self.entry_name = ttk.Entry(self.frame_logon, width = 20, font = ('Arial', 15))
self.entry_pw = ttk.Entry(self.frame_logon, width = 20, font = ('Arial', 15))
# place the widgets
self.entry_name.grid(row = 4, column = 0, padx = 5)
self.entry_pw.grid(row = 4, column = 1, padx = 5)
self.entry_pw.config(show = '*') # make password not show
# widget: connect button Button()
self.loginButton = ttk.Button(self.frame_logon, text = 'Connect',
command = self.login)
self.loginButton.grid(row = 5, column = 1, columnspan = 2, padx = 1, pady = 1, sticky = 'e')
### COMMAND FUNCTIONS
def login(self):
# Make connections (TBA)
# 1) log into app
# 2) ssh into server port
# 3) connect to database
# if successful login and connection, launch reports tab
self.reportTab()
self.notebook.select(1) # switch tabs to reports tab
self.loginButton.state(['disabled']) # disable login button
# TAB 2: reporting tab
def reportTab(self):
# create report frame and add to notebook
self.frame_report = ttk.Frame(self.notebook)
self.notebook.add(self.frame_report, text = 'Report Options')
######### --- REPORT TAB ---- #########
#--------- FILTER 1: -----------
frame = ttk.Frame(self.frame_report)
frame.grid(row=1,column=0)
frame.config(height = 100, width = 200)
frame.config(relief = RIDGE)
ttk.LabelFrame(frame, height=100,width = 200,text = 'FILTER 1').pack()
#--------- FILTER 2: -----------
frame2 = ttk.Frame(self.frame_report)
frame2.grid(row=1,column=1)
frame2.config(height = 100, width = 200)
frame2.config(relief = RIDGE)
ttk.LabelFrame(frame2, height=100,width = 200,text = 'FILTER 2').pack()
#---------- PROBLEMATIC CODE: trying to add a drop down menu ----
hops = range(0,6)
self.selectedHop = StringVar(frame2)
self.selectedHop.set(hops[0])
self.hopOptions = OptionMenu(frame2, self.selectedHop, *hops)
self.hopOptions.grid(row=0, column=2, sticky=EW)
#----------------------------------------------------------------
#--------- FILTER 3: -----------
frame3 = ttk.Frame(self.frame_report)
frame3.grid(row=2,column=0)
frame3.config(height = 100, width = 200)
frame3.config(relief = RIDGE)
lbf3 = ttk.LabelFrame(frame3, height=100,width = 200,text = 'FILTER 3')
lbf3.pack()
#--------- FILTER 4: -----------
frame4 = ttk.Frame(self.frame_report)
frame4.grid(row=2,column=1)
frame4.config(height = 100, width = 200)
frame4.config(relief = RIDGE)
ttk.LabelFrame(frame4, height=100,width = 200,text = 'FILTER 4').pack()
# code for calling queries TBA
# launch results tab if queries successful
# self.resultsTab()
def func(self,value):
print(value)
# TAB 3: results tab
def resultsTab(self):
# create results frame and add to notebook
self.frame_results = ttk.Frame(self.notebook)
self.notebook.add(self.frame_results, text = 'Results')
def clear(self):
self.entry_name.delete(0, 'end')
self.entry_pw.delete(0, 'end')
self.text_comments.delete(1.0, 'end')
def main():
root = Tk()
hccwgui = ReportGUI(root)
root.mainloop()
if __name__ == "__main__": main()
Thanks in advance!
# ...
ttk.LabelFrame(frame2, height=100,width = 200,text = 'FILTER 2').pack()
# ...
self.hopOptions = OptionMenu(frame2, self.selectedHop, *hops)
self.hopOptions.grid(row=0, column=2, sticky=EW)
This is your problem. You're packing a LabelFrame in frame2, and then trying to grid something in frame2. A given container can only use one of grid() or pack()- using both won't cause an error, but the two managers will negotiate on how to place things for the rest of your lifetime.
The solution is to make sure that a given container's children are either packed or gridded, but never both in the same container (though you could have a structure parent->child->grandchild, where child is packed in parent and grandchild is gridded in child).
I have a string 'currentMessage' and a Label to display it.
I have a Toplevel widget, which contains a Text widget to provide new value for 'currentMessage':
from tkinter import *
from tkinter import ttk
root = Tk()
mainFrame = ttk.Frame(root)
mainFrame.grid()
currentMessage = 'current Message'
ttk.Label(mainFrame, text = currentMessage).grid(padx = 10, pady = 10)
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.textBox.get(0.0, END)
def changeValues():
popup = Toplevel(mainFrame)
popup.grid()
textBox = Text(popup, width = 20, height = 5)
textBox.grid(column = 0, row = 0)
textBox.insert(END, 'new message here')
b = ttk.Button(popup, command = lambda: updateCurrentMessage(popup))
b.grid(column = 0, row = 1, padx = 5, pady = 5)
b['text'] = 'Update'
theButton = ttk.Button(mainFrame, command = changeValues, text = 'Click')
theButton.grid(padx = 10, pady = 10)
mainFrame.mainloop()
I tried to get the content of 'textBox' Text widget of the Toplevel by using this function:
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.textBox.get(0.0, END)
But I got an error
'Toplevel' object has no attribute 'textBox'
So how do I access content of the widget 'textBox', which is a child widget of 'popup' (this Toplevel widget is only created when function changeValues() is called)?
I think probably this is what you are looking for -- although I'm just guessing, because you are asking for a solution for a specific problem you think you have, however if I were you I would rethink what exactly do I want to do:
from tkinter import *
from tkinter import ttk
# Create Tk Interface root
root = Tk()
# Initialize mainFrame
mainFrame = ttk.Frame( root )
mainFrame.grid()
# Initialize label of mainframe
theLabel = ttk.Label( mainFrame, text='Current Message' )
theLabel.grid( padx=10, pady=10 )
def createPopup():
# Initialize popup window
popup = Toplevel( mainFrame )
popup.grid()
# Initialize text box of popup window
textBox = Text( popup, width=20, height=5 )
textBox.grid( column = 0, row = 0 )
textBox.insert( END, 'New Message Here' )
# Initialize button of popup window
button = ttk.Button( master = popup,
command = lambda: theLabel.config(text=textBox.get(0.0, END)),
text = 'Update')
button.grid( column=0, row=1, padx=5, pady=5 )
# Initialize button of main frame
theButton = ttk.Button( mainFrame, command=createPopup, text='Click' )
theButton.grid( padx=10, pady=10 )
# Enter event loop
mainFrame.mainloop()
There is a way indeed, like this:
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.nametowidget('textBox').get(0.0, END)
def changeValues():
popup = Toplevel(mainFrame)
popup.grid()
textBox = Text(popup, width = 20, height = 5, name = 'textBox')
textBox.grid(column = 0, row = 0)
textBox.insert(END, 'new message here')
b = ttk.Button(popup, command = lambda: updateCurrentMessage(popup))
b.grid(column = 0, row = 1, padx = 5, pady = 5)
b['text'] = 'Update'
You can choose whatever you want for the 'name'.