I'm writing a UI for a python app with wxPython. I've handled a few of the OnX functions but I need help with OnNew and OnSave/SaveAs
Here is my Save and SaveAs code:
def OnSave(self, event):
self.dirname = ""
saveFileDialog = wx.FileDialog(self, "Save Operation File", self.dirname, "",
"Operation Files (*.fwr)|*.fwr|All Files (*.*)|*.*", wx.SAVE|wx.OVERWRITE_PROMPT)
if saveFileDialog.ShowModal() == wx.ID_OK:
contents = self.control.GetValue()
self.filename = saveFileDialog.GetFilename()
self.dirname = saveFileDialog.GetDirectory()
filehandle = open(os.path.join(self.dirname, self.filename), 'w')
filehandle.write(contents)
filehandle.close()
else:
sys.exit(1)
saveFileDialog.Destroy()
def OnSaveAs(self, event):
self.dirname = "";
saveAsFileDialog = wx.FileDialog(self, "Save Operation File As", self.dirname, "",
"Operation Files (*.fwr)|*.fwr|All Files (*.*)|*.*",
wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if saveAsFileDialog.ShowModal() == wx.ID_OK:
contents = self.control.GetValue()
self.filename = saveFileDialog.GetFilename()
self.dirname = saveFileDialog.GetDirectory()
filehandle = open(os.path.join(self.dirname, self.filename), 'w')
filehandle.write(contents)
filehandle.close()
else:
sys.exit(1)
saveFileDialog.Destroy()
# save current contents in the file
# use wxPython output streams
#output_stream = wx.FileOutputStream(saveFileDialog.GetPath())
#if not output_stream.IsOk():
# wx.LogError("Cannot save contents of Operations File '%s'" % saveFileDialog.GetPath())
# return
the commented part at the bottom is another way I found to do it, is using the input and output streams more correct than the way it currently is? Also heres my other question, I got OnNew Working, here is the code:
def OnNew(self, event):
homedir = os.environ['HOME']
if not os.path.exists(homedir):
if getpass.getuser():
homedir = "C:/Users/" + getpass.getuser() + "/"
else:
homedir = "C:/"
newFileDialog = wx.FileDialog(self, "New Operation File", homedir, "",
"Operation Files (*.fwr)|*.fwr|All Files|(*.*)|*.*", wx.FD_CREATE|wx.OVERWRITE_PROMPT)
Everything is great but the OnOpen Method opens an open file dialog, I want a create file dialog (would this be the same as save? Can someone give me an example OnOpen method, and give me some insight into my OnSave and OnSaveAs methods? As you can see there are three aproaches, one in OnSaveAs, one in OnSave, and one commented out at the bottom of OnSaveAs(). As well as many more I didn't write down here. My main question though is how to get the filedialog for new to be a save dialog where you create a file, rather than an open dialog.
Thanks a ton.
SUMMARY:
1) How do you bring up a FileDialog that allows creation of blank files. I assum it will be similar to save, but hwatever ID flags I pass it always gives me an Open button
2) And as for save methods, is it better to do what I showed in the code, or use streams like the commented out section in SaveAs?.
To get the Save dialog, you need to pass the wx.SAVE style flag to your FileDialog object: style=wx.SAVE. You can read more about the save flag here or here.
Here's some example code that worked for me on Xubuntu 14.04 with wxPython 2.8.12.1 and Python 2.7:
import os
import wx
wildcard = "Python source (*.py)|*.py|" \
"All files (*.*)|*.*"
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"File and Folder Dialogs Tutorial")
panel = wx.Panel(self, wx.ID_ANY)
self.currentDirectory = os.getcwd()
saveFileDlgBtn = wx.Button(panel, label="Show SAVE FileDialog")
saveFileDlgBtn.Bind(wx.EVT_BUTTON, self.onSaveFile)
# put the buttons in a sizer
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(saveFileDlgBtn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
#----------------------------------------------------------------------
def onSaveFile(self, event):
"""
Create and show the Save FileDialog
"""
dlg = wx.FileDialog(
self, message="Save file as ...",
defaultDir=self.currentDirectory,
defaultFile="", wildcard=wildcard, style=wx.FD_SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
print "You chose the following filename: %s" % path
dlg.Destroy()
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
I don't see anything wrong with your saving approach. In most cases, it's better to use Python's low level operators instead of using wxPython's. I would use Python's with operator though as that follows the newer idiom better:
with open(os.path.join(self.dirname, self.filename), 'w') as filehandle:
filehandle.write(contents)
Related
I tried to do the save dialog, where I should choose a file extension, when the data will be saved to.
simple code in python:
def onSave(self, e):
dlg = wx.FileDialog(self, "Choose file", self.dir, "", "*.txt|*.docx", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK:
self.file = dlg.GetFilename()
self.dir = dlg.GetDirectory()
#do something
dlg.Destroy()
Only .txt file is shown in file type selector. WHat is it possible to do more than one file type available to choose?
I'm using python 3.8 and the newest version of WxWidgets on Archlinux
I'm building an application with wxPython and I need to ask the user for a file. here are my functions:
def choose_path(self, event):
"""Choose the path"""
self.btnPath.Disable()
path, exists = open_file()
self.btnPath.Enable()
if path is not None:
if exists:
self.txtPath.SetLabel(path)
self.btnOpen.Enable(bool(self.txtPath.GetValue()))
def open_file(default_path="data\\pcap"):
"""Method for opening files,returns the file_path of the choosen file and exists"""
file_path = None
dialog = wx.FileDialog(None, "File Browser", default_path,
style=wx.FD_OPEN | wx.FD_MULTIPLE | wx.STAY_ON_TOP, wildcard=OPEN_WILDCARD)
if dialog.ShowModal() == wx.ID_OK:
file_path = dialog.GetPath()
dialog.Destroy()
return file_path, os.path.exists(file_path)
The problem is that sometimes it takes time to load the FileDialog and the application crashes. what can I do about it?
I am learning Python. Why do I get the error Exception in Tkinter callback?
I'm trying to Browse the file from the button "Browse" and zip the file in "Compress" button. I don't know what is wrong with my code? Please help!
from Tkinter import *
import tkFileDialog
import gzip
class SecureBox(Frame):
def browse(self):
return tkFileDialog.askopenfilename()
def compressFile(self):
f_in = open(self.browse, 'rb')
f_out = gzip.open('compressFile.gz', 'wb')
f_out.writelines(f_in)
f_out.close()
f_in.close()
def createWidgets(self):
# Pick a file from user
self.compress = Button(self)
self.compress["text"] = "1. Browse"
self.compress["command"] = self.browse
self.compress["fg"] = "blue"
self.compress.pack({"side": "top"})
# Pick a file from user and compress the file
self.compress = Button(self)
self.compress["text"] = "2. Compress"
self.compress["command"] = self.compressFile
self.compress["fg"] = "blue"
self.compress.pack({"side": "top"})
# Adding this function to get the widget show up
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
root = Tk()
root.title ("Secure Box")
root.geometry("500x350")
sb = SecureBox(root)
# start the program
sb.mainloop()
root.destroy()
Save the filename as a class attribute, and use that to open the file:
def browse(self):
self.filename = tkFileDialog.askopenfilename()
def compressFile(self):
f_in = open(self.filename, 'rb')
...
Explanation:
Basically, when you're doing open(self.browse, 'rb') you're passing a function reference to open instead of a filename. This won't work, since open cannot open a function, it can open files. You could use open(self.browse(), 'rb') since self.browse() returns a filename, but that would render your Browse button useless, since the file dialog would then be opened when you click the Compress button.
When saving the filename as a class attribute and using that to open the file as I propose above, you also don't need the return in the browse function. In Tkinter, a button callback is called without any arguments and no return arguments are saved, so returning anything doesn't do anything. If you choose to do remove the browse button altogether and use the open(self.browse(), 'rb') method, you do need to return the filename (but it doesn't need to be a class attribute).
I am learning to use wxPython to build a dialogue based program.
I tried following code (simply copied from wxPython Demo):
import wx
#---------------------------------------------------------------------------
class TestPanel(wx.Panel):
def __init__(self, parent, log):
self.log = log
wx.Panel.__init__(self, parent, -1)
b = wx.Button(self, -1, "Create and Show a DirDialog", (50,50))
self.Bind(wx.EVT_BUTTON, self.OnButton, b)
def OnButton(self, evt):
# In this case we include a "New directory" button.
dlg = wx.DirDialog(self, "Choose a directory:",
style=wx.DD_DEFAULT_STYLE
#| wx.DD_DIR_MUST_EXIST
#| wx.DD_CHANGE_DIR
)
# If the user selects OK, then we process the dialog's data.
# This is done by getting the path data from the dialog - BEFORE
# we destroy it.
if dlg.ShowModal() == wx.ID_OK:
self.log.WriteText('You selected: %s\n' % dlg.GetPath())
# Only destroy a dialog after you're done with it.
dlg.Destroy()
#---------------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
#---------------------------------------------------------------------------
overview = """\
This class represents the directory chooser dialog. It is used when all you
need from the user is the name of a directory. Data is retrieved via utility
methods; see the <code>DirDialog</code> documentation for specifics.
"""
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
I ran above code both in Python IDLE and Apatana Studio 3. Here is what I got.
In Python IDLE, I've got:
IDLE Subprocess: no IP port passed in sys.argv.
And in Apatana Studio 3, I've got:
Traceback (most recent call last):
File "C:\Users\User\My Documents\Aptana Studio 3 Workspace\Test Dialogue\main.py", line 61, in
import run ImportError: No module named run
May I know what am I wrong? Thanks a lot. :)
The ImportError is the Python interpreter (the program that runs your Python code) letting you know it cannot find the module (.py file) you are trying to import. Specifically, the error is saying it cannot find the module "run" which you have asked it to import on line 61.
When you do an import in Python, the interpreter searches a bunch of places for the module. One of those is the current directory, and the rest are standard places like where Python libraries are installed. This page has some info about it: http://docs.python.org/2/tutorial/modules.html#the-module-search-path. You'll actually get the same ImportError if you run the program from the command line. It's a Python error, not an Apatana Studio 3 error.
So if you copy "run.py" into the directory with your Python file, the Python interpreter will be able to easily find it when you asks it to import. Another way is to leave the run.py module where it is and change the sys.path at runtime, or add the module location to the PYTHONPATH variable (see link above for more info).
The run.py module isn't needed for what you are trying to achieve though. Here's an example of your code without the run.py module being imported. I'll warn that I'm new to wxPython myself so there may be better ways to do it ;-)
import wx
# This Log class is copied from the run module
class Log(object):
def WriteText(self, text):
if text[-1:] == '\n':
text = text[:-1]
wx.LogMessage(text)
write = WriteText
class TestPanel(wx.Panel):
def __init__(self, parent, log):
self.log = Log()
wx.Panel.__init__(self, parent, -1)
b = wx.Button(self, -1, "Create and Show a DirDialog", (50,50))
self.Bind(wx.EVT_BUTTON, self.OnButton, b)
def OnButton(self, evt):
# In this case we include a "New directory" button.
dlg = wx.DirDialog(self, "Choose a directory:",
style=wx.DD_DEFAULT_STYLE
#| wx.DD_DIR_MUST_EXIST
#| wx.DD_CHANGE_DIR
)
# If the user selects OK, then we process the dialog's data.
# This is done by getting the path data from the dialog - BEFORE
# we destroy it.
if dlg.ShowModal() == wx.ID_OK:
self.log.WriteText('You selected: %s\n' % dlg.GetPath())
# Only destroy a dialog after you're done with it.
dlg.Destroy()
class Frame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size(300, 150))
panel = TestPanel(self, -1)
class App(wx.App):
def OnInit(self):
self.frame = Frame(parent=None)
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__ == '__main__':
app = App()
app.MainLoop()
I'm not sure what's happening with the error in IDLE though. That's weird!
I want the open dialog to filter files by *.spectrum or not filter it (*.* all files).
I also want the save dialog to suggest a .spectrum extension when saving. The common, new file.ext where the new file is highlighted for us to overwrite.
I have set the wildcard = "*.spectrum" for both options, but please give me a more complete solution.
I've written a couple articles on this subject:
wxPython: Showing 2 Filetypes in wx.FileDialog
The Dialogs of wxPython
Basically what you want for the open and save dialogs is something like this:
wildcard = "Python source (*.spectrum)|*.spectrum|" \
"All files (*.*)|*.*"
Then in the code, you'd do something like this:
def onOpenFile(self, event):
"""
Create and show the Open FileDialog
"""
dlg = wx.FileDialog(
self, message="Choose a file",
defaultDir=self.currentDirectory,
defaultFile="",
wildcard=wildcard,
style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR
)
if dlg.ShowModal() == wx.ID_OK:
paths = dlg.GetPaths()
print "You chose the following file(s):"
for path in paths:
print path
dlg.Destroy()
#----------------------------------------------------------------------
def onSaveFile(self, event):
"""
Create and show the Save FileDialog
"""
dlg = wx.FileDialog(
self, message="Save file as ...",
defaultDir=self.currentDirectory,
defaultFile="", wildcard=wildcard, style=wx.SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
print "You chose the following filename: %s" % path
dlg.Destroy()
Note: Code taken directly from my blog and only modified slightly.