Python tkinter passing input value within the same class - python

Most of the code below is just so the problem is accurately replicated, the issue most likely is in the hand-off of filename fromaskopenfilenameI() to printing(stringToPrint)or the if statement at the end.
Goal
The goal of this program is to simply print the file path to the console when Print File Path button is clicked.
Current state
When the program is executed the window appears correctly and the it lets you select a file in the file system. Once the file is opened, the script seems to call printing method before it executes its own print statement. When I open another file it prints the only the print statement from askopenfilename() (which is correct).
However, clicking the Print File Path Button does not seem to get work at any stage.
An example output would be:
Value on click: no-file
askopenfilename value: C:/Temp/AFTER_FIRST_OPEN.txt
askopenfilename value: C:/Temp/AFTER_SECOND_OPEN.txt
Code
import Tkinter, Tkconstants, tkFileDialog
filename = 'no-file'
class TkApp(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
# options for buttons
button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
# define buttons
Tkinter.Button(self, text='Open File', command=self.askopenfilename).pack(**button_opt)
Tkinter.Button(self, text='Print File Path', command=self.printing(filename)).pack(**button_opt)
Tkinter.Button(self, text='Quit', command=self.quit).pack(**button_opt)
# define options for opening or saving a file
self.file_opt = options = {}
options['defaultextension'] = '.twb'
options['filetypes'] = [('All', '*')]
options['initialdir'] = 'C:\\'
options['parent'] = root
options['title'] = 'Select a File'
def askopenfilename(self):
"""Returns an opened file in read mode.
This time the dialog just returns a filename and the file is opened by your own code.
"""
global filename
# get filename
filename = tkFileDialog.askopenfilename(**self.file_opt)
# open file on your own
if filename:
print "askopenfilename value: " + filename
return filename
def printing(self, stringToPrint):
print "Value on click: " + stringToPrint
def quit(self):
root.destroy()
if __name__=='__main__':
root = Tkinter.Tk()
root.title("Path Printer")
TkApp(root).pack()
root.mainloop()

The root of your problem is that you're calling self.printing at the time you create the button. The solution is simple: change self.printing(filename) to be just self.printing, and then have self.printing print an attribute that is set by self.askopenfilename.
For example:
class TkApp(Tkinter.Frame):
def __init__(self, root):
...
self.currentFile = None
...
Tkinter.Button(self, text='Open File', command=self.askopenfilename)
Tkinter.Button(self, text='Print File Path', command=self.printing)
...
def askopenfilename(self):
...
self.currentFile = tkFileDialog.askopenfilename(**self.file_opt)
...
def printing(self):
print "Value on click: " + self.currentFile
Note: a return statement in a function that is called from a button serves absolutely no purpose. The actual caller of the button ignores all return values.

I think the problem is that the self.printing function cannot take arguments when called from a button press. This is common in many GUI libraries. To get around this, I would recommend that you change filename to self.filename, so that it can be called from self.printing even if it isn't passed.
The code would be:
import Tkinter, Tkconstants, tkFileDialog
class TkApp(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
# options for buttons
button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
#moved initiation of filename to here so it will print if no file has been selected
self.filename = 'no-file'
# define buttons
Tkinter.Button(self, text='Open File', command=self.askopenfilename).pack(**button_opt)
Tkinter.Button(self, text='Print File Path', command=self.printing).pack(**button_opt) #not the removal of variable.
Tkinter.Button(self, text='Quit', command=self.quit).pack(**button_opt)
# define options for opening or saving a file
self.file_opt = options = {}
options['defaultextension'] = '.twb'
options['filetypes'] = [('All', '*')]
options['initialdir'] = 'C:\\'
options['parent'] = root
options['title'] = 'Select a File'
def askopenfilename(self):
"""Returns an opened file in read mode.
This time the dialog just returns a filename and the file is opened by your own code.
"""
# get filename - edited to be part of self
self.filename = tkFileDialog.askopenfilename(**self.file_opt)
# open file on your own
if self.filename:
print "askopenfilename value: " + self.filename
return self.filename
def printing(self):
print "Value on click: " + self.filename
def quit(self):
root.destroy()
if __name__=='__main__':
root = Tkinter.Tk()
root.title("Path Printer")
TkApp(root).pack()
root.mainloop()

Related

Python code to close tkinter pop up window without killing the actual program

I'm new to Python and with help from here I have drafted a code that gets input from a user and pass it on to other programs.
is there a way to close the pop up window without actually terminating or closing the program. I tried using Destroy() but it either just clears the content of the pop up message or messes the whole code.
Could somebody help me out here please. Below is the code I drafted.
import openpyxl
import tkinter as tk
class App(tk.Frame):
def __init__(self,master=None,**kw):
self.answers = {}
tk.Frame.__init__(self,master=master,**kw)
tk.Label(self,text="Give Input Sheet Path").grid(row=0,column=0)
self.Input_From_User1 = tk.Entry(self)
self.Input_From_User1.grid(row=0,column=1)
tk.Label(self,text="Give Output Sheet Path").grid(row=1,column=0)
self.Input_From_User2 = tk.Entry(self)
self.Input_From_User2.grid(row=1,column=1)
tk.Button(self,text="Feed into Program",command = self.collectAnswers).grid(row=2,column=1)
def collectAnswers(self):
self.answers['Input_Path'] = self.Input_From_User1.get()
self.answers['Output_Path'] = self.Input_From_User2.get()
print("Given Input Path ", self.answers['Input_Path'])
print("Given Output Path ", self.answers['Output_Path'])
global Input_Path
global Output_Path
Input_Path = self.answers['Input_Path']
Output_Path = self.answers['Output_Path']
def main():
root = tk.Tk()
root.geometry("300x100")
App(root).grid()
root.mainloop()
wb = openpyxl.load_workbook(Input_Path)
return wb["Sheet1"]
if __name__ == '__main__':
main()
If all you want is for the TK window to "go away" without actually closing, you could use the iconify() method instead of destroy(); this will minimize the App() window to the taskbar without actually closing it.
I added self.iconify() to the end of your collectAnswers() method.
I also took the liberty of making some changes to your code's style to better align with standard Python style practices - if you aren't already using a linter like Flake8 or a formatter like Black, I would recommend doing so! Better to get used to having a style guide enforced before you develop bad habits!
import openpyxl
import tkinter as tk
class App(tk.Tk): # root application instance
def __init__(self,**kw) -> None:
super().__init__()
self.geometry("300x100")
self.title = ("Enter Sheet Paths")
self.resizable(width=False, height=False)
self.grid()
input_label = tk.Label(
self,
text="Give Input Sheet Path"
)
input_label.grid(row=0, column=0)
self.Input_From_User1 = tk.Entry(self)
self.Input_From_User1.grid(row=0, column=1)
output_label = tk.Label(
self,
text="Give Output Sheet Path"
)
output_label.grid(row=1, column=0)
self.Input_From_User2 = tk.Entry(self)
self.Input_From_User2.grid(row=1, column=1)
submit = tk.Button(
self,
text="Feed into Program",
command=self.collect_answers
)
submit.grid(row=2, column=1)
self.answers = {}
def collect_answers(self) -> None:
self.answers['Input_Path'] = self.Input_From_User1.get()
self.answers['Output_Path'] = self.Input_From_User2.get()
print("Given Input Path ", self.answers['Input_Path'])
print("Given Output Path ", self.answers['Output_Path'])
input_path = self.answers['Input_Path']
output_path = self.answers['Output_Path']
self.iconify() # MINIMIZE THE WINDOW
def main():
app = App()
app.mainloop()
wb = openpyxl.load_workbook(Input_Path)
return wb["Sheet1"]
if __name__ == '__main__':
main()

pass tkinter openfilename to a instance variable

Checked:
python pass variable tkinter
Tkinter - How to pass instance variable to another class?
and other web resources but didn't find a solution.
I have a Tkinter button to open file:
import tkinter as tk
from tkinter import filedialog as fd
from myClass import my_function
class select_file:
def __init__(self):
self.root = tk.Tk()
self.filename = ""
tk.Button(self.root, text="Browse", command=self.open).pack()
self.root.mainloop()
def open(self):
filetypes = (('LOG files', '*.LOG'), ('All files', '*.*'))
self.filename = fd.askopenfilename(title='open LOG file', filetypes=filetypes)
self.root.destroy()
print(self.filename)
return self.filename
and that's work fine since I can get the file path in right way.
Output:
C:/Users/xxxx/xxxxx/Dataset/SC180918.LOG
My question is how I can pass the selected filename as instance variable to other function within same project but in another file (myClass.py):
class my_function:
log_frame = pd.DataFrame()
def __init__(self, file):
self.file = file
def create_df(self):
myClass.log_frame = pd.read_table(self.file, sep=';', index_col='TimeStamp', parse_dates=True)
return myClass.log_frame
My task is to pass the file to create_df.
I tried several code I will not post to avoid confusion and not working code.
As the file is important, I generated two python files as below:
myClass.py:
class my_function:
def __init__(self, file):
self.file = file
def create_df(self):
print("filename in my_function is ",self.file)
testMe.py:
import tkinter as tk
from tkinter import filedialog as fd
from myClass import my_function
class select_file:
def __init__(self):
self.root = tk.Tk()
self.filename = ""
tk.Button(self.root, text="Browse", command=self.open).pack()
self.root.mainloop()
def open(self):
filetypes = (('LOG files', '*.LOG'), ('All files', '*.*'))
self.filename = fd.askopenfilename(title='open LOG file', filetypes=filetypes)
self.root.destroy()
print("filename in select_file is ",self.filename)
return self.filename
sfClass = select_file() # select filename by Browse
filename = sfClass.filename # get filename from the class
mfClass = my_function(filename) # pass it to the class
mfClass.create_df()
here is the output if I select testMe.py file:
filename in select_file is C:/Users/XXX/XXX/SOquestions/testMe.py
filename in my_function is C:/Users/XXX/XXX/SOquestions/testMe.py
as a result, filename has been successfully passed to the my_function.
I tested as below as well:
print(mfClass.file)
it prints: C:/Users/XXX/XXX/SOquestions/testMe.py
I would do as following;
sfClass = select_file() # select filename by Browse
filename = sfClass.filename # get filename from the class
mfClass = my_function(filename) # pass it to the class

Using Tkinter to create a GUI that creates a folder and unwrap a ZIP file

Hello fellow programmers,
Im trying to make a GUI with Tkinter. This is the first time that Ive used Tkinter, and Ive run into some issues. The script and GUI should do the following:
Ask user (via entry and 'ok' button) to enter the name of the working folder. Result -> Create the newly made folder on the desktop of the system.
Select an OWL file (which is a zip-file) via TkFileDialog.
Result -> unwrap the selected zip-file in the folder that has been created in step 1.
The script Ive written so-far using online tutorials:
import Tkinter
import Tkconstants
import tkFileDialog
import zipfile
from Tkinter import *
import os
class TkFileDialogExample(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
root.configure(background='lightgrey')
root.wm_title("Audit tool: Thickness of pavement")
root.geometry('{}x{}'.format(500, 500))
Label_1 = Message(root, text="Step 1. Please fill in the name of the output folder and click on 'create'. The output folder will be created in the desktop folder:", width=380,)
Label_1.grid(row=1, columnspan=5)
Entry1 = Entry(root)
Entry1.grid(row=2, sticky=E)
folder_location = '~/Desktop/' + Entry1.get()
def createname():
return os.mkdir(os.path.expanduser(folder_location))
button_1 = Button(root, text="Create", command=createname)
button_1.grid(row=2, column =1, sticky=W)
Label_3 = Message(root, text="Step 2. Please select the OWL file:", width=300,)
Label_3.grid(row=5, sticky=W)
button_2 = Button(self, text='Click here to select the OWL file', command=self.askopenfilename)
button_2.grid(row=4,column=1, sticky=W)
self.file_opt = options = {}
options['defaultextension'] = '.owl'
options['filetypes'] = [('all files', '.*'), ('owl files', '.owl')]
options['initialdir'] = 'C:\\'
options['initialfile'] = 'Title_of_OWL-file.ccr'
options['parent'] = root
options['title'] = 'This is a title'
self.dir_opt = options = {}
options['initialdir'] = 'C:\\'
options['mustexist'] = False
options['parent'] = root
def askopenfile(self):
return tkFileDialog.askopenfile(mode='r', **self.file_opt)
def askopenfilename(self):
filename = tkFileDialog.askopenfilename(**self.file_opt)
zip_ref = zipfile.ZipFile(filename, 'r')
if filename:
return zip_ref.extractall(folder_location)
if __name__=='__main__':
root = Tkinter.Tk()
TkFileDialogExample(root).grid()
root.mainloop()
The problem probably lies within the third use of 'folder_location'. Since I am relatively new to the Python language, I cannot seem to find a solution to this problem.
Thank you for your help and time!
Yours truly,
Ruben van der Heijden
The issue is that you have defined the variable folder_location only in the local scope of your TkFileDialogExample.__init__ method. As a result, it is not accessible to any of the other methods of your class. If you do want it to be accessible, then you'll want to set it as an attribute of your class using the self keyword.
def __init__(self, root):
# Stuff
self.folder_location = os.path.join('~', 'Desktop', Entry1.get())
Then you can access it from your TkFileDialogExample.askopenfilename method:
def askopenfilename(self):
filename = tkFileDialog.askopenfilename(**self.file_opt)
zip_ref = zipfile.ZipFile(filename, 'r')
if filename:
return zip_ref.extractall(self.folder_location)
Side Note: In general, it is best to use os.path.join to construct file paths from strings.

WinSound Play sound from variable?

How could I use the winsound.PlaySound() function to play with a variable stored instead of a specific sound? I am making a makeshift Music Player and I want to be able to simply play a song that is selected by the user. Here's my current code.
import Tkinter, Tkconstants, tkFileDialog
import winsound
from Tkconstants import *
from tkFileDialog import *
from PIL import Image, ImageTk
class MusicPlayer(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
# options for buttons
button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
#options for images
# define image
img = Image.open('musicPlayer.PNG')
bg = ImageTk.PhotoImage(img)
label = Tkinter.Label(image=bg)
label.image = bg
label.pack()
# define buttons
but1 = Tkinter.Button(self, text='Play', command=self.play)
but2 = Tkinter.Button(self, text='Stop', command=self.stop)
but1.grid(sticky="S, W, E", column=1)
but1.grid(sticky="S, W, E", column=1)
# define options for opening or saving a file
self.file_opt = options = {}
options['defaultextension'] = '*.wav'
options['filetypes'] = [('WAV Sound Files', '*.wav')]
options['initialdir'] = 'C:\\'
options['initialfile'] = '.wav'
options['parent'] = root
options['title'] = 'Pick a File'
# This is only available on the Macintosh, and only when Navigation Services are installed.
#options['message'] = 'message'
# if you use the multiple file version of the module functions this option is set automatically.
#options['multiple'] = 1
# defining options for opening a directory
self.dir_opt = options = {}
options['initialdir'] = 'C:\\'
options['mustexist'] = False
options['parent'] = root
options['title'] = 'Pick a Dir'
def askopenfile(self):
return tkFileDialog.askopenfile(mode='r', **self.file_opt)
def askopenfilename(self):
# get filename
filename = tkFileDialog.askopenfilename(**self.file_opt)
# open file on your own
if filename:
return open(filename, 'r')
print filename
def asksaveasfile(self):
return tkFileDialog.asksaveasfile(mode='w', **self.file_opt)
def asksaveasfilename(self):
# get filename
filename = tkFileDialog.asksaveasfilename(**self.file_opt)
# open file on your own
if filename:
return open(filename, 'w')
def askdirectory(self):
return tkFileDialog.askdirectory(**self.dir_opt)
def play(self):
soundfile = self.askopenfilename()
winsound.PlaySound(soundfile, winsound.SND_FILENAME)
def stop(self):
winsound.PlaySound(None, winsound.SND_PURGE)
if __name__=='__main__':
root = Tkinter.Tk()
root.iconbitmap(r'C:\Python27\DLLs\musicPlayer.ico')
MusicPlayer(root).pack()
root.wm_title('Music Player')
root.mainloop()
Things to Note
I am new to the winsound plugin, as well as Python itself, and I am not sure which flag I am supposed to use.
Error I get
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
return self.func(*args)
File "C:\Users\Brenneman.Josh.19\Downloads\code (2)\MusicPlayer.py", line 88, in play
winsound.PlaySound(soundfile, winsound.SND_FILENAME)
TypeError: must be string or read-only buffer, not file
winsound's PlaySound() needs to be passed a string with the filename and one or more flags. I'd recommend the SND_ASYNC flag, which plays the sound and returns immediately. Use the following:
winsound.PlaySound('C:/Windows/Media/chimes.wav', winsound.SND_ASYNC)

How can I save a previously created text file after opening and changing it?

I am building a text editor like Notepad in python and i am using Tkinter.
I have implemented New, Open, Save as, Quit,Cut, Copy, Paste, About and Help functions of the editor successfully. But I'm struggling with the Save function.
When I open a previously saved file and save it after editing it is functioning like Save as function. I have used tkFileDialog.asksavefile to save the text file and tkFileDialog.asksavefilename to implement the Save as function of the editor.
I am very new to python.
Can anyone guide me here ?
#! /usr/bin/python
import Tkinter
from Tkinter import *
import tkFileDialog, tkMessageBox
import os
class OpenEdit:
def __init__(self):
# Root Frame widget
self.root = Tk()
# Menu panel in frame
menubar = Menu(self.root)
# File menu,for open,save,save as and quit
filemenu = Menu(menubar)
editmenu = Menu(menubar)
filemenu.add_command(label="New", command=self.new)
filemenu.add_command(label="Open", command=self.open)
filemenu.add_command(label="Save", command=self.save)
filemenu.add_command(label="Save as", command=self.save_as)
filemenu.add_separator()
filemenu.add_command(label="Quit", command=self.root.quit)
menubar.add_cascade(label="File", menu=filemenu)
#Edit menu including Cut, Copy and Paste
editmenu = Menu(menubar)
editmenu.add_command(label="Cut", command=self.cut)
editmenu.add_command(label="copy", command=self.copy)
editmenu.add_command(label="Paste", command=self.paste)
menubar.add_cascade(label="Edit", menu=editmenu)
# About menu for show about us and help
aboutmenu = Menu(menubar)
aboutmenu.add_command(label="About", command=self.about)
aboutmenu.add_command(label="Help", command=self.help)
menubar.add_cascade(label="About", menu=aboutmenu)
# Returning defined setting for GUI
self.root.config(menu=menubar)
#Setting up the title of the widget
self.root.title("Untitled - OpenEdit")
# Adding Text Widget in the GUI
self.text = Text(self.root)
# This line allows it to be resized
self.text.pack(expand=YES, fill=BOTH)
self.root.mainloop()
#Defining new method
def new(self):
self.root.title("Untitled - OpenEdit")
self.file = None
self.text.delete(1.0,END)
#Defining open method
def open(self):
self.file = tkFileDialog.askopenfilename(defaultextension=".txt",filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
if self.file == "":
#no file to open
self.file = None
else:
#try to open the file
#set the window title
self.root.title(os.path.basename(self.file) + " - OpenEdit")
self.text.delete(1.0,END)
file = open(self.file,"r")
self.text.insert(1.0,file.read())
file.close()
#Defining save method
def save(self):
fileName = tkFileDialog.asksaveasfile(mode='w')
try:
file = open(fileName, 'w')
textoutput = self.text.get(0.0, END)
file.write(textoutput)
except:
pass
finally:
file.close()
#Defining save_as method
def save_as(self):
fileName = tkFileDialog.asksaveasfilename(initialfile='Untitled.txt',defaultextension=".txt",filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
try:
file = open(fileName, 'w')
textoutput = self.text.get(0.0, END)
file.write(textoutput)
except:
pass
finally:
file.close()
#Defining cut method
def cut(self):
self.text.event_generate("<<Cut>>")
#Defining copy method
def copy(self):
self.text.event_generate("<<Copy>>")
#Defining paste method
def paste(self):
self.text.event_generate("<<Paste>>")
#Defining about method
def about(self):
tkMessageBox.showinfo("OpenEdit","Created by: XYZ")
#Defining help method
def help(self):
tkMessageBox.showinfo("Help","This is help")
#Starting the instance of the class OpenEdit
OpenEdit()
Your save function explicitly prompts for a filename. If you don't want to prompt for a filename, just don't do that.
Instead, use the current filename ... I see open already saves it:
def open(self):
self.file = tkFileDialog.askopenfilename(...
so you can re-use it in save:
def save(self):
# filename = tkFileDialog.asksaveasfile(...
fileName = self.file

Categories

Resources