Tkinter Code runs but not window does not show - python

I noticed if I eliminate/comment the ########### Create Dropdown list for Code corresponding name ########### section below, the window appears. Also, if I use the same code in a different file, the DropDown list appears as normal.... super weird!!
Not sure what is going on here.
Can you help?
Code below:
from tkinter import *
########### Create main window, call it root ###########
root = Tk()
#Defining classes and methods
class Code:
def __init__(self, code, name, skill, description):
self.code = code
self.name = name
self.skill = skill
self.description = description
codesList.append(self)
namesList.append(name)
#Defining variables
codesList = []
namesList = []
selectedname = StringVar()
selectedname.set('Please select the correct the correct knowledge category necessary to resolve the ticket.')
A11 = Code(11, 'Fundamentals', 'A', '')
B11 = Code(11,'Geology', 'B', '')
B12 = Code(12,'Reservoir Engineering', 'B', '')
########### Create list of Dictionaries ###########
TypeD = {}
SiteD = {}
P4dcD = {}
SkillD = {}
########### Create Incident Types Dictionary###########
TypeD = dict(Normal='NORMAL', \
Parent='PARENT', \
Child='CHILD')
TypeNameL = list()
for i in TypeD.keys():
TypeNameL.append(i)
########### Create Skill Levels ###########
SkillD = dict(Awareness = 'A', \
Foundation = 'B', \
Skill = 'C', \
Advance = 'D')
SkillNameL = list()
for i in SkillD.keys():
SkillNameL.append(i)
########### Create main menu ###########
mainmenu = Menu(root)
root.config(menu = mainmenu)
submenu = Menu(mainmenu)
mainmenu.add_cascade(label = "File", menu=submenu)
submenu.add_command(label = "New Project", command=doNothing)
submenu.add_separator()
submenu.add_command(label = "Exit", command= exitmeth)
editmenu = Menu(mainmenu)
mainmenu.add_cascade(label = "Edit", menu=editmenu)
editmenu.add_command(label = "Redo", command = doNothing)
########### Toolbar ###########
toolbar = Frame(root, bg="blue")
insertButt = Button(toolbar, text = "Insert image", command = InsertImgcmd)
insertButt.pack(side=LEFT, padx = 2, pady=2)
printButt = Button(toolbar, text="Print", command = printP4dcD)
printButt.pack(side=LEFT, padx = 2, pady=2)
toolbar.pack(side=TOP, fill=X)
########### Create Dropdown list for Code corresponding name ###########
LabelCodeDDL = Label(root, text="Petrel Code").grid(row=2, column=0, sticky=W)
CodeDDL = OptionMenu(root, selectedname, *namesList)
CodeDDL.pack()
CodeDDL.configure(font=("Calibri", 11))
CodeDDL.grid(row=3, column=0)
########## Statusbar ##########
statusbar = Label(root, text='', bd=1, relief=SUNKEN, anchor=W)
statusbar.pack(side=BOTTOM, fill=X)
root.title("Ticket Summary Tool")
root.geometry("300x200")
root.mainloop()
I should get some errors or the window should display. I can't figure out what is happening...

You are using both pack and grid with widgets that are directly in root (for example, LabelCodeDDL = Label(root, text="Petrel Code").grid(row=2, column=0, sticky=W) and toolbar.pack(side=TOP, fill=X)). You cannot mix them like that. All widgets that have the same parent or master must use one or the other.

Related

Using Tkinter to iterate through a list of questions, and use radio buttons to record the answers

