How can I save text files for tkinter - python

I write a code like this:
import tkinter as tk
from tkinter import *
def note1():
window = tk.Tk()
window.title("Not")
window.geometry("300x600+90+0")
notes = Entry(window,font="Verdana 14 italic")
notes.pack()
notesf = tk.Label(text=notes,font = "Verdana 10 italic" )
notesf.pack
window = tk.Tk()
window.title("Note")
window.geometry("1680x1050+90+0")
monhts = tk.Label(text="OCAK",font = "Verdana 50 italic")
monhts.pack()
day1= tk.Button(text="1 Ocak",font = "Verdana 30 italic",command=note1)
day1.place(x=75,y=250)
window.mainloop()
But my problem isn't with all code if you look at the Def line everything seems normal but I just want to save this entry like you just write x person will pay 10 dollars and you close the program after that. When you open it again it shouldn't disappear. I have just trying to solve this for a couple of hours but I still don't have an idea. Please help me.
Here we are writing entries:

Welcome to Stack Overflow!
In order to achieve this, you will need to save the contents in a text file and then retrieve them when required. Here is a working example of what you are looking for:
import tkinter as tk
from tkinter import *
def save(cont, win):
with open ('save.txt', 'w+') as file:
file.write(cont.get())
file.close()
win.destroy()
def retrieve(cont):
with open ('save.txt', 'r') as file:
data = file.read()
file.close()
return data
def note1():
window1 = tk.Toplevel()
window1.title("Not")
window1.geometry("300x600+90+0")
content = StringVar()
notes = Entry(window1, font="Verdana 14 italic", textvariable = content)
notes.pack()
try:
content.set(retrieve(content))
except:
pass
notesf = tk.Label(text=notes,font = "Verdana 10 italic" )
notesf.pack
window1.protocol("WM_DELETE_WINDOW", lambda cont = content, win = window1: save(cont, win))
window = tk.Tk()
window.title("Note")
window.geometry("1680x1050+90+0")
monhts = tk.Label(text="OCAK",font = "Verdana 50 italic")
monhts.pack()
day1= tk.Button(text="1 Ocak",font = "Verdana 30 italic",command=note1)
day1.place(x=75,y=250)
window.mainloop()
Notes:
I have attached the Entry to a StringVar(), by doing so, I can easily use the .get() and .set() method for getting and setting the content respectively.
You were having 2 instances of Tk() in the same mainloop(), which is not appreciated, make sure you have one Tk() in one mainloop() and the others as Toplevel().
I have used .protocol("WM_DELETE_WINDOW", ...) method on the window since you wanted the save to happen upon closing the window.
The approach that I have mentioned ensures your Entry will display the previously entered data even if you kill the parent window after saving, but if you like to not have the data after killing the parent window and only have it during the runtime, I suggest you to just make use of the StringVar and then set it's previous value, every time you click the button.

Related

Problem creating a simple tkinter GUI that displays names of text files from a folder and their contents when clicked

I have been trying to develop a GUI for my python based voice assistant. The following is a snippet of the code that I am having problem with.What I want to do is display the name of text files from a folder and display their contents in the same window when the user clicks on one of the file names.
from tkinter import *
import os
menu_color = "#2c2b34"
frame_color = "#28262e"
font_color = "#06dff5"
ss_f_button = []
note_f_button = []
note_text = None
def note_window(): #To operate Note Window
global note_f_button
path = os.path.join(sys.path[0], "Notes/")
note_files = [f for f in os.listdir(path)]
note_f_button = []
if len(note_files)>0:
y=60
for i in range(len(note_files)):
note_f_button.append(Button(root, bg=frame_color, fg=font_color, activebackground=frame_color, activeforeground=font_color, bd ="0", text=note_files[i], font=("Helvetica Neue Bold", "10"), cursor="hand2", command=lambda: open_note(note_files[i])))
note_f_button[i].place(x=55, y=y)
y+=40
root.update()
def open_note(f_name): #To operate Note Window
global note_text
if note_text != None:
note_text.place_forget()
note_text = None
path = os.path.join(sys.path[0], "Notes/")
with open(f"{path}{f_name}", "r") as file:
note_text = file.read()
note_text = Label(root, text=note_text, bg=frame_color, fg=font_color, font=("Helvetica Neue Bold", "11"))
note_text.place(x=340, y=60)
root.update()
root = Tk()
root.title("TEST")
root.geometry("706x462")
note_window()
root.update()
root.mainloop()
Here is the output:
You would understand it best if you run it yourself!! If you try this code, be sure to change the font style as Helvetica may not be installed in your system!!
The problem I am facing is that both the files show the same text when clicked, or more specifically, both of them show the same text from the test.txt file.Can anyone please provide a way to do what I am trying to achieve and also point out where I am doing it wrong.I am using Python 3.8.3.

tkinter saving appearance changes

