Related
The goal is to allow the user to select from the combobox dropdown and then click Select Files button. The button will get the product type (the value from the combobox) and will open the correct directory based on what is chosen in the combobox. Problem is, I cannot seem to get this value since the button and combobox are in different frames. I feel like I'm missing something basic here.
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
def select_files(prod_type):
path = f"\\\\10.10.3.7\\Production\\Test_Folder\\{prod_type}"
filetypes = (
('PDF Files', '*.pdf'),
)
filenames = fd.askopenfilenames(
title='Open files',
initialdir=path,
filetypes=filetypes)
for file in filenames:
print(file)
class InputFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.columnconfigure(0, weight=3)
self.__create_widgets()
def __create_widgets(self):
# Product
ttk.Label(self, text='Product:').grid(column=0, row=0, sticky=tk.W)
self.product_type = tk.StringVar()
self.product_combo = ttk.Combobox(self, width=30, textvariable=self.product_type)
self.product_combo['values'] = ('Notepad', 'Flat Notecard', 'Folded Notecard', 'Journal')
self.product_combo.set('Notepad')
self.product_combo['state'] = 'readonly'
self.product_combo.grid(column=1, row=0, sticky=tk.W)
# Algorithm:
ttk.Label(self, text='Algorithm:').grid(column=0, row=1, sticky=tk.W)
algo_var = tk.StringVar()
algo_combo = ttk.Combobox(self, width=30)
algo_combo['values'] = ('panel', 'fuzzy')
algo_combo.set('panel')
algo_combo.grid(column=1, row=1, sticky=tk.W)
# Orientation:
ttk.Label(self, text='Orientation:').grid(column=0, row=2, sticky=tk.W)
orientation_var = tk.StringVar()
orientation_combo = ttk.Combobox(self, width=30, textvariable=orientation_var)
orientation_combo['values'] = ('auto', 'portrait', 'landscape')
orientation_combo.set('auto')
orientation_combo.grid(column=1, row=2, sticky=tk.W)
# Margin:
ttk.Label(self, text='Margin:').grid(column=0, row=3, sticky=tk.W)
margin = ttk.Entry(self, width=30)
margin.grid(column=1, row=3, sticky=tk.W)
# Gap:
ttk.Label(self, text='Gap:').grid(column=0, row=4, sticky=tk.W)
gap = ttk.Entry(self, width=30)
gap.grid(column=1, row=4, sticky=tk.W)
# Repeat:
ttk.Label(self, text='Repeat:').grid(column=0, row=5, sticky=tk.W)
repeat_number = tk.StringVar()
repeat = ttk.Spinbox(self, from_=1, to=10, width=30, textvariable=repeat_number)
repeat.set(1)
repeat.grid(column=1, row=5, sticky=tk.W)
for widget in self.winfo_children():
widget.grid(padx=0, pady=5)
class ButtonFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.__create_widgets()
def __create_widgets(self):
ttk.Button(self, text='Select Files', command=self.on_go_pressed).grid(column=0, row=0)
ttk.Button(self, text='Generate PDF').grid(column=0, row=1)
for widget in self.winfo_children():
widget.grid(padx=0, pady=3)
def on_go_pressed(self):
select_files(InputFrame.product_type.get())
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("PDF n-up")
self.eval('tk::PlaceWindow . center')
self.geometry('400x200')
self.resizable(0, 0)
self.attributes('-toolwindow', True)
# layout on the root window
self.columnconfigure(0, weight=4)
self.columnconfigure(1, weight=1)
self.__create_widgets()
def __create_widgets(self):
# create the input frame
input_frame = InputFrame(self)
input_frame.grid(column=0, row=0)
# create the button frame
button_frame = ButtonFrame(self)
button_frame.grid(column=1, row=0)
if __name__ == '__main__':
app = App()
app.mainloop()
You can pass the product type variable to ButtonFrame when you create it, since you create the ButtonFrame after creating the InputFrame. Here is the code, with changed and added lines marked accordingly:
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
def select_files(prod_type):
path = f"/home/sam/Pictures/Test/{prod_type}"
filetypes = (
('PDF Files', '*.pdf'),
)
filenames = fd.askopenfilenames(
title='Open files',
initialdir=path,
filetypes=filetypes)
for file in filenames:
print(file)
class InputFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.columnconfigure(0, weight=3)
self.__create_widgets()
def __create_widgets(self):
# Product
ttk.Label(self, text='Product:').grid(column=0, row=0, sticky=tk.W)
self.product_type = tk.StringVar()
self.product_combo = ttk.Combobox(self, width=30, textvariable=self.product_type)
self.product_combo['values'] = ('Notepad', 'Flat Notecard', 'Folded Notecard', 'Journal')
self.product_combo.set('Notepad')
self.product_combo['state'] = 'readonly'
self.product_combo.grid(column=1, row=0, sticky=tk.W)
# Algorithm:
ttk.Label(self, text='Algorithm:').grid(column=0, row=1, sticky=tk.W)
algo_var = tk.StringVar()
algo_combo = ttk.Combobox(self, width=30)
algo_combo['values'] = ('panel', 'fuzzy')
algo_combo.set('panel')
algo_combo.grid(column=1, row=1, sticky=tk.W)
# Orientation:
ttk.Label(self, text='Orientation:').grid(column=0, row=2, sticky=tk.W)
orientation_var = tk.StringVar()
orientation_combo = ttk.Combobox(self, width=30, textvariable=orientation_var)
orientation_combo['values'] = ('auto', 'portrait', 'landscape')
orientation_combo.set('auto')
orientation_combo.grid(column=1, row=2, sticky=tk.W)
# Margin:
ttk.Label(self, text='Margin:').grid(column=0, row=3, sticky=tk.W)
margin = ttk.Entry(self, width=30)
margin.grid(column=1, row=3, sticky=tk.W)
# Gap:
ttk.Label(self, text='Gap:').grid(column=0, row=4, sticky=tk.W)
gap = ttk.Entry(self, width=30)
gap.grid(column=1, row=4, sticky=tk.W)
# Repeat:
ttk.Label(self, text='Repeat:').grid(column=0, row=5, sticky=tk.W)
repeat_number = tk.StringVar()
repeat = ttk.Spinbox(self, from_=1, to=10, width=30, textvariable=repeat_number)
repeat.set(1)
repeat.grid(column=1, row=5, sticky=tk.W)
for widget in self.winfo_children():
widget.grid(padx=0, pady=5)
class ButtonFrame(ttk.Frame):
def __init__(self, parent, product_type): ### EDITED THIS LINE
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.product_type = product_type ### ADDED THIS LINE
self.__create_widgets()
def __create_widgets(self):
ttk.Button(self, text='Select Files', command=self.on_go_pressed).grid(column=0, row=0)
ttk.Button(self, text='Generate PDF').grid(column=0, row=1)
for widget in self.winfo_children():
widget.grid(padx=0, pady=3)
def on_go_pressed(self):
select_files(self.product_type.get()) ### EDITED THIS LINE
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("PDF n-up")
self.eval('tk::PlaceWindow . center')
self.geometry('400x200')
self.resizable(0, 0)
# self.attributes('-toolwindow', True)
# layout on the root window
self.columnconfigure(0, weight=4)
self.columnconfigure(1, weight=1)
self.__create_widgets()
def __create_widgets(self):
# create the input frame
input_frame = InputFrame(self)
input_frame.grid(column=0, row=0)
# create the button frame
button_frame = ButtonFrame(self, input_frame.product_type) ### EDITED THIS LINE
button_frame.grid(column=1, row=0)
if __name__ == '__main__':
app = App()
app.mainloop()
Notice how in the line button_frame = ButtonFrame(self, input_frame.product_type), I give it input_frame.product_type as an argument, so that it can access it any time it wants.
The changes to ButtonFrame required for this: I changed the __init__() method so that it can receive another argument. It then assigns the value of the product_type argument to a variable so that it can use it later. When it calls select_files(), it simply uses self.product_type.
As to why calling select_files(InputFrame.product_type.get()) doesn't work: product_type is a variable that is created only when InputFrame is initialized. In the line above, you reference the class itself, not an instance of the class, so it has not been initialized. Therefore, anything that is created in InputFrame.__init__() is not defined, becuase __init__() wasn't called.
This is my first encounter with listboxes and I want to know how to insert the name of each team member into the corresponding listbox.
I have a dictionary called teams, and it's store data like that:
{'Team1': {'Aleks', Richard}, 'Team2': {'Louis'}, 'Team3': set(), 'Team4': set()}
I need to put set of names in particular listbox (ex. 'Team1' set should appear in the team1Members listbox).
I was trying to use .insert method to insert specific items from my dictionary, but I receive an error:
_tkinter.TclError: bad listbox index ".!frame.!listcheckpage": must be active, anchor, end, #x,y, or a number
My code:
from tkinter import *
from tkinter import messagebox
import tkinter.ttk as ttk
import time
class CollegeApp(Tk):
def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (StartPage, TeamsPage, successfullAddTeam, selectionPage, listCheckPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
self.lift()
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.startMenu()
def startMenu(self):
heading = Label(self, text="College Tournament Points\n Count Software",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=240, pady=40)
start_Btn = Button(self, text="START", font="Arial 16", width=8,
command=lambda: self.controller.show_frame(selectionPage))
start_Btn.grid(row=1, column=0, columnspan=2, padx=30, pady=5)
exit_Btn = Button(self, text="EXIT", font="Arial 16", width=8,
command=self.controller.destroy)
exit_Btn.grid(row=2, column=0, columnspan=2, padx=30, pady=5)
def starting_Program(self):
pass
class selectionPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamSelect()
def teamSelect(self):
heading = Label(self, text="Select one of two options",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=250, pady=40)
teams = Button(self, text="Teams", font="Arial 24", width=15,
command=lambda: self.controller.show_frame(TeamsPage))
teams.grid(row=1, column=0, padx=270, pady=5)
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
headingTest = Label(self, text="Enter your UserName:", font="Arial 20")
headingTest.grid(row=0, column=0, pady=5, padx=5)
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=5, pady=5)
self.TeamName = StringVar(self)
self.TeamName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15, padx=5)
self.team_names = list(teams.keys())[:-1]
self.teamSelection = OptionMenu(self, self.TeamName, *self.team_names)
self.teamSelection.grid(row=1, column=1, sticky=W)
backBtn = Button(self, text="BACK", font="Arial 16",
command=lambda: self.controller.show_frame(StartPage))
backBtn.config(height=4, width=12)
backBtn.grid(sticky=W, row=2, column=0, pady=5, padx=5)
confirmBtn = Button(self, text="Confirm User", font="Arial 16",
command=self.confirm)
confirmBtn.config(height=4, width=12)
confirmBtn.grid(row=2, column=2, sticky=E, padx=45, pady=300)
def confirm(self):
if self.add_to_team():
time.sleep(0.2)
self.controller.show_frame(successfullAddTeam)
def add_to_team(self):
user = self.usernameEnter.get()
if len(user) == 0:
messagebox.showwarning(title='No user', message='Please enter a username!')
return
if self.usernameEnter.get():
time.sleep(0.1)
self.controller.show_frame(successfullAddTeam)
team_name = self.TeamName.get()
team = teams[team_name]
if user in team:
messagebox.showwarning(title='In team', message=f'{user} is already a member of {team_name}!')
team.add(user)
print(teams)
class successfullAddTeam(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
successText = Label(self, text="You have successfully joined to a team!", font="Arial 25")
successText.grid(row=0, column=0, columnspan=2, padx=180, pady=35)
newUser = Button(self, text="Add another user", font="Arial 16",
command=lambda: self.controller.show_frame(selectionPage))
newUser.config(height=3, width=12)
newUser.grid(row=1, column=0, columnspan=2, padx=200, pady=10)
checkList = Button(self, text="Check the lists", font="Arial 16",
command=lambda: self.controller.show_frame(listCheckPage))
checkList.config(height=3, width=12)
checkList.grid(row=2, column=0, columnspan=2, padx=200, pady=0)
#####################################Problem here###############################################
class listCheckPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
team1Members = Listbox(self)
team1Members.insert(self, teams['Team1'])
team1Members.config(height=13, width=20)
team1Members.grid(row=0, column=0, padx=10, pady=5, sticky=W)
team2Members = Listbox(self)
team2Members.insert(self, teams['Team2'])
team2Members.config(height=13, width=20)
team2Members.grid(row=0, column=1, padx=7, pady=5, sticky=W)
team3Members = Listbox(self)
team3Members.insert(self, teams['Team3'])
team3Members.config(height=13, width=20)
team3Members.grid(row=0, column=3, padx=7, pady=5, sticky=W)
team4Members = Listbox(self)
team4Members.insert(self, teams['Team4'])
team4Members.config(height=13, width=20)
team4Members.grid(row=0, column=4, padx=7, pady=5, sticky=W)
addUserBtn = Button(self, text="Add User", font="Arial 16",
command=lambda: self.controller.show_frame(selectionPage))
addUserBtn.config(height=3, width=18)
addUserBtn.grid(row=1, column=4, sticky=S)
if __name__ == '__main__':
teams = {}
for team in range(1, 5):
teams[f'Team{team}'] = set()
app = CollegeApp()
app.geometry("800x500")
app.title('Points Counter')
app.mainloop()
It is obvious that I am doing something wrong, and I would like to know how this issue can be properly resolved.
Hi Guys I have Problem after add background in my project, I don't see anything but after resize I see background: I don't want to use ttk in my object.
This is my code:
from tkinter import (Button, Label, Frame)
class HomeFrame(Frame): # Inherit Frame class
"""Application main interface"""
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.root = parent # Define internal variable root
self.root.configure(background='green')
self.home_page()
def home_page(self):
"""Load control"""
Label(self, text="First name").grid(row=0, column=0, padx=20, pady=20)
Full_name = Button(self, text="Get Full name")
Full_name.grid(row=0, column=1, columnspan=2, padx=20, pady=20)
Label(self, text="Last name").grid(row=1, column=0, padx=20, pady=20)
hello = Button(self, text="hello")
hello.grid(row=3, column=2, columnspan=2, padx=20, pady=20)
This is Result:
Interface without resize
After Resize:
Interface After Resize
from tkinter import (Button, Label, Frame)
class HomeFrame(Frame): # Inherit Frame class
"""Application main interface"""
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.root = parent # Define internal variable root
self.root.configure(background='green')
self.config(background='green')
self.home_page()
def home_page(self):
"""Load control"""
Label(self, text="First name").grid(row=0, column=0, padx=20, pady=20)
Full_name = Button(self, text="Get Full name")
Full_name.grid(row=0, column=1, columnspan=2, padx=20, pady=20)
Label(self, text="Last name").grid(row=1, column=0, padx=20, pady=20)
hello = Button(self, text="hello")
hello.grid(row=3, column=2, columnspan=2, padx=20, pady=20)
Small problem here, my code seem to be clean but the tkinter GUI doesn't appear ? Can seem to figure it out. The GUI / Code is for a report form type.
Thanks for your help in advance
from tkinter import *
class FicheDeSignalement(Frame):
def __init__(self):
Frame.__init__(self)
programme = Frame()
programme.pack(side="top", fill="both", expand=True)
programme.grid_rowconfigure(0, weight=5)
programme.grid_columnconfigure(0, weight=5)
self.pages = {}
for onePage in (StartProgram, InformationsPage):
start_page = onePage(programme, self)
self.pages[onePage] = start_page
start_page.grid(row=0, column=0, sticky="nsew")
self.show_pages(StartProgram)
def show_pages(self, cont):
see_start_page = self.pages[cont]
see_start_page.tkraise()
class StartProgram(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent, controller)
label = Label(self, text="Fiche de Signalement", font=LARGE_FONT)
label.pack(padx=10, pady=10)
start_button = Button(self, text="Commencer", command=lambda: controller.see_page(InformationsPage))
start_button.pack()
class InformationsPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent, controller)
label = Label(self, text="Informations sur le suspect", font=LARGE_FONT)
label.pack(side="top", fill="both", expand=True, padx=10, pady=10)
person_suspected = Label(self, text="Prenom")
person_suspected.grid(row=0, column=0, padx=10, pady=10)
first_name = Entry(self)
first_name.grid(row=0, column=1, padx=10, pady=10)
person_suspected_2 = Label(self, text="Nom")
person_suspected_2.grid(row=0, column=2, padx=10, pady=10)
last_name = Entry(self)
last_name.grid(row=0, column=3, padx=10, pady=10)
person_height = Label(self, text="Grandeur")
person_height.grid(row=1, column=0, padx=10, pady=10)
size_height = Entry(self)
size_height.grid(row=1, column=1, padx=10, pady=10)
person_weight = Label(self, text="Poids")
person_weight.grid(row=1, column=2, padx=10, pady=10)
size_weight = Entry(self)
size_weight.grid(row=1, column=3, padx=10, pady=10)
app = FicheDeSignalement()
app.mainloop()
In addition to indentation errors and missing import statements and missing definition of LARGE_FONT, you have this problem:
label = Label(self, text="Informations sur le suspect")
label.pack(side="top", fill="both", expand=True, padx=10, pady=10)
person_suspected = Label(self, text="Prenom")
person_suspected.grid(row=0, column=0, padx=10, pady=10)
Both label and person_suspected share the same parent (self), but one uses pack and one uses grid. You can't use both of them with widgets that share a common parent. You must use only grid or only pack.
I'm trying to create a GUI in Python 2.7 with Tkinter. I need that the increment value from my Spinbox changes accordingly to a value selected from a selection of Radiobutton. I've tried different approaches but not success so far. I'm attaching part of the code that isn't working. I really appreciate if someone could come up with a solution. Thanks!
class Frequency_Window(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
global var_increment
self.var_x = IntVar()
self.self_value = IntVar()
self.freq_Hz = IntVar()
self.parent.title("Test")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(1, pad=7)
self.rowconfigure(5, weight=1)
self.rowconfigure(5, pad=7)
self.var_x.set("1")
label_RadioButton = ttk.Label(self,
justify=LEFT,
text="Increments")
label_RadioButton.grid(sticky=N+W+S+E,
pady=4,
padx=5,
row=0,
column=1)
R1 = ttk.Radiobutton(self,
text="1",
variable=self.var_x,
command=self.set_increment,
value=1)
R1.grid(sticky=NW,
row=1,
column=1,
pady=5)
R10 = ttk.Radiobutton(self,
text="10",
variable=self.var_x,
command=self.set_increment,
value=10)
R10.grid(sticky=NW,
row=2,
column=1,
pady=5)
R100 = ttk.Radiobutton(self,
text="100",
variable=self.var_x,
command=self.set_increment,
value=100)
R100.grid(sticky=NW,
row=3,
column=1,
pady=5)
var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
increment=self.var_x.get(),
width=4,
relief=FLAT,
buttonbackground='black')
var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
def set_increment(self):
selection = "You selected the option " + str(self.var_x.get())
print selection
return
Hi I just found the way to do it. I had to change my object available in the class adding it to self. From this:
var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
increment=self.var_x.get(),
width=4,
relief=FLAT,
buttonbackground='black')
var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
To this:
self.var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
width=4,
relief=FLAT,
buttonbackground='black')
self.var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
And then in the call function, I used the configure option to change the value of increment, as this:
def set_increment(self):
selection = "You selected the option " + str(self.var_x.get())
self.var_freq_Hz.config(increment = self.var_x.get())
print selection
return
Now it's working properly. However, if someone comes up with a more Pythonic solution is highly appreciate! Cheers!