I'm using pyqt and I just made a Qfiledialog to save a PDF that my program produced, like this:
QtGui.QFileDialog.getSaveFileName(self, "Save file", "", ".pdf")
But the file must be saved at "P:\", in any folder, but have to be "P:".
How can I do that?
You need directoryEntered and fileSelected signals instead of modal getSaveFileName. Some pseudo code:
self.dialog = QtGui.QFileDialog()
self.dialog.directoryEntered.connect(self.checkDir)
self.dialog.fileSelected.connect(self.saveFile)
self.dialog.setAcceptMode(QFileDialog.AcceptSave)
self.dialog.setFileMode(QFileDialog.AnyFile)
self.dialog.setDirectory("P:")
self.dialog.show()
....
def checkDir(self, directory):
if not (directory.startsWith("P:")):
self.dialog.setDirectory("P:")
def saveFile(self, fileName):
directory = QtCore.QFileInfo(fileName).canonicalPath()
Related
I'm trying to add a default name to QFileDialog() the images below illustrate.
This is what I get (no filename)
and this is what I want to achieve without having to input it manually, I want to pass the file_name threw a function and have that name show up there.
This is the code im trying to make to work:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import *
import sys
class mainwindowUI(QMainWindow):
def __init__(self):
super(mainwindowUI, self).__init__()
self.exportFiles('test.mp3')
def exportFiles(self,file_name):
filename, _ = QFileDialog.getSaveFileName(self, "Save audio file", "", "Audio Files (*.mp3)")
if filename:
print(filename)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = mainwindowUI()
app.exec_()
I tried to add options:
filename, _ = QFileDialog.getSaveFileName(self, "Save audio file", "", "Audio Files (*.mp3)", options=QFileDialog.setLabelText(file_name))
But this is incorrect and i have no idea how to make it work...
Anyone know how to add a file name to save file dialog?
The third argument indicates the initial name:
def exportFiles(self, file_name):
default_dir ="/home/qt_user/Documents"
default_filename = os.path.join(default_dir, file_name)
filename, _ = QFileDialog.getSaveFileName(
self, "Save audio file", default_filename, "Audio Files (*.mp3)"
)
if filename:
print(filename)
First create a save-as action
self.saveas=QAction(QtGui.QIcon('saveas.png'),'save-as')
Add the save-as action to toolbar
toolbar=self.addToolbar('toolbar');
toolbar.addAction(self.saveas);
Sub this for your QFileDialog code
Fn, _=QFileDialog.getSaveFileName(self,'export pdf',file_name,'Pdf files(.pdf);;All files()');
when connecting the signal to the slot do this
Self.Saveas.toggled.connect(self.exportfiles('name of default file');
I am working on developing a file selection dialog using Python 3.6 and pyqt5. The basic idea of the dialog is that it has the option to preview files before selecting. It can preview any kinds of registered windows files. The design was done using QtDesigner MainWindow.
Now I can open this preview file browser from another pyqt/python3 file. But how can I retrieve the selected filename and file path from that script?
Here is the test file where I am opening the preview browser file:
class TestBrowser(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self,browser):
super(self.__class__, self).__init__()
self.setupUi(self) # This is defined in design.py file automatically
# It sets up layout and widgets that are defined
self.browser=browser
self.pushButton.clicked.connect(self.dario)
def dario(self):
self.browser.exec_()
def main():
app = QApplication(sys.argv)
browser=bd.BrowserDialog()
main=TestBrowser(browser)
main.show()
sys.exit(app.exec_())
if __name__ == '__main__': # if we're running file directly and not importing it
main()
I personally use globals on a different .py file (for sanity purposes) for stuff like this when I get stuck on "how can I move a value from another class/function/something".
On new .py file:
file_name = None
file_path = None
# Save function
def save_filename(selected_file, selected_path):
global file_name, file_path
file_name = selected_file
file_path = selected_path
And on your browser when you select a file, add:
mynewpyfile.save_filename(file, path)
Then from your main window you can get the file data as:
self.pushTestbutton.clicked.connect(self.do_something)
def do_something(self):
print("the selected file is" + mynewpyfile.file_path + "/" + mynewpyfile.file_name)
Other alternatives: http://doc.qt.io/qt-5/qfiledialog.html
In this approach you just add a QlineEdit and... athough limited, it can't be easier than this.
self.lineTest.setText(QtWidgets.QFileDialog.getOpenFileName()[0])
I would like to change the text of a Label widget from the QLabel class to display the file path of an image file chosen by a user when they click a button to open the file dialog to choose an image from their computer. Here is the code:
class GUI(QMainWindow):
#Load the GUI.
def __init__(self):
super().__init__()
#Define the window icon.
self.window_icon = QIcon("LightMap.png")
#Make the UI.
self.init_ui()
#Fill the GUI.
def init_ui(self):
#Load the UI file.
main_window = uic.loadUi("mainwindow.ui", self)
#Set the window icon.
self.setWindowIcon(self.window_icon)
#Add commands for actions under the submenus.
self.command_file_menu(main_window)
self.command_settings_menu(main_window)
self.command_help_menu(main_window)
#Handle the case that the user clicks on the "Open Image" button.
main_window.button_open_image.setStatusTip("Open Image")
main_window.button_open_image.clicked.connect(self.open_file)
#Make sure this variable has been declared so that we can click "Start Mapping" at any time.
self.file_chosen = None
#Handle the case that the user clicks on the "Start Mapping" button.
main_window.button_start_mapping.setStatusTip("Start Mapping")
main_window.button_start_mapping.clicked.connect(self.start_mapping)
#Show the main window.
self.show()
#Add commands for actions under the File menu.
def command_file_menu(self, main_window):
#Back-end logic for Open Image.
main_window.action_open_image.setShortcut("CTRL+O")
main_window.action_open_image.setStatusTip("Open Image")
main_window.action_open_image.triggered.connect(self.open_file)
#Open an image file.
def open_file(self):
#Select the file dialog design.
dialog_style = QFileDialog.DontUseNativeDialog
dialog_style |= QFileDialog.DontUseCustomDirectoryIcons
#Open the file dialog to select an image file.
self.file_chosen, _ = QFileDialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "",
"JPEG (*.JPEG *.jpeg *.JPG *.jpg *.JPE *.jpe *JFIF *.jfif);; PNG (*.PNG *.png);; GIF (*.GIF *.gif);; Bitmap Files (*.BMP *.bmp *.DIB *.dib);; TIFF (*.TIF *.tif *.TIFF *.tiff);; ICO (*.ICO *.ico)", options=dialog_style)
#Show the path of the file chosen.
if self.file_chosen:
#Change the text on the label to display the file path chosen.
else:
#Change the text on the label to say that "No file was selected. Please select an image."
#This 'else' statement is used to catch the case where the user presses 'Cancel' after opening the file dialog,
#which will close the file dialog without choosing any file, even if they had already previously chosen a file
#from previously opening the file dialog.
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())
I have already tried to directly pass main_window into open_file() and directly set the label text like this: main_window.label_file_name.setText(self.file_chosen), but the file dialog opens immediately as I launch the GUI with the error TypeError: argument1 has unexpected type NoneType.
I managed to get this feature working with TkInter, but I haven't been able to figure out how to repeat that functionality over to PyQt5. Here is an example of my working TkInter code:
class GUI:
#Structure the GUI.
def __init__(self):
#Create a blank window.
self.root = Tk()
#Create the frame.
frameRoot = Frame(self.root)
frameRoot.pack()
#Create the menu.
menu = Menu(self.root)
self.root.config(menu=menu)
#Create the "File" submenu.
fileMenu = Menu(menu, tearoff=0)
menu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Open Image", command=self.openFile)
#Make a button to open the image file.
self.fileChosen = None #Prevent the user from mapping without first selecting an image.
self.buttonFile = Button(frameRoot, text="Open Image...", command=self.openFile)
self.buttonFile.grid(row=3, column=1)
#Display the directory path of the file chosen.
self.fileName = StringVar()
self.fileName.set("No File Selected")
self.labelFileName = Label(frameRoot, textvariable=self.fileName, fg="red")
self.labelFileName.grid(row=4, column=1)
#Keep the window open.
self.root.mainloop()
#Open the image file.
def openFile(self):
#Only accept the following file types.
self.fileChosen = filedialog.askopenfilename(filetypes=[("Bitmap Files", "*.BMP *.bmp *.DIB *.dib"),
("JPEG", "*.JPEG *.jpeg *.JPG *.jpg *.JPE *.jpe *JFIF *.jfif"),
("PNG", "*.PNG *.png"),
("GIF", "*.GIF *.gif"),
("TIFF", "*.TIF *.tif *.TIFF *.tiff"),
("ICO", "*.ICO *.ico")
])
#If a file was selected, show the file path. Else, inform the user.
if self.fileChosen:
self.fileName.set(self.fileChosen)
else:
self.fileName.set("No image was selected. Please select an image.")
if __name__ == "__main__":
#Create an object to access the class.
g = GUI()
The key to my success with my TkInter implementation was the usage of the StringVar() class which comes from TkInter. I've tried doing a mix of TkInter and PyQt5 just to get this requirement working, but that just threw some more errors.
In your case you should be able to access the variable main_window since it allows me to access the label, for this you must pass it as a parameter, so I would suggest that you use a lambda function and modify your code to:
[...]
main_window.button_open_image.clicked.connect(lambda: self.open_file(main_window))
#Open an image file.
def open_file(self, main_window):
#Select the file dialog design.
dialog_style = QFileDialog.DontUseNativeDialog
dialog_style |= QFileDialog.DontUseCustomDirectoryIcons
#Open the file dialog to select an image file.
self.file_chosen, _ = QFileDialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "",
"JPEG (*.JPEG *.jpeg *.JPG *.jpg *.JPE *.jpe *JFIF *.jfif);; PNG (*.PNG *.png);; GIF (*.GIF *.gif);; Bitmap Files (*.BMP *.bmp *.DIB *.dib);; TIFF (*.TIF *.tif *.TIFF *.tiff);; ICO (*.ICO *.ico)", options=dialog_style)
#Show the path of the file chosen.
if self.file_chosen:
main_window.label_file_name.setText(self.file_chosen)
#Change the text on the label to display the file path chosen.
else:
main_window.label_file_name.setText("No file was selected. Please select an image.")
#Change the text on the label to say that "No file was selected. Please select an image."
#This 'else' statement is used to catch the case where the user presses 'Cancel' after opening the file dialog,
#which will close the file dialog without choosing any file, even if they had already previously chosen a file
#from previously opening the file dialog.
Is there any way to directly browse to a folder using QFileDialog?
Meaning, instead of double clicking on each folder while navigating to the destination folder, simply enter the path somewhere or use a hotkey like the one (Shift+Command+G) in Finder on Mac OS X.
Thanks!
EDIT: (my code)
filter = "Wav File (*.wav)"
self._audio_file = QtGui.QFileDialog.getOpenFileName(self, "Audio File",
"/myfolder/folder", filter)
self._audio_file = str(self._audio_file)
If you use the static QFileDialog functions, you'll get a native file-dialog, and so you'll be limited to the functionality provided by the platform. You can consult the documentation for your platform to see if the functionality you want is available.
If it's not available, you'll have to settle for Qt's built-in file-dialog, and add your own features. For your specific use-case, this should be easy, because the built-in dialog already seems to have what you want. It has a side-bar that shows a list of "Places" that the user can navigate to directly. You can set your own places like this:
dialog = QtGui.QFileDialog(self, 'Audio Files', directory, filter)
dialog.setFileMode(QtGui.QFileDialog.DirectoryOnly)
dialog.setSidebarUrls([QtCore.QUrl.fromLocalFile(place)])
if dialog.exec_() == QtGui.QDialog.Accepted:
self._audio_file = dialog.selectedFiles()[0]
Here's a convenience function for quickly making an open/save QFileDialog.
from PyQt5.QtWidgets import QFileDialog, QDialog
from definitions import ROOT_DIR
from PyQt5 import QtCore
def FileDialog(directory='', forOpen=True, fmt='', isFolder=False):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
options |= QFileDialog.DontUseCustomDirectoryIcons
dialog = QFileDialog()
dialog.setOptions(options)
dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
# ARE WE TALKING ABOUT FILES OR FOLDERS
if isFolder:
dialog.setFileMode(QFileDialog.DirectoryOnly)
else:
dialog.setFileMode(QFileDialog.AnyFile)
# OPENING OR SAVING
dialog.setAcceptMode(QFileDialog.AcceptOpen) if forOpen else dialog.setAcceptMode(QFileDialog.AcceptSave)
# SET FORMAT, IF SPECIFIED
if fmt != '' and isFolder is False:
dialog.setDefaultSuffix(fmt)
dialog.setNameFilters([f'{fmt} (*.{fmt})'])
# SET THE STARTING DIRECTORY
if directory != '':
dialog.setDirectory(str(directory))
else:
dialog.setDirectory(str(ROOT_DIR))
if dialog.exec_() == QDialog.Accepted:
path = dialog.selectedFiles()[0] # returns a list
return path
else:
return ''
Use getExistingDirectory method instead:
from PyQt5.QtWidgets import QFileDialog
dialog = QFileDialog()
foo_dir = dialog.getExistingDirectory(self, 'Select an awesome directory')
print(foo_dir)
In PyQt 4, you're able to just add a QFileDialog to construct a window that has a path textfield embedded inside of the dialog. You can paste your path in here.
QtGui.QFileDialog.getOpenFileName(self, 'Select file') # For file.
For selecting a directory:
QtGui.QFileDialog.getExistingDirectory(self, 'Select directory')
Each will feature a path textfield:
Below you'll find a simple test which opens directly the dialog at a certain path, in this case will be the current working directory. If you want to open directly another path you can just use python's directory functions included in os.path module:
import sys
import os
from PyQt4 import QtGui
def test():
filename = QtGui.QFileDialog.getOpenFileName(
None, 'Test Dialog', os.getcwd(), 'All Files(*.*)')
def main():
app = QtGui.QApplication(sys.argv)
test()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
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)