Working with GUIs and text files - how do I 'synchronize' them? - python

I am working on a larger programming project, and since I am a beginner it is not that complex. I will try to keep it straight forward: I want to create a GUI program that reads from a text file with "elements of notes", i.e. as a calendar.
The interface should have "text entry box", where you can submit new notes, and there should also be two buttons that upon pressing them "scrolls" up and down among the existing notes, i.d. turning page. A single note should be displayed at all times in a text box under the two buttons.
So, to wrap this up, my question is: How is the best way to "load" the text file's notes to the program, so that I can make the buttons scroll between them? Should I read the text file into a list that I give my Application(Frame) object?
Here is some of my code so far:
from tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self, master):
""" Initialize Frame. """
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2 column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
# main
text_file = open("diary.txt", "r")
note_list = text_file.readlines()
text_file.close()
# No idea where to put the note_list, which 'client' should receive it?
root = Tk()
root.title("Diary")
app = Application(root)
root.mainloop()
So now that you have examined my code, how to fill in the missing pieces?
Edit: I added the text_file and note_list under the # main.
Note: I have used calendar and diary interchangeably, but the program is more of a calendar.

You can use it inside Application class:
from Tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self):
""" Initialize Frame. """
Frame.__init__(self)
self.note_list = []
with open("diary.txt", "r") as notes:
self.note_list = text_file.readlines()
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2, column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
app = Application()
app.master.title("Diary")
app.mainloop()

Related

Chechboxes in Tkinter

I'm new to GUIs, and I'm writing some code segments for school. This is an issue I've been having in multiple assignments and I can't seem to wrap my head around it. When I implement checkboxes, the value returned is always positive regardless of whether or not I check to box. For example, this is a code I've been writing that is supposed to create a menu for the user to select from, and them display the correct total:
from tkinter import *
def main():
class Application(Frame):
#GUI application that creates a menu to be chosen from and selections to be made.
def __init__(self, master):
#Initialize Frame.
Frame.__init__(self, master)
self.grid()
self.createWidgets()
def addPrices(self):
#store price float
price = 0.00
#add all contents of the list selected
#use if statement to determine which prices need to be added
if self.isPizza:
price += 3.00
if self.isFries:
price += 0.50
if self.isCoke:
price += 0.25
if self.isChurro:
price += 1.50
#display totals
#Use label to print total
Label(self,text = "Your total is: ").grid(row = 9, column = 0, columnspan = 2, sticky = W)
Label(self,text = price).grid(row = 10, column = 0, columnspan = 2, sticky = W)
def createWidgets(self):
#create instruction label
Label(self,text = "Please Select your Items:").grid(row = 0, column = 4, columnspan = 2, sticky = W)
#create labels for checkboxes / menu
Label(self,text = "Pizza.... $3.00").grid(row = 1, column = 5, sticky = W)
Label(self,text = "Fries... $0.50").grid(row = 2, column = 5, sticky = W)
Label(self,text = "Coke... $0.25").grid(row = 3, column = 5, sticky = W)
Label(self,text = "Churro... $1.50").grid(row = 4, column = 5, sticky = W)
#create input via checkboxes
#Create a plain of checkboxes to select items
self.isPizza = BooleanVar()
Checkbutton(self,text = "Pizza",variable = self.isPizza).grid(row = 6, column = 0, sticky = W)
self.isFries = BooleanVar()
Checkbutton(self, text = "Fries",variable = self.isFries).grid(row = 6, column = 1, sticky = W)
self.isCoke = BooleanVar()
Checkbutton(self, text = "Coke",variable = self.isCoke).grid(row = 7, column = 0, sticky = W)
self.isChurro = BooleanVar()
Checkbutton(self, text = "Churro",variable = self.isChurro).grid(row = 7, column = 1, sticky = W)
#Create submit button
Button(self,text = "Click to submit order",command = self.addPrices).grid(row = 8, column = 0, sticky = W)
root = Tk()
root.geometry("800x400")
root.title(" Order Up!")
app = Application(root)
root.mainloop()
main()
The program always returns 5.25 as the total, which is just the amount of all items added together. Am I missing a segments that will change my Boolean variables depending on user input?
You need to test the boolean value of the each Var's value, not of the Var itself.
Change if self.isPizza: to if self.isPizza.get():, etc, and your program works.
PS Wrapping your entire program in def main: and calling main(), as you did, is useless and wastes an indentation level and makes the program harder to read. If you want to make a file useful for import, as well as direct running, define your top-level classes and functions as module level and only put code that does things that should not happen on import inside main, and then guard the execution of main. In this case:
from tkinter import *
class Application:
...
def main():
root = Tk()
...
root.mainloop()
if __name__ == '__main__':
main()
You can now import this file into a test file and test the Application class without root.mainloop() taking control.