How to make two buttons still appear after closing the program and calling the function causes the addition of further buttons?
Here is the code:
from tkinter import *
win = Tk()
def add_button():
b2 = Button(win, text="click").grid()
b1 = Button(win, text="click", command=add_button).grid()
win.mainloop()
To save/restore the appeareance, in your case you need to save the number of buttons. The basic idea is:
Read the config file containing the number of buttons and create them (see restore_window() in the code below).
Let the users add as many buttons as they want, keeping track of how many buttons were added (in the number_of_btns variable).
Save the number of buttons in a file when the window is closed. To do so I used win.protocol("WM_DELETE_WINDOW", save_and_close) to execute save_and_close() when the user closes the window.
Here is the full code:
# from tkinter import * -> to be avoided because it may lead to naming conflicts
import tkinter as tk
number_of_btns = 0 # keep track of the number of buttons
def restore_window():
try:
with open("window_config.txt", "r") as file: # open file
nb = int(file.read()) # load button number
except Exception: # the file does not exist or does not contain a number
nb = 0
for i in range(nb):
add_button()
def save_and_close():
with open("window_config.txt", "w") as file:
# write number of buttons in file
file.write(str(number_of_btns))
win.destroy()
def add_button():
global number_of_btns # change value of number_of_btns outside the scope of the function
b2 = tk.Button(win, text="click").grid()
number_of_btns += 1
win = tk.Tk()
win.protocol("WM_DELETE_WINDOW", save_and_close) # execute save_and_close when window is closed
b1 = tk.Button(win, text="Add", command=add_button).grid()
restore_window()
win.mainloop()

Tkinter entry widget .get doesn't work

I am fairly new to python and am currently working on a school project, my aim is to create a search bar that can be used to search a data file, however I am struggling to get the search bar to work correctly. I am using the tkinter entry widget.
When I call .get(), the string in the entry widget is not printed. Here is my code...
from tkinter import *
def searchButton():
text = searched.get()
print (text)
def drawStatWindow():
global searched
statWindow = Tk()
statWindow.title("View Statistics")
statWindow.config(bg = "grey")
statWindow.geometry('800x900')
searched = StringVar()
searchBox = Entry(statWindow, textvariable = searched)
searchBox.place(x= 450, y=50, width = 200, height = 24)
enterButton = tkinter.Button(statWindow, text ="Enter", command =searchButton)
enterButton.config(height = 1, width = 4)
enterButton.place(x=652, y=50)
drawStatWindow()
When I type a string into the entry widget and press the enter button, nothing happens.
Like I say I am not very experienced and this is my first project, but after reading about the tkinter entry widgets I can't understand why this won't work.
I am using python V3.4.0
Thanks.
Your code lacks a call to mainloop(). You could try adding it to the end of the drawStatWindow() function:
statWindow.mainloop()
You might want to restructure your code into a class. This allows you to avoid using global variables and generally provides better organisation for your application:
from tkinter import *
class App:
def __init__(self, statWindow):
statWindow.title("View Statistics")
statWindow.config(bg = "grey")
statWindow.geometry('800x900')
self.searched = StringVar()
searchBox = Entry(statWindow, textvariable=self.searched)
searchBox.place(x= 450, y=50, width = 200, height = 24)
enterButton = Button(statWindow, text ="Enter", command=self.searchButton)
enterButton.config(height = 1, width = 4)
enterButton.place(x=652, y=50)
def searchButton(self):
text = self.searched.get()
print(text)
root = Tk()
app = App(root)
root.mainloop()
You have to add mainloop() because tkinter needs it to run.
If you run code in IDLE which use tkinter then IDLE runs own mainloop() and code can work but normally you have to add mainloop() at the end.
And you have to remove tkinter in tkinter.Button.
from tkinter import *
def searchButton():
text = searched.get()
print(text)
def drawStatWindow():
global searched
statWindow = Tk()
statWindow.title("View Statistics")
statWindow.config(bg="grey")
statWindow.geometry('800x900')
searched = StringVar()
searchBox = Entry(statWindow, textvariable=searched)
searchBox.place(x= 450, y=50, width=200, height=24)
# remove `tkinter` in `tkinter.Button`
enterButton = Button(statWindow, text="Enter", command=searchButton)
enterButton.config(height=1, width=4)
enterButton.place(x=652, y=50)
# add `mainloop()`
statWindow.mainloop()
drawStatWindow()
No need to use textvariable, you should use this:
searchBox = Entry(statWindow)
searchBox.focus_set()
searchBox.place(x= 450, y=50, width = 200, height = 24)
then you will be able to use searchBox.get(), that will be a string.

Python/Tkinter dynamically update label

