Problem displaying entry text with Tkinter - python

I am a newbie in python. I am trying to write a program to reference books, book chapters and journal articles in Harvard and APA style. I need to be able to print the entry from the user.
The code displays three windows. In the first, the user is asked to choose the referencing style (Harvard/APA) and when clicking the button it opens a second window which allows the user to choose the source (book/book chapter/journal). Then a third window opens which allows the user to input the information that is required (author/year/title and so on).
After this, the user must click another button done to see the full reference. To visualise the execution, select Harvard, then Book, as I have only written that part of the code.
from tkinter import *
def book_harvard():
reference = author_entry.get()
reference_1 = year_entry.get()
reference_2 = title_entry.get()
string_to_display = reference + reference_1 + reference_2
print(string_to_display)
def TypeofTextHarvard():
second = Toplevel(first)
first.withdraw()
second.title("Type of Source")
Source = Label (second, text = "What type of source would you like to reference?").grid(column = 1, row = 0)
Book = Button (second, text = "Book", command = Harvard).grid(column = 1, row = 1)
Chapter = Button (second, text = "Book Chapter").grid (column = 1, row = 2)
Journal = Button (second, text = "Journal Article").grid (column = 1, row = 3)
first = Tk()
first.title("Referencing Style")
Reference = Label (first, text = "Which referencing style would you like to use?").grid(column = 1, row = 0)
Harvard = Button (first, text = "Harvard Style", command = TypeofTextHarvard).grid (column = 1, row = 1)
APA = Button (first, text = "APA Style").grid (column = 1, row = 2)
def Harvard():
third = Toplevel()
third.title("book")
author = StringVar()
year = StringVar()
title = StringVar()
author_label = Label(third, text = "Author")
author_entry = Entry(third)
year_label = Label(third, text = "Year")
year_entry = Entry(third)
title_label = Label(third, text = "Title")
title_entry = Entry(third)
button_1 = Button(third, text = "Done", command = book_harvard)
author_label_2 = Label(third, textvariable = author)
year_label_2 = Label(third, textvariable = year)
title_label_2 = Label(third, textvariable = title)
author_label.grid (row = 0, column = 0)
author_entry.grid (row = 0, column = 1)
year_label.grid (row = 1, column = 0)
year_entry.grid (row = 1, column = 1)
title_label.grid (row = 2, column = 0)
title_entry.grid (row = 2, column = 1)
button_1.grid (row = 3, column = 0)
author_label_2.grid (row = 4, column = 1)
year_label_2.grid (row = 4, column = 2)
title_label_2.grid (row = 4, column = 3)
first.mainloop()
However I get the following error:
reference = author_entry.get()
NameError: name 'author_entry' is not defined