Tkinter window not responding after Text Insert

I'm new to Python and just started venturing into doing GUIs. I created a Tkinter window that is pretty basic: it has 3 Entry bars and 3 File Dialog buttons. When you chose the 3rd directory, the GUI file automatically makes a call to a separate file and receives a large text block which is then displayed in a Text box.
The whole thing works correctly, but my problem is that after receiving and inserting the text response, Tkinter stops working and doesn't allow the user to scroll down.
I read that one reason this happens is because people use both .pack( ) and .grid( ), but I'm not mixing those two functions.
Thanks in advance for any help!
Here's my GUI file
from tkinter import *
from tkinter import filedialog
from gui_GPSExtractor import *
import os
class Application(Frame):
def __init__(self, master):
""" Initialize Frame """
Frame.__init__(self, master)
self.grid( )
self.startGUI( )
""" Create Labels, Text Boxes, File Dialogs, and Buttons """
def startGUI(self):
# Label for Scan Path
self.dLabel = Label(self, text = "Scan Path")
self.dLabel.grid(row = 0, column = 0, columnspan = 2, sticky = W)
# Entry for Scan Path
self.dEntry = Entry(self, width = 60)
self.dEntry.grid(row = 1, column = 0, sticky = W)
# Button for Scan Path Directory Browse
self.dButton = Button(self, text = "Browse", command = lambda: self.browseFiles("d"))
self.dButton.grid(row = 1, column = 1, sticky = W)
# Label for CSV Path
self.cLabel = Label(self, text = "CSV Path")
self.cLabel.grid(row = 3, column = 0, columnspan = 2, sticky = W)
# Entry for CSV Path
self.cEntry = Entry(self, width = 60)
self.cEntry.grid(row = 4, column = 0, sticky = W)
# Button for CSV Path Directory Browse
self.cButton = Button(self, text = "Browse", command = lambda: self.browseFiles("c"))
self.cButton.grid(row = 4, column = 1, sticky = W)
# Label for Log Path
self.lLabel = Label(self, text = "Log Path")
self.lLabel.grid(row = 6, column = 0, columnspan = 2, sticky = W)
# Entry for Log Path
self.lEntry = Entry(self, width = 60)
self.lEntry.grid(row = 7, column = 0, sticky = W)
# Button for Log Path Directory Browse
self.lButton = Button(self, text = "Browse", command = lambda: self.browseFiles("l"))
self.lButton.grid(row = 7, column = 1, sticky = W)
# Text Box for Results
self.resultText = Text(self, width = 60, height = 30, wrap = WORD, borderwidth = 3, relief = SUNKEN)
self.resultText.grid(row = 9, column = 0, columnspan = 2, sticky = "nsew")
# Scrollbar for Text Box
self.scrollBar = Scrollbar(self, command = self.resultText.yview)
self.scrollBar.grid(row = 9, column = 2, sticky = "nsew")
self.resultText["yscrollcommand"] = self.scrollBar.set
def browseFiles(self, btnCalling):
if(btnCalling == "d"):
self.dName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.dEntry.delete(0, END)
self.dEntry.insert(0, self.dName)
elif(btnCalling == "c"):
self.cName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.cEntry.delete(0, END)
self.cEntry.insert(0, self.cName)
elif(btnCalling == "l"):
self.lName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.lEntry.delete(0, END)
self.lEntry.insert(0, self.lName)
output = extractGPS(self.dName, self.cName, self.lName)
self.resultText.delete(0.0, END)
self.resultText.insert(0.0, output)
# Start the GUI
root = Tk( )
root.title("Python gpsExtractor")
root.geometry("650x650")
app = Application(root)
root.mainloop( )