I am currently trying to make a GUI to an existing python program using Tkinter. The program gives the user two options from which the user must choose to either accept or decline. Before using Tkinter the options were placed in the terminal and awaited for a raw_input. (y/n). How can I make this so the canvas text updates with the new data and awaits for the users button click?
To make my question more specific: How can I run another programs code while the Tkinter mainloop is running and make these two interact?
Example code below.
from Tkinter import *
root = Tk()
root.resizable(width=False, height=False)
root.geometry('{}x{}'.format(500,550))
root.wm_title("Tkinter test")
BtnFrame = Frame (root)
BtnFrame.pack(side = BOTTOM)
BtnFrame.place(y=450, x=20)
canvas_1 = Canvas(root, width = "200", height ="300")
canvas_2 = Canvas(root, width = "250", height ="300")
canvas_1.pack(side = LEFT)
canvas_2.pack(side = RIGHT)
textfield_1 = canvas_1.create_text(100,50)
textfield_2 = canvas_2.create_text(100,50,)
def update_textfiel_1(text):
global textfield_1
canvas_1.delete(textfield_1)
textfield = canvas.create_text(100,50,text = text)
def update_textfiel_2(text):
global textfield_2
canvas_2.delete(textfield_2)
textfield1 = canvas1.create_text(100,50,text = text)
Accept = Button(BtnFrame, text="Accept", width=25)
Decline = Button(BtnFrame, text="Decline", width=25)
Accept.pack(side = LEFT)
Decline.pack(side = RIGHT)
root.mainloop()
First off you have some inconsistent variable names in your update_textfiel functions, you can greatly simplify it by using .itemconfigure (documentation for methods on canvas widget)
def update_textfiel_1(new_text):
canvas_1.itemconfigure(textfield_1, text=new_text)
def update_textfiel_2(new_text):
canvas_2.itemconfigure(textfield_2, text=new_text)
If I understand correctly you want a way to have a function that will simply wait for the user to press one of the buttons and then return the result, this is very easy with tkMessageBox:
question = """Do you accept {}?
if you say no you will instead get {}"""
#this message can GREATLY be improved
# But I really don't understand what you are using it for...
def user_confirmation(name1, name2):
response = tkMessageBox.askyesno("Accept or Decline",question.format(name1,name2))
print(response)
if response: # == True
return name1
else:
return name2
I have not yet found a way to make a blocking function that works with the window you have currently...

How to open another window and get data from it, then save to a file?

I'm trying to create a program in python using tkinter, and this program is supposed to have a list of books created by the user. On the main window (the one with the list), there should be a menubar with the option to add a book to the list. When clicked, this option should open another window, this time with one entrybox, where the user should enter the book's title and an add button, to add the button to the list.
The list is saved in a .txt file.
This is the program I wrote so far:
import sys
from tkinter import *
def newBook():
def add():
BookTitle = v.get()
bookTitle = '\n' + BookTitle
books = open('c:/digitalLibrary/books.txt', 'a')
books.write(bookTitle)
books.close()
addWindow = Tk()
v = StringVar()
addWindow.geometry('250x40+500+100')
addWindow.title('digitalLibrary - Add Book')
newBookEntry = Entry(addWindow,textvariable=v)
newBookEntry.pack()
addButton = Button(addWindow, text='ADD', command=add)
addButton.pack()
def refresh():
books = open('c:/digitalLibrary/books.txt', 'r')
bookList = books.readlines()
books.close()
for i in range (0, len(bookList)):
bookOne = Label(text=bookList[i])
bookOne.grid(row=i, column=0, sticky=W)
def quitProgram():
tfQuit = messagebox.askyesno(title='Close Program', message='Are you sure?')
if tfQuit:
window.destroy()
window = Tk()
menubar = Menu(window)
window.geometry('400x400+200+100')
window.title('digitalLibrary')
booksmenu = Menu(menubar, tearoff=0)
booksmenu.add_command(label='Add Book', command=newBook)
booksmenu.add_command(label='Delete Book')
booksmenu.add_command(label='Close Program', command=quitProgram)
menubar.add_cascade(label='digitalLibrary', menu=booksmenu)
books = open('c:/digitalLibrary/books.txt', 'r')
bookList = books.readlines()
books.close()
for i in range (0, len(bookList)):
bookOne = Label(window, text=bookList[i])
bookOne.grid(row=i, column=0, sticky=W)
refreshButton = Button(window, text='Refresh', command=refresh)
refreshButton.grid(row=0, column=1)
window.config(menu=menubar)
window.mainloop()
It seems logical to me that this should work, but it just doesn't. When I click the ADD button on the Add Book window, all it does is add the line break to the .txt file.
I know that it works if I use the OS library and create a separate python file for the add book window, but I'd rather put it all in one code, if possible.
I've tried many things, and tried searching it in the web, but I got nowhere.
The root cause of your problem is that you are creating more than once instance of Tk. You cannot do this. If you want to create a popup window, create an instance of Toplevel. A proper Tkinter application creates exactly once instance of Tk with exactly one invocation of mainloop.
If your main goal is to simply get input from the user (versus learning how to write your own dialog), you might want to consider using one of the built-in dialogs.
For example:
import tkinter.simpledialog as tkSimpleDialog # python 3.x
...
def newBook():
BookTitle = tkSimpleDialog.askstring("Add Book","What is the name of the book?")
if BookTitle is not None:
bookTitle = '\n' + BookTitle
books = open('/tmp/books.txt', 'a')
books.write(bookTitle)
books.close()

Categories

Resources