The cause of the NameError is because author_entry is a variable local to the Harvard() function, so can't be referenced outside of it, such as in the separate book_harvard() function. The simplest—although not the best—solution is to make it a global variable. The other Entry widgets potentially have the same problem, so in the code below I have declared all of them global.
I also noticed another potential issue you're likely to run into, namely assigning the return value of the grid() method to a variable. e.g.:
Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)
This is not doing what you think because the grid() method always returns None, so that's the value that's getting assigned to Book. I haven't fixed these, but doing so is easy, just create the widget first and assign it to a variable, and then on another line, all variable.grid(...).
One final piece of advice: read and start following the PEP 8 - Style Guide for Python Code. I've done that to some degree to the version of your code with the fix in it shown below.
FYI: The accepted answer to the question Best way to structure a tkinter application describes an excellent object-oriented way to structure and implement Tkinter-based applications.
from tkinter import *
def book_harvard():
global author_entry, year_entry, title_entry # ADDED
reference = author_entry.get()
reference_1 = year_entry.get()
reference_2 = title_entry.get()
string_to_display = reference + reference_1 + reference_2
print(string_to_display)
def TypeofTextHarvard():
second = Toplevel(first)
first.withdraw()
second.title("Type of Source")
Source = Label(second, text = "What type of source would you like to reference?").grid(column=1, row=0)
Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)
Chapter = Button(second, text="Book Chapter").grid(column=1, row=2)
Journal = Button(second, text="Journal Article").grid(column=1, row=3)
first = Tk()
first.title("Referencing Style")
Reference = Label(first, text="Which referencing style would you like to use?").grid(column=1, row=0)
Harvard = Button(first, text="Harvard Style", command=TypeofTextHarvard).grid(column=1, row=1)
APA = Button(first, text="APA Style").grid(column=1, row=2)
def Harvard():
global author_entry, year_entry, title_entry # ADDED
third = Toplevel()
third.title("book")
author = StringVar()
year = StringVar()
title = StringVar()
author_label = Label(third, text="Author")
author_entry = Entry(third)
year_label = Label(third, text="Year")
year_entry = Entry(third)
title_label = Label(third, text="Title")
title_entry = Entry(third)
button_1 = Button(third, text="Done", command=book_harvard)
author_label_2 = Label(third, textvariable=author)
year_label_2 = Label(third, textvariable=year)
title_label_2 = Label(third, textvariable=title)
author_label.grid(row=0, column=0)
author_entry.grid(row=0, column=1)
year_label.grid(row=1, column=0)
year_entry.grid(row=1, column=1)
title_label.grid(row=2, column=0)
title_entry.grid(row=2, column=1)
button_1.grid(row=3, column=0)
author_label_2.grid(row=4, column=1)
year_label_2.grid(row=4, column=2)
title_label_2.grid(row=4, column=3)
first.mainloop()

Related

Python - Tkinter : How to create radiobuttons in loop? [duplicate]

This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 2 years ago.
Hello im trying to create a questionnaire with 5 choises for each question. Since I have lots of questions, I wanted to create labels and radiobuttons in a loop. However, I can not call mainloop() function of tkinter in a loop so when I call it on the outside of the loop, my selection on the questionnaire of any question becomes the answer of the last question. How can I fix this?
def selected(value, question):
answer_values[question-1] = value
print(value, question)
root = Tk()
root.title('Kişilik Analiz Testi')
answers = {}
for x in range(0, enneagram.shape[0]):
soru = str(x+1) + ". " + enneagram.SORULAR[x] + " Cümlesi sizi ne kadar iyi ifade ediyor?"
myLabel = Label(root, text = soru).grid(row = x+1, column = 1, sticky = W)
Label(root, text = "Sorular").grid(row = 0, column = 1, sticky = W)
Label(root, text = "Çok Zayıf ").grid(row = 0, column = 2)
Label(root, text = "Zayıf ").grid(row = 0, column = 3)
Label(root, text = "Orta ").grid(row = 0, column = 4)
Label(root, text = " İyi ").grid(row = 0, column = 5)
Label(root, text = "Çok İyi").grid(row = 0, column = 6)
answers["soru{0}".format(x)] = IntVar()
answers["soru{0}".format(x)].set(3)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 1, command = lambda: selected(1, x+1)).grid(row = x+1, column = 2)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 2, command = lambda: selected(2, x+1)).grid(row = x+1, column = 3)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 3, command = lambda: selected(3, x+1)).grid(row = x+1, column = 4)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 4, command = lambda: selected(4, x+1)).grid(row = x+1, column = 5)
button = Radiobutton(root, variable = answers["soru{0}".format(x)], value = 5, command = lambda: selected(5, x+1)).grid(row = x+1, column = 6)
root.mainloop()
When I run this cell, i get this window. Default choice is the middle one. When I click on other choices it prints out the index of the last question:
Try this code:
import tkinter as tk
from functools import partial
def function(i):
print("You toggled number %i"%i)
print([var.get() for var in variables])
root = tk.Tk()
variables = []
for i in range(5):
# Create the new variable
variable = tk.IntVar()
variables.append(variable)
# Create the command using partial
command = partial(function, i)
# Create the radio button
button = tk.Radiobutton(root, variable=variable, value=i, command=command)
button.pack()
root.mainloop()
It uses the partial function/class from functools.