AttributeError or ImportError in python calculator program

I am writing a calculator program with python, and i keep getting an error message
AttributeError: 'Application' object has no attribute 'response_txt'
from tkinter import *
class Application(Frame):
""" GUI application calculator. """
def __init__(self, master):
""" Initialize the frame. """
super(Application, self).__init__(master)
# Adds the grid layout manager
self.grid()
# The result string
self.response_str = ""
#sets up the controls in the frame
self.create_widgets()
def create_widgets(self):
""" Create and sequence """
#Text Sequence
self.sequence_txt = Text(self, height = 1, width = 30, wrap=WORD)
self.sequence_txt.grid(row = 0, column = 0, columnspan = 2)
# Configure the Text to center
self.sequence_txt.tag_config("center_align", justify='center')
# Configure the Text to center
self.response_txt.tag_config("center_align", justify='center')
###buttons
# Button 1
Button(self,
bg='1',
command = self.one_btn_clicked,
height = 2
).grid(row = 2, column = 0, sticky = NSEW)
#buttons clicked
def one_btn_clicked(self):
"""This method is run when the one button gets clicked"""
#append a 1
self.response_str+="1"
#update text
self.response_txt.delete(0.0, END)
self.response_txt.insert(0.0, self.response_str, "center_align")
#add number
self.compare_sequences();
#main
root = Tk()
root.title("Calculator")
app = Application(root)
root.mainloop()
When i ran this through the module, it gave me this error:
AttributeError: 'Application' object has no attribute 'response_txt'
I tried importing a submodule like this:
`import self.response_txt`
And then it gave me this error message:
ImportError: No module named 'self'
I really need this to work, school assignment due tomorrow. Any ideas are appreciated, I am very new to programming. I am also aware that the program is not really that close to done, but before I can move to any other steps I need to make sure what I did here will work in the first place. Thank you.
You forgot to intitalise self.response_txt. Furthermore, '1' is not a valid argument for bg in the code:
Button(self,
bg='1',
command = self.one_btn_clicked,
height = 2
).grid(row = 2, column = 0, sticky = NSEW)
Corrected code:
from tkinter import *
class Application(Frame):
""" GUI application calculator. """
def __init__(self, master):
""" Initialize the frame. """
super(Application, self).__init__(master)
# Adds the grid layout manager
self.grid()
# The result string
self.response_str = ""
#sets up the controls in the frame
self.create_widgets()
def create_widgets(self):
""" Create and sequence """
#Text Sequence
self.sequence_txt = Text(self, height = 1, width = 30, wrap=WORD)
self.sequence_txt.grid(row = 0, column = 0, columnspan = 2)
self.response_txt = Text(self, height = 1, width = 30, wrap=WORD)
self.response_txt.grid(row = 0, column = 0, columnspan = 2)
# Configure the Text to center
self.sequence_txt.tag_config("center_align", justify='center')
# Configure the Text to center
self.response_txt.tag_config("center_align", justify='center')
###buttons
# Button 1
Button(self,
bg='white',
command = self.one_btn_clicked,
height = 2
).grid(row = 2, column = 0, sticky = NSEW)
#buttons clicked
def one_btn_clicked(self):
"""This method is run when the one button gets clicked"""
#append a 1
self.response_str+="1"
#update text
self.response_txt.delete(0.0, END)
self.response_txt.insert(0.0, self.response_str, "center_align")
#add number
self.compare_sequences();
#main
root = Tk()
root.title("Calculator")
app = Application(root)
root.mainloop()
Also you haven't created compare_sequences function.

Python-tkinter: For loop supposed to collect entries from an array and pass to text box, only passes last entry

