Having problems with tkinter destroy method with labels - python

First time posting to Stack! I am very new to Python / Tkinter so bear with me.
I am trying to write code that looks for a saved txt file upon startup that describes the path of a chosen XML file, and for it to print a tkinter label based on the chosen directory.
Problem I'm having is this: if you choose the XML file path, it will print the path - which is what I want. But, if you choose another XML file path, the previously printed label doesn't get destroyed, and the new label gets applied on top of the old one. I have looked at other people having similar issues and I'm stuck. I have tried a few different ways of implementing the .destroy() method, and none of them seem to be working. I wouldn't be surprised if there are other errors/redundancies in my code (please focus on the .destroy() issue), but it seems to be working the way I want other than this issue. I do not get any error messages with this code.
Here's what the code looks like right now (I only posted the part that is having the issue, let me know if you need more).
I have been testing this issue by selecting a long file path first, and then a shorter path on the desktop. The path on the desktop will print on top of the previous label instead destroying the previous label, seemingly ignoring the reset() function.
import xml.etree.ElementTree as ET
from tkinter import filedialog
from tkinter import *
import tkinter as tk
root= tk.Tk()
canvas1 = tk.Canvas(root, width = 750, height = 750)
canvas1.pack()
#Destroy previous label
global label_file
def reset():
label_file.destroy()
#Function that saves selected path
def findfile():
reset()
global file_selected
file_selected = filedialog.askopenfilename(filetypes=[("XML Files", "*.xml")])
if file_selected == "":
label_file = tk.Label(root, text= 'Error. Choose location of config.xml:', bg='red' )
canvas1.create_window(370, 165, window=label_file)
else:
label_file = tk.Label(root, text= 'Saved Path: '+ file_selected, bg='yellow' )
canvas1.create_window(370, 165, window=label_file)
savedpath = open("path.txt", "w")
savedpath.write(file_selected)
#Attempts to read save file on startup
try:
with open('path.txt', 'r') as f:
global file_selected
file_selected = f.readline()
label_file = tk.Label(root, text= 'Path: ' + file_selected, bg='#00ff00' )
canvas1.create_window(370, 165, window=label_file)
button1 = tk.Button (root, text='Change Path',command=findfile, bg='orange')
canvas1.create_window(50, 200, window=button1)
#If no save file on startup
except FileNotFoundError:
file_selected = ""
label_file = tk.Label(root, text= 'Choose location of config.xml file: ', bg='red' )
canvas1.create_window(168, 165, window=label_file)
button2 = tk.Button (root, text='Browse',command=findfile, bg='orange')
canvas1.create_window(50, 200, window=button2)
root.mainloop()

Related

How do I shop tkPDFViewer from combining PDF's when opening PDFs using buttons?