Tkinter - inserting information from a text box to a specific location in a python script

I've recently finished a data standardisation script and am currently trying to make it more user-friendly by creating an app with Tkinter. I have already managed to run the data standardisation script through Tkinter, but the script requires minor changes between different data sets.
What I'm trying to achieve is inserting a user-defined piece of text to a specific location in the script. I have tried the text widget on Tkinter, however I have only managed to open the script in the app, which is something I avoid doing (optimally the app user would not even need to see the original code).
What I'm rather trying to do is having a Tkinter textbox, with a 'Run' button next to it. That way when a user inserts a specific name (e.g. 'Law Conference Attendees Jan 2020') it would automatically place this piece of text here df['Data Identifier'] = ''
My current Tkinter code looks like this:
def __init__(self):
super(Root, self).__init__()
self.title("Python Tkinter Dialog Widget")
self.minsize(320, 200)
self.text_area = Text()
self.text_area.grid(column = 2, row = 3)
self.labelFrame = ttk.LabelFrame(self, text = "Open File")
self.labelFrame.grid(column = 0, row = 1, padx = 20, pady = 20)
self.button()
self.button1()
self.button2()
self.textbox()
self.textbox1()
self.textbox2()
def button(self):
self.button = ttk.Button(self.labelFrame, text = "Browse a File",command = self.open_file)
self.button.grid(column = 1, row = 1)
def button1(self):
self.button1 = ttk.Button(self.labelFrame, text = "Cleanse Campaign Codes",command = self.standardize)
self.button1.grid(column = 1, row = 7)
def button2(self):
self.button2 = ttk.Button(self.labelFrame, text = "Cleanse Data",command = self.helloCallBack)
self.button2.grid(column = 1, row = 8)
def textbox(self):
self.textbox = ttk.Entry(self.labelFrame)
self.textbox.grid(column = 6, row = 1)
def textbox1(self):
self.textbox1 = ttk.Entry(self.labelFrame)
self.textbox1.grid(column = 6, row = 2)
def textbox2(self):
self.textbox2 = ttk.Entry(self.labelFrame)
self.textbox2.grid(column = 6, row = 3)
def helloCallBack(self):
os.system('python data_cleansing_final.py')
def open_file(self):
open_return = filedialog.askopenfile(initialdir = "C:/", title="Select file to open", filetypes=(("python files", "*.py"), ("all files", "*.*")))
for line in open_return:
self.text_area.insert(END, line)
def standardize(self):
open_return = open_return.apply(lambda x: difflib.get_close_matches(x, textbox)[0])
root = Root()
root.mainloop()
I would very much appreciate any help or advice.
You could add a StringVar to your textbox.
self.inputstring = ttk.StringVar(self.lableFrame, value = 'value')
self.textbox2 = ttk.Entry(self.labelFrame, textvariable = self.inputstring)
self.textbox2.grid(column = 6, row = 3)
To read the variable you should use:
self.inputstring.get()
You can make an entry:
text = Entry(root, width=10)
text.grid(column=0, row=0)
With a button next to it:
run = Button(root, text="Run", width=10, command=runClicked)
run.grid(column=1, row=0)
And then a method called runClicked above these:
def runClicked():
userText = text.get()
And then the variable userText variable will hold whatever the user types in and you can use it as you wish.
All in all your code would look something like:
def runClicked():
userText = text.get()
text = Entry(root, width=10)
text.grid(column=0, row=0)
run = Button(root, text="Run", width=10, command=runClicked)
run.grid(column=1, row=0)

Can i Make Labels Clickable in tkinter and get the Value of label clicked?

