I am wanting to change the borderwidth and relief of a ttk combobox. But I only want to change these attributes for 1 combobox. Is there a way to make the second combobox have a borderwidth of 3 and a relief of solid, like the text box 2?
import tkinter as tk
from tkinter import font as tkfont, filedialog, messagebox
from tkinter.ttk import Combobox
class SLS_v1(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Setting up the root window
self.title('APP')
self.geometry("552x700")
self.resizable(False, False)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frames["MenuPage"] = MenuPage(parent=container, controller=self)
self.frames["MenuPage"].grid(row=0, column=0, sticky="nsew")
self.show_frame("MenuPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class MenuPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
text1 = tk.Text(self, width=25, height=1)
text1.pack(pady=20)
combobox1 = tk.ttk.Combobox(self, width=25, height=2, state='readonly')
combobox1.pack(pady=20)
text2 = tk.Text(self, width=50, borderwidth=3, relief='solid', height=1)
text2.pack(pady=20)
combobox2 = tk.ttk.Combobox(self, width=50, height=5, state='readonly')
combobox2.pack(pady=20)
if __name__ == "__main__":
app = SLS_v1()
app.mainloop()
To change ttk objects you must define the style like this.
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.style = ttk.Style(self)
self.style.theme_use("default")
Then you can define specifics for your Combobox like this.
self.style.configure("K.TCombobox",
**dict(
padding = 1, arrowsize = 12,
borderwidth = 3, relief = "solid"))
Complete implementation like this.
combobox2 = Combobox(self, width=50, height=5, state='readonly', style = "K.TCombobox")
Related
I want to pass variable n from startpage to page1. Then put the variable into a label widget called label_country. How can I do this within tkinter? I tried calling the variable by the class and I also used the n.get() method.
import tkinter as tk
from tkinter import ttk
class tkinterApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self, height=1000, width=1000, bg="gray")
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, Page1):
frame = F(container, self)
self.frames[F] = frame
frame.place(relx=0, rely=0, relwidth=1, relheight=1)
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="gray")
style = ttk.Style()
style.configure('W.TButton', foreground='black', background='white'
)
button = ttk.Button(self, text="slect a country ", style='W.TButton',
command=lambda: [ controller.show_frame(Page1)])
button.place(relx=0.66, rely=0.05, relwidth=0.2, relheight=0.07)
ttk.Label(self, text="country slect:").place(relx=0.14, rely=0.05, relwidth=0.5, relheight=0.07)
n = tk.StringVar()
country_choice = ttk.Combobox(self, width=27, textvariable=n)
country_choice["values"] = ([x for x in df["Country"].unique()])
country_choice.place(relx=0.14, rely=0.05, relwidth=0.5, relheight=0.07)
country_choice.current()
text_box = tk.Text(self, height=28, width=30, bg="white")
text_box.insert(tk.INSERT, "INFORMATIONT ABOUT THE PROGRAM")
text_box.config(state="disabled")
text_box.place(relx=0.14, rely=0.15, )
class Page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="gray")
label_country = tk.Label(self, text= StartPage.n, bg = "white")
label_country.place(relx=0.795, rely=0.13, relwidth=0.0755, relheight=0.03)
app = tkinterApp()
app.mainloop()
import tkinter as tk
from tkinter import *
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
class pages(tk.Tk):
#starts us off in the login page
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "ScanNET")
tk.Tk.wm_minsize(self, 800, 800)
container = tk.Frame(self)
container.pack(side=TOP, fill=BOTH, expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky=N+E+S+W)
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
#the tabs
my_notebook = ttk.Notebook(self.root)
my_notebook.pack()
devicestab = Frame(my_notebook, width=800, height=600)
reportstab = Frame(my_notebook, width=800, height=600)
devicestab.pack(fill=BOTH, expand=1)
reportstab.pack(fill=BOTH, expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = pages()
app.mainloop()
When I run this, both the loginpage and GUI windows open. Correct me if I'm wrong, but I think the problem is probably around the
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
my_notebook = ttk.Notebook(self.root)
part in the GUI class. I've searched everywhere and I can't seem to find a way to have a first page as a login page which will move to a second page that has tabs using notebook. I feel as if something else has to be in the ttk.Notebook() part, and perhaps remove self.root = tk.Tk() after. I'd love to hear what y'all think.
I am assuming you want the notebook in the same widget of the rest, so you should not use tk.Tk() and then you place the notebook in the parent which is already your root. Check the code in the end of my answer. Also, since there was a lot of problems with your code I made some changes and comments that will help you to write better codes in tkinter. Please read it carefully. You may also want to study the effbot web page.
import tkinter as tk
# from tkinter import * # just don't do this
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
# class pages(tk.Tk):
class Pages(tk.Tk): # class names should start with upper case
#starts us off in the login page
# def __init__(self, *args, **kwargs):
def __init__(self):
# tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.__init__(self)
# tk.Tk.wm_title(self, "ScanNET")
self.winfo_toplevel().title("ScanNET")
# tk.Tk.wm_minsize(self, 800, 800)
self.wm_minsize(800, 800) # since you defined tk.Tk as pages parent you can call Tk methods directly
container = tk.Frame(self)
# container.pack(side=TOP, fill=BOTH, expand=True)
# container.grid_rowconfigure(0, weight=1)
# container.grid_columnconfigure(0, weight=1)
container.grid(row=0, column = 0) # don't use pack if you want to use grid
self.frames = {}
for F in (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
# frame.grid(row=0, column=0, sticky=N+E+S+W)
frame.grid(row=0, column=0, sticky='NESW') #since we are not importing all we are not importing tk.W but you can use string instead
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
# self.root = tk.Tk() # don't create new Tk objects, you just need one. The others should be Toplevel objects
### self.root = tk.Toplevel() ### this would be the correct way of creating a new window but you don't want to do that here your root is your parent
#the tabs
# my_notebook = ttk.Notebook(self.root)
my_notebook = ttk.Notebook(self) # this is how you place the notebook in the Frame widget and not in a new one
# my_notebook.pack()
my_notebook.grid() # we are now using grid so it will not accept pack anymore
# devicestab = Frame(my_notebook, width=800, height=600)
devicestab = tk.Frame(my_notebook, width=800, height=600) # again, since we are not importing al we have to use tk. before tkinter methods
# reportstab = Frame(my_notebook, width=800, height=600)
reportstab = tk.Frame(my_notebook, width=800, height=600)
# devicestab.pack(fill=BOTH, expand=1)
devicestab.pack(fill="both", expand=1) # instead of tk.BOTH we can use "both"
reportstab.pack(fill="both", expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = tk.LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = tk.LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = tk.LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= tk.LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = Pages()
app.mainloop()
In my code, there are two frames. In the first one, I put in an Add button that will produce a new frame with a Combobox. The idea is to add a few Combobox like that in the first frame, pick different options for different Combobox, and then print them out in the next frame. But when I hit the Show options button in the second frame, it doesn't print out the options that I just chose in the first frame. How can I solve this?
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def add_compare():
global list_1
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
self.options_1 = ttk.Combobox(frame, values=['a','b','c','d','e'])
self.options_1.grid(row=1, column=0)
list_1.append(self.options_1.get())
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add', command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
Here's a modified version of your code that will print the options selected so far when the Next is pressed. To prevent the Comboboxes from interferring with each other a list of them and an associated StringVars is kept.
Having separate StringVars avoids the problem of choosing an option on one of them from changing it on the others — i.e. a different textvar gets associated with each one.
To make collecting all the options together into list_1, a callback function named selected() has been defined and gets "bound" to Combobox selection events. This make it so that, in addition to the above, the option selected will also get appended to the global list_1, which is what the Show options button displays.
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.comboboxes = [] # Comboboxes created. ADDED
self.combobox_vars = [] # Vars for Comboboxes. ADDED.
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
# Combobox event handler. ADDED
def selected(event, var):
list_1.append(var.get()) # Append Combobox option selected.
def add_compare():
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
combobox_var = StringVar() # ADDED.
combobox = ttk.Combobox(frame, values=list('abcde'),
textvar=combobox_var) # For each Combobox. ADDED.
combobox.grid(row=1, column=0)
combobox.bind('<<ComboboxSelected>>', # Bind event handler. ADDED.
lambda event, var=combobox_var: selected(event, var)) # ADDED.
self.controller.comboboxes.append(combobox) # ADDED.
self.controller.combobox_vars.append(combobox_var) # ADDED.
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add',
command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
I am trying to make a tkinter widow with multiple frames, but also the functions of notebook, like multiple widows. The problem is I am kind of unfamiliar with tkinter and am not sure how to do that. This is my current code, and it doesn't work, and would love to know what I should do to make it work. Again, the dream end result would be that I would have a first widow, which says the test text, and then the 2nd window which has multiple tabs.
from tkinter import ttk
import tkinter as tk
Font= ("Verdana", 8)
LargeFont = ("Verdana", 12)
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Info", font=LargeFont)
label.pack(pady=2,padx=10)
text = tk.Label(self, text="testtestestetetqwegfegeg\ntestwegwegwegweg", font=Font)
text.pack(pady=2,padx=2)
button = tk.Button(self, text="Go to the Card",
command=lambda: controller.show_frame(PageOne))
button.pack(fill="x")
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
nb = ttk.Notebook(ttk.Frame())
nb.grid(row=1, column=0, columnspan = 50, rowspan=49, sticky='nesw')
p1 = (nb)
nb.add(p1, text='test')
label = tk.Label(self, text="", font=LargeFont)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
app = App()
app.mainloop()
The error that I eventually get is that it creates a third frame that is displayed with the test tab. Everything else works.
Thanks for your help
I know exactly what you mean because I'm trying the same. To me
nb = ttk.Notebook(self)
worked.
best
Pkanda
Taubate Brazil
The following is an excerpt of a my first python project I am currently working on.
I am able to add the check button into the GUI, but it is practically useless because I can't find out how I can get the value from the checkbutton.
import tkinter as tk
from tkinter import *
class base(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
#tk.Tk.iconbitmap(self, "iconz.ico")
tk.Tk.wm_title(self, "Mandelbrot Renderer")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, MainPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class MainPage(tk.Frame):
def getcheckvalue(self):
print (self.mvar.get())
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = ttk.Button(self, text="Re-Render",
command=self.getcheckvalue)
button2.pack()
mvar = IntVar()
self.cbutton = ttk.Checkbutton(self, text="shadow",onvalue=1, offvalue=0, variable=mvar)
self.cbutton.pack()
app = base()
app.geometry ("800x600")
app.mainloop()
mvar = IntVar()
In this line you are creating a local mvar. To access it from outside of your __init__ method, you need to make it class variable by adding self. prefix.
self.mvar = IntVar()
self.cbutton = ttk.Checkbutton(..., variable=self.mvar)