I'm new to coding, so apologies if this question is a little base. Anyways, this GUI im making in python is supposed to collect several user entries, and pass them to a text box in the GUI. Right now though, the for loop at the end of the code is only putting the last entry into the text box. Why?
from Tkinter import *
class Application(Frame):
""" A SPC program that takes user input and saves the file """
def __init__(self,master):
""" initializes the frame """
Frame.__init__(self,master)
self.grid()
#creates an array to store entries into
self.entry_list = [None]*7
self.create_widgets()
def create_widgets(self):
"""create widgets for user inputted data"""
# creates a text widget next to the entries that displays what the user has input
Label(self, text = "Do these values you entered seem correct?").grid(row = 0, column = 4, sticky = W, padx = 5, pady = 5)
self.checktext = Text(self, width =15, height = 42, wrap = WORD)
self.checktext.grid(row = 1, rowspan = 10, column = 4, sticky = W, padx =5, pady =5)
# get name
Label(self, text = "First Name:").grid(row = 0, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[0] = Entry(self)
self.entry_list[0].grid(row = 0, column = 1)
Label(self, text = "Last Name:").grid(row = 1, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[1] = Entry(self)
self.entry_list[1].grid(row = 1, column = 1)
# get work order
Label(self, text = "Work Order Number:").grid(row = 2, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[2] = Entry(self)
self.entry_list[2].grid(row = 2, column = 1)
# get todays date
Label(self, text = "Todays Date:").grid(row = 3, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[3] = Entry(self)
self.entry_list[3].grid(row = 3, column = 1)
# get bubble number
Label(self, text = "Bubble Number:").grid(row = 4, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[4] = Entry(self)
self.entry_list[4].grid(row = 4, column = 1)
# get USL and LSL
Label(self, text = "USL:").grid(row = 5, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[5] = Entry(self)
self.entry_list[5].grid(row = 5, column = 1)
Label(self, text = "LSL:").grid(row = 6, column = 0, sticky = W, padx=5, pady=5)
self.entry_list[6] = Entry(self)
self.entry_list[6].grid(row = 6, column = 1)
# button to submit user entered values up to the input data values portion of the gui
self.button = Button(self)
self.button["text"] = "Submit"
self.button["command"] = self.submit
self.button.grid(row = 5, column = 2, sticky = W, padx=5, pady=5)
# creates a spot to dictate whether USL and LSL are correct
self.checklimits = Text(self, width = 20, height = 3, wrap = WORD)
self.checklimits.grid(row = 6, column = 3, sticky = W, padx = 5)
"""# get User Input Data values
Label(self, text = "Enter Results:").grid(row = 7, column = 0, sticky = W, padx=5, pady=5)
self.entry_list8 = Text(self, width = 15, height = 30)
self.entry_list8.grid(row = 7, column = 1) """
def submit(self):
""" submits user data up to input data section of GUI and checks USL vs LSL"""
# checks to make sure limits were imput properly
USL = int(self.entry_list[5].get())
LSL = int(self.entry_list[6].get())
if USL > LSL:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.checklimits.delete(0.0, END)
self.checklimits.insert(0.0, message)
# puts entries into text box
for x in self.entry_list:
entry = x.get()
if entry:
self.checktext.delete(0.0, END)
self.checktext.insert(END, entry + "\n")
root = Tk()
root.title("SPC Input Program")
root.geometry("700x750")
app = Application(root)
The problem is here:
for x in self.entry_list:
entry = x.get()
if entry:
self.checktext.delete(0.0, END)
self.checktext.insert(END, entry + "\n")
You're deleting everything in the widget before putting the next string into it, every time. To fix the issue, simply don't delete everything every time. If you want to clear the widget before repopulating it, move the deletion out of the loop:
self.checktext.delete(0.0, END)
for x in self.entry_list:
entry = x.get()
if entry:
self.checktext.insert(END, entry + "\n")
Ok I figured it out and boy do I feel dumb. So here was my for loop before:
for x in self.entry_list:
entry = x.get()
if entry:
self.checktext.delete(0.0, END)
self.checktext.insert(END, entry + "\n")
That self.chectext.delete(0.0, END) line is there to delete whatever the user input into the text box each time they submit, but by being inside the for loop it deleted each entry before adding the next. So duh, of course it would only show the last entry because it deleted the first few! So I put the line outside of the for loop like so:
# puts entries into text box
self.checktext.delete(0.0, END)
for x in self.entry_list:
entry = x.get()
if entry:
print entry
self.checktext.insert(END, entry + "\n")
and now it works fine

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