I would like user to click on the number's and then the number should change color and i shall be able to capture on what label user has clicked, this form then shall be saved in Text and PDF format..Thanks a mil in advance for any help
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class Proj_pres:
"""Defininf clickable labels in frame"""
#def fr_lb(self):
def __init__(self,master):
master.title(" Feedback Form")
#master.resizable(False,False)
self.frame_header = ttk.Frame(master, borderwidth = 5, relief ='ridge').grid(sticky = NE)
#self.frame_header.pack()
ttk.Label(self.frame_header, text = " For recording feedback on Autumn(inerm) project presentations",
font=('Arial',16,'bold')).grid(row = 0, column = 0,sticky = NW)
"""Defining new frame"""
self.frame_content = ttk.Frame(master,borderwidth = 5)
self.frame_content.grid(row = 2, column = 0,columnspan = 3, sticky = NW)
"""Adding check buttons for Studio 1 and Studio 2"""
self.chkb1 = IntVar()
self.b1 = ttk.Checkbutton(self.frame_content, text = "UC1Studio1", variable = self.chkb1).grid(row =0,column = 0)
self.chkb2 = IntVar()
self.b2 = ttk.Checkbutton(self.frame_content, text = "UC2Studio2", variable = self.chkb2).grid(row = 0, column = 8,columnspan = 2,stick=W)
"""Adding Labels for Team and Reviewer"""
ttk. Label(self.frame_content, text = "Team Name").grid(row =4, column = 0,sticky = W)
ttk.Label(self.frame_content, text = "Reviewer").grid(row = 4,column = 7, sticky = E)
ttk.Label(self.frame_content).grid(row=2, column=0)
"""Adding Entry Boxes for team name and reviewer"""
ttk.Entry(self.frame_content).grid( row = 4, column = 1,columnspan = 4,sticky = W)
ttk.Entry(self.frame_content).grid( row = 4, column = 8,columnspan = 2, sticky = E)
"""Adding Label and frame for grading info"""
self.frame_info = ttk.Frame(master,borderwidth = 5, relief = 'solid')
self.frame_info.grid(row = 3, column = 0,sticky = NW)
ttk.Label(self.frame_info).grid(row =5,column = 0)
ttk.Label(self.frame_info, text ="Please use the feeedback scale for each of the following criterion, "
"where 5 = excellent and 1 = poor").grid(row = 7, column = 0,sticky = W)
ttk.Label(self.frame_info).grid(row = 6, column =0)
ttk.Label(self.frame_info,text = "OVERVIEW OF PROJECT").grid(row = 8, column = 0, sticky = NW)
ttk.Label(self.frame_info, text = " 5: Well Structured,4: Clear aim, 3:Understandable project "
"view").grid(row = 9, column = 0, sticky = NW)
ttk.Label(self.frame_info, text=" 2: Absent,1: Confused "
"view").grid(row=9, column=5, sticky=NW)
#ttk.Label(self.frame_info, text=" should come here").grid(row=9, column=1, sticky=NW)
"""Adding frame in column 2 for clickable Labels"""
self.frame_clk=ttk.Frame(self.frame_info, borderwidth= 5, relief ='solid')
self.frame_clk.grid(row = 9,column = 2,columnspan = 3,sticky = NW)
self.f1_l5 = StringVar()
l5 = ttk.Label(self.frame_clk,text = " 5 " ,
background = 'white',borderwidth=5,relief= 'ridge',font =('Helvetica',12,'bold'))
#,textvariable = self.f1_l5
l5.grid(row=0,column =1,columnspan =2 )
f1_l4= ttk.Label(self.frame_clk, text=" 4 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l4.grid(row =0 , column = 3)
f1_l3 = ttk.Label(self.frame_clk, text=" 3 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l3.grid(row=0, column=4)
f1_l2 = ttk.Label(self.frame_clk, text=" 2 ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
f1_l2.grid(row=0, column=5)
f1_l1 = ttk.Label(self.frame_clk, text=" 1 ",background = 'white', borderwidth=5,relief= 'ridge',font=('Helvetica', 12, 'bold'))
f1_l1.grid(row=0, column=6)
#elf.frame_content.pack()
def main():
root = Tk()
proj_pres = Proj_pres(root)
root.mainloop()
if __name__ == '__main__':main()
def clickFunction(event): #event is argument with info about event that triggered the function
global selectedNumber #make the number visible throughout the program, don't need this if you'll just pass it as argument to function
event.widget.config(background = "green") #event.widget is reference to widget that was clicked on and triggered the function
selectedNumber = 7 - event.widget.grid_info()["column"] #grid info is dictionary with info about widget's grid relative to widget, more at http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/grid-methods.html
if(selectedNumber > 5): selectedNumber = 5
print(selectedNumber)
''' if someday you won't use grid, but will use list to store Labels, this is a way to get Label's position
selectedNumber = myLabels.index(event.widget)
'''
l5.bind("<Button-1>", clickFunction)
f1_l4.bind("<Button-1>", clickFunction)
f1_l3.bind("<Button-1>", clickFunction)
f1_l2.bind("<Button-1>", clickFunction)
f1_l1.bind("<Button-1>", clickFunction)
''' Alternative way for making lots of similar widgets, not to mention extending Label class
myLabels = [] #create List to make code more compact and to be able to use loops
for i in range(5, 0, -1):
myLabels.append(ttk.Label(self.frame_clk, text=" " + str(i) + " ",background = 'white',borderwidth=5,relief= 'ridge', font=('Helvetica', 12, 'bold'))
myLabels.bind("<Button-1>", clickFunction)
myLabels[i].grid(row =0 , column = 6 - i)
'''
Here is code you can add below "f1_l1.grid(row=0, column=6)" line (around ln 77). But I think you might need RadioButton for that purpose since it automatically unmarks other options and supports IntVar. More about events: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/events.html This webpage has excellent (but a bit outdated) documentation.
Btw, there is one quick fix you might want to apply when making programs for yourself. In Python you can add fields to classes and their instances outside their definition. E.g. in your code, you cold have written f1_l1.myNumber = 1 after "creating" it and in clickFunction instead of grid_info() use selectedNumber = event.widget.myNumber. It'd do the thing, but don't tell them I taught you that ;) since it isn't considered good practice adding fields that way.
If you have any more questions feel free to ask.

Python Tkinter not opening when using .grid()

I am working through online tutorials to learn how to make a GUI with Tkinter. But i am having an issue when using the .grid() function.
Here is what i have so far:
from Tkinter import *
root = Tk()
title = Label(root, text = "Hello World")
title.pack()
name = Label(root, text = "Name")
password = Label(root, text = "Password")
entry_name = Entry(root)
entry_password = Entry(root)
name.grid (row = 0, sticky = E)
password.grid (row = 0, sticky = E)
entry_name.grid (row = 0, column = 1)
entry_password.grid (row = 1, column = 1)
check = Checkbutton(root, text = "Keep me logged in")
check.grid(columnspan = 2)
root.mainloop()
So the problem im having is as soon as i include that first line:
name.grid(row = 0, sticky = E)
And then run the script, there are no errors, but nothing opens. The program just hangs and i have to close the command prompt in order to regain control.
If i comment out all the lines using .grid() they program works fine and will open a window with my title inside it.
So, does anyone know what im doing wrong?
Im using Python 2.7
You cannot use both pack and grid with two or more widgets that share the same parent. In your case you're using pack for title and grid for everything else. Use one or the other.
Keep grid geometry manager consistent so use title.grid().
from tkinter import *
root = Tk()
title = Label(root, text = "Hello World")
title.grid()
name = Label(root, text = "Name")
password = Label(root, text = "Password")
entry_name = Entry(root)
entry_password = Entry(root)
name.grid(row = 0, sticky = E)
password.grid (row = 0, sticky = E)
entry_name.grid (row = 0, column = 1)
entry_password.grid (row = 1, column = 1)
check = Checkbutton(root, text = "Keep me logged in")
check.grid(columnspan = 2)
root.mainloop()

How can I make a in interactive list in Python's Tkinter complete with buttons that can edit those listings?

Basically I want there to be a list, which displays files I have stored in a certain folder, and beside the list there are buttons which open up separate windows which can edit or add a new item to that list.
I want addchar to open up an new window with spaces for different fields, then when you press a "create" button in that window it closes, creates a file on the info you just entered (that's why i've imported os) as well as creating a new item on the main interface's listbox as the name of the character (which is one of the fields). The removechar function would remove that entry and delete the file, and editchar would open up a window similar to addchar, but with the info of the selected item on the list.
EDIT: Here's the code so far
from tkinter import *
import os
import easygui as eg
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
# character box
Label(frame, text = "Characters Editor").grid(row = 0, column = 0, rowspan = 1, columnspan = 2)
charbox = Listbox(frame)
for chars in []:
charbox.insert(END, chars)
charbox.grid(row = 1, column = 0, rowspan = 5)
charadd = Button(frame, text = " Add ", command = self.addchar).grid(row = 1, column = 1)
charremove = Button(frame, text = "Remove", command = self.removechar).grid(row = 2, column = 1)
charedit = Button(frame, text = " Edit ", command = self.editchar).grid(row = 3, column = 1)
def addchar(self):
print("not implemented yet")
def removechar(self):
print("not implemented yet")
def editchar(self):
print("not implemented yet")
root = Tk()
root.wm_title("IA Development Kit")
app = App(root)
root.mainloop()
Ok, I implemented addchar and removechar for you (and tweaked a few other things in your code). I'll leave the implementation of editchar to you - take a look at what I wrote to help you, as well as the listbox documentation
from Tkinter import * # AFAIK Tkinter is always capitalized
#import os
#import easygui as eg
class App:
characterPrefix = "character_"
def __init__(self, master):
self.master = master # You'll want to keep a reference to your root window
frame = Frame(master)
frame.pack()
# character box
Label(frame, text = "Characters Editor").grid(row = 0, column = 0, rowspan = 1, columnspan = 2)
self.charbox = Listbox(frame) # You'll want to keep this reference as an attribute of the class too.
for chars in []:
self.charbox.insert(END, chars)
self.charbox.grid(row = 1, column = 0, rowspan = 5)
charadd = Button(frame, text = " Add ", command = self.addchar).grid(row = 1, column = 1)
charremove = Button(frame, text = "Remove", command = self.removechar).grid(row = 2, column = 1)
charedit = Button(frame, text = " Edit ", command = self.editchar).grid(row = 3, column = 1)
def addchar(self, initialCharacter='', initialInfo=''):
t = Toplevel(root) # Creates a new window
t.title("Add character")
characterLabel = Label(t, text="Character name:")
characterEntry = Entry(t)
characterEntry.insert(0, initialCharacter)
infoLabel = Label(t, text="Info:")
infoEntry = Entry(t)
infoEntry.insert(0, initialInfo)
def create():
characterName = characterEntry.get()
self.charbox.insert(END, characterName)
with open(app.characterPrefix + characterName, 'w') as f:
f.write(infoEntry.get())
t.destroy()
createButton = Button(t, text="Create", command=create)
cancelButton = Button(t, text="Cancel", command=t.destroy)
characterLabel.grid(row=0, column=0)
infoLabel.grid(row=0, column=1)
characterEntry.grid(row=1, column=0)
infoEntry.grid(row=1, column=1)
createButton.grid(row=2, column=0)
cancelButton.grid(row=2, column=1)
def removechar(self):
for index in self.charbox.curselection():
item = self.charbox.get(int(index))
self.charbox.delete(int(index))
try:
os.remove(characterPrefix + item)
except IOError:
print "Could not delete file", characterPrefix + item
def editchar(self):
# You can implement this one ;)
root = Tk()
root.wm_title("IA Development Kit")
app = App(root)
root.mainloop()

Categories

Resources