I'm using python to create a tkinter GUI to ask a list of questions (stored in excel), and plan to save the results of the selected buttons within a .csv to ingest into a PBI dashboard. However, I'm having difficulty with two things 1) iterating through the list of questions, and 2) creating a "next" button to navigate to the next question (linked to my first problem). I'm newer to python/Tkinter, so any advice/suggestions are appreciated.
from tkinter import ttk
from openpyxl.workbook import Workbook
from openpyxl import load_workbook
global root1
global response
#initiate the main window
root1 = Tk()
#create main window label
label1=Label(root1,text="Question Tool")
#define exit button
def Exit():
root1.destroy()
#define get value
def selection():
selection=print("User Selected " + str(response.get()))
#read governance questions
wb=Workbook()
wb=load_workbook('Questions.xlsx')
ws=wb.active
questions=ws['A']
#def start and stop buttons
def Start_Button():
global response
root1.destroy()
root=Tk()
root.title("Question Tool")
tabControl = ttk.Notebook(root)
tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)
tab3 = ttk.Frame(tabControl)
tab4 = ttk.Frame(tabControl)
tab5 = ttk.Frame(tabControl)
tabControl.add(tab1, text ='1) Governance')
tabControl.add(tab2, text ='2) Eligibility')
tabControl.add(tab3, text ='3) Operations')
tabControl.add(tab4, text ='4) Monitoring')
tabControl.add(tab5, text ='5) Continuing Improvment')
tabControl.pack(expand = 1, fill ="both")
#apply the questions as labels
ttk.Label(tab1,text=questions[10].value).grid(column = 0,row = 0,padx = 30,pady = 30)
response=StringVar()
RB1=ttk.Radiobutton(tab1,text="Yes",value="YES",variable=response)
RB1.grid(column=0,row=5,padx=10,pady=10)
RB2=ttk.Radiobutton(tab1,text="No",value="NO",variable=response)
RB2.grid(column=0,row=10,padx=10,pady=10)
x=response.get()
ttk.Button(tab1,text="Next",command=selection).grid(column=0,row=20,padx=10,pady=10)
ttk.Label(tab2,text ="Eligibility radio buttons/questions here").grid(column = 0,row = 0,padx = 30,pady = 30)
ttk.Label(tab3,text ="Operations radio buttons/questions here").grid(column = 0,row = 0,padx = 30,pady = 30)
ttk.Label(tab4,text ="Monitoring radio buttons/questions here").grid(column = 0,row = 0,padx = 30,pady = 30)
ttk.Label(tab5,text ="Continuing Improvment radio buttons/questions here").grid(column = 0,row = 0,padx = 30,pady = 30)
root.mainloop()
#add the lable to the root window
label1.pack()
#Add start and stop buttons
Start_Button=Button(root1,text="Click to Begin",padx=10,pady=10, command=Start_Button)
Start_Button.pack()
Exit_Button=Button(root1,text="Exit",padx=10,pady=10,command=Exit)
Exit_Button.pack()
#call main loop
root1.mainloop()
You can change the text or other standard options of the label after creating this label.
In this example, I am manipulating the value of the variable associated with the buttons (response).
Radiobuttons also have commands like select() and deselect().
from tkinter import *
from tkinter import ttk
# from openpyxl.workbook import Workbook
# from openpyxl import load_workbook
# initiate variables
global root1
global response
# answers to be saved somewhere
answers = {"governance": [],
"eligibility": [],
"operations": [],
"monitoring": [],
"continuing_improvement": []
}
# prepared question lists
questions = {"governance": ['A', 'B'],
"eligibility": ['C', 'D'],
"operations": ['E', 'F'],
"monitoring": ['G', 'H'],
"continuing_improvement": ['I', 'J']
}
# initiate the main window
root1 = Tk()
# create main window label
label1 = Label(root1, text="Question Tool")
# add the lable to the root window
label1.pack()
# define exit button
def Exit():
root1.destroy()
def selection(parent, label_obj):
global response
global questions
global answers
user_choice = response.get()
if user_choice == "":
# do something if no answer is selected
print("No answer selected!")
else:
print("User Selected: " + label_obj["text"])
print("User Selected: " + user_choice)
# get question category
label_obj_name = label_obj.winfo_name()
# update answers
answers[label_obj_name].append({label_obj["text"]: user_choice})
# check if we have run out of questions
if len(answers[label_obj_name]) == len(questions[label_obj_name]):
# clear parent tab
for i in parent.winfo_children():
i.destroy()
msg = ttk.Label(parent, text="Done")
msg.grid(column=0, row=0, padx=30, pady=30)
print(answers[label_obj_name])
print(answers)
# optional: reset response for new tab
response.set("")
else:
# iterating through the list of questions
# The questions must be different or not repeated in the same category.
# get the next question in the list
next_question = questions[label_obj_name][len(answers[label_obj_name])]
# get next question text
label_obj["text"] = next_question
# optional: reset response for next question
response.set("")
# or set default selection
# response.set("YES")
def create_labels_and_buttons(parent, label_text, label_name):
"""Create a separate label and buttons for each tab.
The response object is global to all tabs.
Added a label name to distinguish which category the question belongs to.
"""
global response
lb = ttk.Label(parent, text=label_text, name=label_name)
lb.grid(column=0, row=0, padx=30, pady=30)
rb1 = ttk.Radiobutton(parent, text="Yes", value="YES", variable=response)
rb1.grid(column=0, row=5, padx=10, pady=10)
rb2 = ttk.Radiobutton(parent, text="No", value="NO", variable=response)
rb2.grid(column=0, row=10, padx=10, pady=10)
# you can pass the arguments to the function like here
ttk.Button(parent, text="Next",
command=lambda: selection(parent, lb)).grid(column=0, row=20, padx=10, pady=10)
def Start_Button():
global response
global questions
global answers
root1.destroy()
root = Tk()
root.title("Question Tool")
tabControl = ttk.Notebook(root)
tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)
tab3 = ttk.Frame(tabControl)
tab4 = ttk.Frame(tabControl)
tab5 = ttk.Frame(tabControl)
tabControl.add(tab1, text='1) Governance')
tabControl.add(tab2, text='2) Eligibility')
tabControl.add(tab3, text='3) Operations')
tabControl.add(tab4, text='4) Monitoring')
tabControl.add(tab5, text='5) Continuing Improvement')
tabControl.pack(expand=1, fill="both")
# response for buttons
response = StringVar()
# apply the questions as labels
create_labels_and_buttons(parent=tab1, label_text=questions["governance"][0], label_name="governance")
create_labels_and_buttons(parent=tab2, label_text=questions["eligibility"][0], label_name="eligibility")
create_labels_and_buttons(parent=tab3, label_text=questions["operations"][0], label_name="operations")
create_labels_and_buttons(parent=tab4, label_text=questions["monitoring"][0], label_name="monitoring")
create_labels_and_buttons(parent=tab5, label_text=questions["continuing_improvement"][0],
label_name="continuing_improvement")
root.mainloop()
# add start and stop buttons
Start_Button = Button(root1, text="Click to Begin", padx=10, pady=10, command=Start_Button)
Start_Button.pack()
Exit_Button = Button(root1, text="Exit", padx=10, pady=10, command=Exit)
Exit_Button.pack()
# call main loop
root1.mainloop()