In this code, I'm trying to open PDFs as a separate window using tkinter and tkPDFViewer. The way this is done is a simple UI opens up with 2 buttons for 2 articles that are accessed from my computer in this case (but I just labeled it "filepath" for the file path to avoid revealing personal info). However, while the buttons work and open up a PDF window and a download window below that (as expected), when you close the PDF window (and the download window closes along with it) and then re-click on a button (the same one or a different one), it shows the previous pdf and the current one that appeared when you re-click combined. As you repeat this process, the PDFs just append to each other. However, what should happen is that the corresponding PDF to the article that is described in the button is shown and no other PDFs. How do I fix this? I've already tried to move the PDF initialization outside the event function then re-initialize it, but that results in a "local variable used before being defined" error, so that doesn't work, and I currently do not know of any other way to do this.
pdfArray = [
["skweak: Weak Supervision Made Easy for NLP",
r"filepath",
"Pierre Lison, Jeremy Barnes, and Aliaksandr Hubin",
"skweak, NLP, Natural Language Processing"],
["Information Theoretic-Based Quality Measures for Clustering",
r"filepath",
"Barry Drake, and Tiffany Huang",
"Quality Measures, Clustering, Data"
]
]
#Import tkinter library
import os
from tkinter import *
import tkinter as tk
from tkinter import ttk
from tkPDFViewer import tkPDFViewer as pdfViewer
from functools import partial
import shutil
#Create an instance of tkinter frame or window
mainWin= Tk()
#Set the geometry of tkinter frame
mainWin.geometry("1000x600+20+20")
download_icon = tk.PhotoImage(file=r'filepath')
paw_icon = tk.PhotoImage(file=r'filepath')
def download_pdf(original_file):
#this if-else statment detects if the original file exists.
if os.path.isfile(original_file):
newFileStem = os.path.expanduser('~') + r"\Downloads\ChatBox_download"
num = 0
while os.path.isfile(newFileStem + "(%d).pdf"%num):
num = num + 1;
newFile = newFileStem + "(%d).pdf"%num
f = open(newFile, "x")
shutil.copyfile(original_file, newFile)
completeWin = Toplevel(mainWin)
completeWin.geometry("400x75+660+480")
completeWin.title("Download Complete")
Label(completeWin, text = "Download Complete!", font = ('Gabriola', 14, 'bold')).pack()
Label(completeWin, text = str(newFile), font = ('Gabriola', 10)).pack(pady=2)
else:
notFoundWin = Toplevel(mainWin)
notFoundWin.geometry("200x75+660+480")
notFoundWin.title("File Not Found")
Label(notFoundWin, text = "File Not Found", font = ('Gabriola', 14, 'bold')).pack(pady=20)
#Define a new function to open the window
def open_win(pdf_ID):
pdf_title = pdfArray[pdf_ID][0] #title of pdf
file_location = pdfArray[pdf_ID][1] #location of pdf
authors = pdfArray[pdf_ID][2] #authors
keywords = pdfArray[pdf_ID][3] #keywords
pdfWin = Toplevel(mainWin)
pdfWin.geometry("600x350+640+20")
pdfWin.title(pdf_title)
# Adding pdf location and width and height.
pdfViewer.ShowPdf().pdf_view(pdfWin, pdf_location=file_location, width=70, height=100).pack(ipadx = 10, ipady = 10)
infoWin = Toplevel(pdfWin)
infoWin.geometry("600x200+640+420")
infoWin.title("PDF Information")
Label(infoWin, text = "Information: ", font = ('Gabriola', 15, 'bold')).pack(pady=2)
Label(infoWin, text = "Title: " + pdf_title, font = ('Gabriola', 12)).pack(pady=1)
Label(infoWin, text = "Author(s): " + authors, font = ('Gabriola', 12)).pack(pady=1)
Label(infoWin, text = "Keyword(s): " + keywords, font = ('Gabriola', 12)).pack(pady=1)
tk.Button(infoWin, image=download_icon, borderwidth = 0, command=partial(download_pdf, file_location)).pack(pady=1)
#Create a label
Label(mainWin, text= "Click any button below to open a PDF", font= ('Gabriola', 25, 'bold')).pack(pady=30, padx = 10)
#Create a button to open a New Window
for ID in range(0, len(pdfArray)):
tk.Button(mainWin, image=paw_icon, compound=LEFT, text=" Open \" " + pdfArray[ID][0]+" \"", font= ('Gabriola', 12), command=partial(open_win, ID)).pack(pady=2)
mainWin.mainloop()
I ran into this issue as well when using tkPDFViewer.
To fix I had to go into the tkPDFViewer module and add a line:
self.img_object_li.clear()
immediately after the line:
def add_img():
I'm just a beginner myself so this was my fix to get around the issue.
From what I understand the line:
self.img_object_li.append(timg)
adds images indefinitely, I was trying to destroy the frame and widgets containing the objects from my main program but couldn't get it to work at all. Issue just kept persisting. This is probably not the best way to do it and someone else will ahve a better fix.

Merging Files in Tkinter Search Files Application

