How to open a window on top of other windows when calling a function?
import wx
def openFile(wildcard="*"):
app = wx.App(None)
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
dialog = wx.FileDialog(None, 'Open', wildcard=wildcard, style=style)
if dialog.ShowModal() == wx.ID_OK:
path = dialog.GetPath()
else:
dialog.Destroy()
path = 'No file'
return f'<div class="notification error">{path}</div>'
dialog.Destroy()
return f'<div id="pathToFile" class="notification">{path}</div>'
The Accepted answer from #VZ is spot on for all normal usage but strictly speaking, your code can be tweaked to work, even if it serves no real purpose but you'll notice, despite passing wx.STAY_ON_TOP, it will not honour it.
Like so:
import wx
def openFile(wildcard="*"):
app = wx.App(None)
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.STAY_ON_TOP
dialog = wx.FileDialog(None, 'Open', wildcard=wildcard, style=style)
if dialog.ShowModal() == wx.ID_OK:
path = dialog.GetPath()
else:
path = 'No file'
dialog.Destroy()
return f'<div class="notification error">{path}</div>'
print(openFile())
To show a dialog on top of some other top level window you need to specify that window as the dialog parent (instead of using None as you do).
There is no support for showing a native dialog, such as the "Open file" one, on top of all windows, this can only be done for custom windows using wx.STAY_ON_TOP flag.
Related
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)
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 have a program set up so that it displays a FileChooserDialog all by itself (no main Gtk window, just the dialog).
The problem I'm having is that the dialog doesn't disappear, even after the user has selected the file and the program has seemingly continued executing.
Here's a snippet that showcases this issue:
from gi.repository import Gtk
class FileChooser():
def __init__(self):
global path
dia = Gtk.FileChooserDialog("Please choose a file", None,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
self.add_filters(dia)
response = dia.run()
if response == Gtk.ResponseType.OK:
print("Open clicked")
print("File selected: " + dia.get_filename())
path = dia.get_filename()
elif response == Gtk.ResponseType.CANCEL:
print("Cancel clicked")
dia.destroy()
def add_filters(self, dia):
filter_any = Gtk.FileFilter()
filter_any.set_name("Any files")
filter_any.add_pattern("*")
dia.add_filter(filter_any)
dialog = FileChooser()
print(path)
input()
quit()
The dialog only disappears when the program exits with the quit() function call.
I've also tried dia.hide(), but that doesn't work either - the dialog is still visible while code continues running.
What would the proper way to make the dialog disappear?
EDIT: I've since learned that it's discouraged to make a Gtk dialog without a parent window. However, I don't want to deal with having to have the user close a window that has nothing in it and simply stands as the parent for the dialog.
Is there a way to make an invisible parent window and then quit the Gtk main loop when the dialog disappears?
You can set up a window first by doing:
def __init__ (self):
[.. snip ..]
w = Gtk.Window ()
dia = Gtk.FileChooserDialog("Please choose a file", w,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
also, set a default value for path in case the user cancels:
path = ''
Then, at the end of your script:
print (path)
while Gtk.events_pending ():
Gtk.main_iteration ()
print ("done")
to collect and handle all events.
I've got some code that uses the Gtk+ FileChooserDialog in Python 3.4 to allow a user to select a file.
Then, it's supposed to close the dialog (obviously) and continue executing the code that follows the user choosing a file. However, what happens is that the user selects their file, and the code continues, but the dialog doesn't disappear like it should.
I had this issue previously, and we figured out the reason why it was happening then and resolved it, but now it's happening again and although I know what's causing, I don't know how to actually resolve it.
Here's my code:
from gi.repository import Gtk
class FileChooser():
def __init__(self):
global path
dia = Gtk.FileChooserDialog("Please choose a file", None,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
self.add_filters(dia)
response = dia.run()
if response == Gtk.ResponseType.OK:
print("Open clicked")
print("File selected: " + dia.get_filename())
path = dia.get_filename()
elif response == Gtk.ResponseType.CANCEL:
print("Cancel clicked")
dia.destroy()
def add_filters(self, dia):
filter_any = Gtk.FileFilter()
filter_any.set_name("Any files")
filter_any.add_pattern("*")
dia.add_filter(filter_any)
filter_text = Gtk.FileFilter()
filter_text.set_name('Text files')
filter_text.add_mime_type('text/plain')
dia.add_filter(filter_text)
filter_py = Gtk.FileFilter()
filter_py.set_name('Python files')
filter_py.add_mime_type('text/x-python')
dia.add_filter(filter_py)
filter_img = Gtk.FileFilter()
filter_img.set_name('Image')
filter_img.add_mime_type('image/*')
dia.add_filter(filter_img)
dialog = FileChooser()
# path variable will be used after this point
The issue here is that, for reasons unknown to me, if I have the global path declaration in the FileChooser() class' __init__() function, the dialog won't disappear.
If I remove that global path declaration, the dialog goes away, but I get a NameError: name 'path' is not defined later in the program when I try to access the path variable!
I have also tried making path global right at the start of the program, but I still get the NameError.
What can I do to make this variable accessible later in my program, while still making the dialog disappear?
Consider the path variable as an instance to FileChooser(). It provides a logical end to have path accessed by the dialog that is representing the FileChooser().
class FileChooser():
def __init__(self):
#Stores your path
self.path = None
dia = Gtk.FileChooserDialog("Please choose a file", None,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
self.add_filters(dia)
response = dia.run()
if response == Gtk.ResponseType.OK:
print("Open clicked")
print("File selected: " + dia.get_filename())
self.path = dia.get_filename()
elif response == Gtk.ResponseType.CANCEL:
print("Cancel clicked")
dia.destroy()
When you create the object.
dialog = FileChooser()
You can access it as follows:
dialog.path
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.