How to make find and replace system in python

This a simple code in which i have created a text area using tkinter and a menu in which there is a option of find and replace in which if user click on it then a gui will appear in which user will enter a word to whom they want to replace and then a word to whom they want replace with but till now i have just created a gui . But how can i replace word with a word given by user with the text of text area that i have created.
from tkinter import *
import tkinter.font as font
from tkinter import messagebox
root = Tk()
root.title("MyCodeEditor")
editor = Text()
editor.pack()
menu_bar = Menu(root)
def find_replace():
f = Tk()
f.title("Find and Replace")
find_label = Label(f,text = "Find : ")
replace_label = Label(f,text = "Replace : ")
find_label.grid(row = 0 , column = 0)
replace_label.grid(row = 3 , column = 0)
global find_enter
global replace_enter
find_enter = Entry(f,fg = "black" , background = "blue",borderwidth = 5,width = 40)
replace_enter = Entry(f,fg = "black" , background = "blue", borderwidth = 5, width =40 )
find_enter.grid(row = 0 , column = 1)
replace_enter.grid(row = 3 , column = 1)
btn_replace = Button(f,text = 'Replace',fg = 'black',command = None)
btn_replace.grid(row=0, column = 5)
format_bar = Menu(menu_bar , tearoff = 0)
format_bar.add_command(label = 'Find and Replace',command = find_replace)
menu_bar.add_cascade(label = 'Format' ,menu = format_bar )
root.config(menu = menu_bar)
root.mainloop()
Here is a simple example (most of it is just the GUI looks, the main part is the actual replace method):
from tkinter import Tk, Text, Entry, Frame, Button, Toplevel, Label, Menu, TclError, IntVar
normal_font = ('comicsans', 10)
class FindAndReplace(Toplevel):
def __init__(self, parent, text_widget: Text):
Toplevel.__init__(self, parent)
self.focus_force()
self.title('Find and Replace')
self.geometry('500x200')
self.resizable(False, False)
self.parent = parent
self.widget = text_widget
try:
self.start_index = self.widget.index('sel.first')
self.end_index = self.widget.index('sel.last')
except TclError:
self.start_index = '1.0'
self.end_index = 'end'
self.to_find = None
self.to_replace = None
# creating find entry
find_frame = Frame(self)
find_frame.pack(expand=True, fill='both', padx=20)
Label(find_frame, text='Find:', font=normal_font).pack(side='left', fill='both', padx=20)
self.find_entry = Entry(find_frame)
self.find_entry.pack(side='right', expand=True, fill='x')
# creating replace entry
replace_frame = Frame(self)
replace_frame.pack(expand=True, fill='both', padx=20)
Label(replace_frame, text='Replace:', font=normal_font).pack(side='left', fill='both', padx=20)
self.replace_entry = Entry(replace_frame)
self.replace_entry.pack(side='right', expand=True, fill='x')
# creating buttons
button_frame = Frame(self)
button_frame.pack(expand=True, fill='both', padx=20)
Button(button_frame, text='Cancel', font=normal_font,
command=self.destroy).pack(side='right', fill='x', padx=5)
Button(button_frame, text='Replace', font=normal_font,
command=self.replace).pack(side='right', fill='x', padx=5)
def __find_get(self):
self.to_find = self.find_entry.get()
def __replace_get(self):
self.to_replace = self.replace_entry.get()
def replace(self):
self.__find_get()
self.__replace_get()
if not self.to_replace:
return
length = IntVar()
index = self.widget.search(self.to_find, self.start_index, stopindex=self.end_index, count=length)
end_index = self.widget.index(index + f'+{length.get()}c')
self.widget.delete(index, end_index)
self.widget.insert(index, self.to_replace)
root = Tk()
menu_bar = Menu(root)
file_menu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label='File', menu=file_menu)
file_menu.add_command(label='Find and Replace', command=lambda: FindAndReplace(root, text))
root.config(menu=menu_bar)
text = Text(root)
text.pack()
root.mainloop()
Obviously some other functionality could be added such as replace all