I am trying to build a simple application using Tkinter wherein I should be able to search files in my local folders and display them. For example, if I am searching a 'test.txt' file, it will return me that file plus all txt files. Now the second part of the problem is, I have to merge all the files that was returned to me in my search into one single file (I know it sounds absurd but please forgive me). I have successfully achieved the first part but not able to implement the second part. Quite new to functions and OOPs concepts. Pasting my code below in the hope for some guidance. Please forgive me for the code quality as I am quite new.
import pandas as pd
from tkinter import *
import os
from docx import Document
doc1 = Document()
def search_file():
file_entry_name = entry.get()
answer.delete(1.0,END)
extension = file_entry_name.split('.')[1]
file_name = file_entry_name.split('.')[0]
file_entry_name = file_entry_name.lower()
for r,d,f in os.walk('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA'):
for file in f:
file.split()
if file.startswith(file_entry_name) or file.endswith(extension):
answer.insert(INSERT,file + '\n')
def merge_file():
# files = os.listdir('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA')
# global answer
# for i in answer:
# if i != '.DS_Store': # i kept getting an error for a hidden file. So excluded it
# doc1.add_heading(i, 2)
# doc2 = Document(i)
# for para in doc2.paragraphs:
# para_in_doc = doc1.add_paragraph(para.text)
# doc1.add_page_break()
# doc1.save('search.docx')
return
root = Tk()
root.title('Docu Search')
topframe = Frame(root)
entry = Entry(topframe)
entry.pack()
button = Button(topframe, text="search",command =search_file)
button.pack()
topframe.pack(side = TOP)
bottomframe = Frame(root)
scroll = Scrollbar(bottomframe)
scroll.pack(side=RIGHT, fill=Y)
answer = Text(bottomframe, width=80, height=50, yscrollcommand = scroll.set,wrap= WORD)
scroll.config(command=answer.yview)
merge_button = Button(bottomframe, text="merge",command =merge_file)
merge_button.pack()
answer.pack()
bottomframe.pack()
root.mainloop()

Getting Tcl error while working with python Tkinter command for GUI

I am working on a GUI that downsamples videos in a folder that the user inputs.
This is the basic framework:
1.On button click the user inputs the path/directory of the videos
2.I have a downsample function that takes this input (path) of the user and downsamples the videos.
EDIT: I have seen similar answers under the same error, I have tried the solution but it's not working and was giving different errors. So, instead, I'm posting this to avoid confusion and would like to learn how to fix this particular one.
This is what I have:
from tkinter import *
from tkinter.ttk import *
from tkinter.filedialog import askopenfile
root = Tk()
root.geometry('200x100')
def open_file():
file = askdirectory()
if file is not None:
return file#add if directory is not correct option
btn = Button(root, text ='Open', command = lambda:open_file())
btn.pack(side = TOP, pady = 10)
#mainloop()
def downsamplevideos(open_file):
for video in os.listdir(open_file):
input_file_name=video
(
ffmpeg
.input('/Users/lala/Desktop/checktwo/{}'.format(input_file_name))
.filter_('scale', 640, 360)
.output("/Users/lala/Desktop/videos/downsampleda{}".format(input_file_name))
.run(capture_stdout=True, capture_stderr=True)
)
btn2 = Button(root, text="Select",command=lambda:downsamplevideos(open_file()))
btn2.pack(side = TOP, pady = 10)
This is opening a window with two button. But it is not working, that is it is not downsampling. Can anyone help me with this implementation?
When you call open_file after pressing the open button, the file path is not stored anywhere. This can be resolved by creating a global variable directory, which will store the file path so it can be used in downsamplevideos.
directory = None
def open_file():
file = askdirectory()
if file is not None:
global directory
directory = file
btn = Button(root, text ='Open', command = lambda:open_file())
btn.pack(side = TOP, pady = 10)
#mainloop()
def downsamplevideos():
global directory
for video in os.listdir(directory):
input_file_name=video
(
ffmpeg
.input('/Users/lala/Desktop/checktwo/{}'.format(input_file_name))
.filter_('scale', 640, 360)
.output("/Users/lala/Desktop/videos/downsampleda{}".format(input_file_name))
.run(capture_stdout=True, capture_stderr=True)
)
btn2 = Button(root, text="Select",command=lambda:downsamplevideos())
btn2.pack(side = TOP, pady = 10)

How can I save text files for tkinter

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.

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.

Categories

Resources