Newbie problem with using tkinter checkbutton in a class

Running python 3.8 in PyCharm
I'm trying to create a class to allow creation of a tkinter checkbutton (and eventually other widgets) that will hold all the formatting and definition for the widget. I would like to be able to test the state of the checkbutton and act on it in a callback. But like many others, my checkbutton variable seems to always be 0. I'm fairly sure its a garbage collection issue, but I can't figure a way around it. Note the second set of parameters in the class definition specify the location of the label to display the checkbutton variable state. At the moment, the callback is just to display the variable state in a label.
Acknowledgement:
I modified code from Burhard Meier's book "Python GUI Programming Cookbook" for this. The code related to the class is mine, the rest is from Burkhard Meier.
'''
This is a modification of code by Burhard A. Meier
in "Python GUI Programming Cookbook"
Created on Apr 30, 2019
#author: Burkhard A. Meier
'''
#======================
# imports
#======================
import tkinter as tk
from tkinter import ttk
# Create instance
win = tk.Tk()
# Add a title
win.title("GUI Test Box")
# Modify adding a Label
a_label = ttk.Label(win, text="Testing TK Widgets")
a_label.grid(column=0, row=0)
# Modified Button Click Function
def click_me():
action.configure(text='Hello ' + name.get() + ' ' +
number_chosen.get())
#Define the Checkbutton Class
class ChkBut(): #lable, xloc, yloc, xlab, ylab
def __init__(self, lable, xloc, yloc, xlab, ylab): # , xloc, yloc, text="default", variable = v, onvalue='Set', offvalue='NotSet'):
v = tk.IntVar()
self.v = v
self.lable = lable
self.xloc = xloc
self.yloc = yloc
self.xlab = xlab
self.ylab = ylab
c = tk.Checkbutton(
win,
text= self.lable,
variable=self.v,
command=self.cb(self.v, xlab,ylab))
c.grid(column=xloc, row=yloc, sticky = tk.W)
c.deselect()
def cb (self, c, xlab, ylab):
if c.get()==1:
c_label = ttk.Label(win, text="Set")
c_label.grid(column=xlab, row=ylab)
elif c.get()==0:
c_label = ttk.Label(win, text="NotSet")
c_label.grid(column=xlab, row=ylab)
else:
c_label = ttk.Label(win, text=c.v.get())
c_label.grid(column=xlab, row=ylab)
# Changing the Label
ttk.Label(win, text="Enter a name:").grid(column=0, row=0)
# Adding a Textbox Entry widget
name = tk.StringVar()
name_entered = ttk.Entry(win, width=12, textvariable=name)
name_entered.grid(column=0, row=1)
# Adding a Button
action = ttk.Button(win, text="Click Me!", command=click_me)
action.grid(column=2, row=1)
# Creating three checkbuttons
ttk.Label(win, text="Choose a number:").grid(column=1, row=0)
number = tk.StringVar()
number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly')
number_chosen['values'] = (1, 2, 4, 42, 100)
number_chosen.grid(column=1, row=1)
number_chosen.current(0)
check1 = ChkBut("Button 1", 0, 4, 0, 5)
chVarUn = tk.IntVar()
check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn)
check2.deselect()
check2.chVarUn = 0
check2.grid(column=1, row=4, sticky=tk.W)
chVarEn = tk.IntVar()
check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn)
check3.select()
check3.chVarEn = 0
check3.grid(column=2, row=4, sticky=tk.W)
name_entered.focus() # Place cursor into name Entry
#======================
# Start GUI
#======================
win.mainloop()

problem with tkinter under defined function

Can you please help me with follwing issue I face:
When I am creating radiobutton with tkinter, I don't have a problem to select from the list.
However, if I put the same script under a menu, then selected option is always the default one, ("Python",1) in this specific case. Do you have any idea how to overcome this? Thanks in advance!
import tkinter as tk
root_m = tk.Tk()
root_m.geometry("400x200")
frame_m = tk.Frame(root_m)
root_m.title("NUMERIC UNIVERSE")
frame_m.pack()
def chars_merging():
languages = [
("Python",1),
("Perl",2),
("Java",3),
("C++",4),
("C",5)
]
root = tk.Tk()
root.geometry("400x200")
frame = tk.Frame(root)
root.title("SELECT SOMETHING")
frame.pack()
v = tk.IntVar()
v.set(0) # initializing the choice, i.e. Python
label = tk.Label(frame,
text="""Choose your favourite
programming language:""",
justify = tk.LEFT,
padx = 20)
label.pack()
def ShowChoice():
global data_sel
data_sel = v.get()
print(data_sel)
for val, language in enumerate(languages):
tk.Radiobutton(frame,
text=language,
indicatoron = 0,
width = 20,
padx = 20,
variable=data_sel,
command=ShowChoice,
value=val).pack(anchor=tk.W)
root.mainloop()
#return(languages[v.get()])
print("You selected", languages[v.get()])
button3 = tk.Button(frame_m,
text="3.Prepare and merge chars",
command=chars_merging,
width=25)
button3.pack()
# CLOSING THE WINDOW ---------------------------------------------------------
def finish():
root_m.destroy()
button_n = tk.Button(frame_m,
text="Finish",
command=finish,
width=25)
button_n.pack()
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
root_m.mainloop()

How to open a new frame from a current window in python tkinter?

class Login:
def __init__(self):
Label1 = Label(root,text = "Username")
Label2 = Label(root,text = "Password")
self.Entry1 = Entry(root)
self.Entry2 = Entry(root,show = "*")
Label1.grid(row=0)
Label2.grid(row=1)
self.Entry1.grid(row = 0,column = 1)
self.Entry2.grid(row = 1,column = 1)
root.minsize(width = 300,height = 80)
##new_window_button = Button(text="new window", command = ????)
##new_window_button.grid(columnspan = 2)
lgbutton = Button(text = "Login",command = self.ButtonClicked)
lgbutton.grid(columnspan = 2)
def ButtonClicked(self):
username = self.Entry1.get()
password = self.Entry2.get()
GetDatabase(username,password)
Currently this is what I have to create a window, however I want it to that when the new_window_button is clicked, the new page has its own widgets. I've used Toplevel before but it creates a child window without the widgets. Instead, the widgets are added to the parent window.
Judging by the comments it looks as though you are struggling with declaring the correct parent for widgets.
When a widget is declared the first parameter passed in to it is it's parent. For example:
Label(root, text="I'm in the root window.")
# ^ This is the parent
As opposed to:
Label(top, text="I'm in the top window.")
# ^ This is the parent
Please see a more fleshed out example below:
from tkinter import *
root = Tk()
top = Toplevel(root)
label1 = Label(root, text="I'm a placeholder in your root window.")
label2 = Label(top, text="I'm a placeholder in your top window.")
label1.pack()
label2.pack()
root.mainloop()
import tkinter
from tkinter import *
class LoginForm(Frame):
def __init__(self,master=None):
super().__init__(master)
self.pack()
self.createWidget()
def createWidget(self):
self.lblEmailId=Label(self,text="Email Id")
self.lblEmailId.grid(row=0,column=0)
self.varEmailid=StringVar()
self.txtEmailId=Entry(self,textvariable=self.varEmailid)
self.txtEmailId.grid(row=0,column=1)
self.txtEmailId.bind("<KeyRelease>",self.key_press)
self.lblPassword = Label(self, text="Password")
self.lblPassword.grid(row=1, column=0)
self.varPassword=StringVar()
self.txtPassword= Entry(self, textvariable=self.varPassword)
self.txtPassword.grid(row=1, column=1)
self.btnLogin=Button(self,text="Login")
self.btnLogin.grid(row=2,column=1)
self.btnLogin.bind("<Button-1>",self.btnLogin_click)
def btnLogin_click(self,event):
self.varPassword.set(self.varEmailid.get())
LoginWindow=Toplevel()
def key_press(self,event):
self.varPassword.set(self.varEmailid.get())
root=Tk()
fromLogin=LoginForm(root)
root.mainloop()

Categories