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])
Related
I have a tkinter gui and I would like it to retain the original window position and size upon relaunching.
Here is an answer that illustrates how to set a specific position and dimensions, but not a word about remembering the settings: How to specify where a Tkinter window opens?
Highly appreciate any help.
The only way to remember settings from session to session is to write them into a file. So, get the root window geometry (it's a string) and write it into a file. If you want the function to be executed automatically as a hook, bind it to the "<Configure>" event:
def save_size(event):
with open("myapp.conf", "w") as conf:
conf.write(root.geometry()) # Assuming root is the root window
root.bind("<Configure>",save_size)
You can later read the geometry from the file and restore it.
#Here I save the x and y position of the window to a file "myapp.conf"
#Here I see if the file exists.
if os.path.isfile("myapp.conf"):
#Here I read the X and Y positon of the window from when I last closed it.
with open("myapp.conf", "r") as conf:
root.geometry(conf.read())
else:
#Default window position.
root.geometry('610x270+0+0')
def on_close():
#custom close options, here's one example:
#close = messagebox.askokcancel("Close", "Would you like to close the program?")
#if close:
#Here I write the X Y position of the window to a file "myapp.conf"
with open("myapp.conf", "w") as conf:
conf.write(root.geometry())
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_close)
It took me pretty much time to get my head around actual implementation of this. So I wanted to share my final code. Based on DyZ suggestion.
I didn't use <Configure> event as suggested because only saving before quit is enough for me.
class Window(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# ...
# bla bla bla
# My GUI codes came here
# ...
# Try to load last saved window data
self.statusbar['text']="reading ini file..."
ini_file_path = "mapedit.ini"
try:
# if the file is there
# get geometry from file
ini_file = open(ini_file_path,'r')
self.geometry(ini_file.read())
self.statusbar['text']= "ini file read"
ini_file.close()
except:
# if the file is not there, create the file and use default
# then use default geometry.
self.statusbar['text']="ini file not found. New file created."
ini_file = open(ini_file_path, 'w')
ini_file.close()
self.geometry("640x400+100+200")
def client_exit(self):
self.save_geo()
self.destroy()
def save_geo(self):
# save current geometry to the ini file
try:
with open("mapedit.ini", 'w') as ini_file:
ini_file.write(self.geometry())
self.statusbar['text']="geo sv"
ini_file.close()
except:
statusbar['text']="ini file not found"
'''
This is where I created GUI instance
'''
if __name__ == "__main__":
win = Window()
# attach deletion handler to 'client_exit' method
win.protocol("WM_DELETE_WINDOW", win.client_exit)
win.mainloop()
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 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()
Hello Im writing a program in python and pyqt4 to control a amplifier.The program connects with a serial port(pyserial module). Now I want to modify my version that it can be used on other platforms and computers. I have already loaded and add a list with all serial ports to a ComboBox. Because its exhausting to choose and connect the port every time Im starting the program, I want the ComboBox to save the last chosen Port and connect to it. I'm new in Python and have no idea.How can I save and load the last String chosen in a ComboBox?
All I can think of is doing some File I/O.
Say, you have a file index.txt . You would need to store the index, so, each time the combo box is activated, you open the file in read mode, read the number inside, close the file, change the integer to the current item's index, open the file in write mode, write the new integer to it and close the file again. This way you always have the latest chosen item's index stored in a file.
Then, at startup, you open the file again and read the string inside. You set the combobox's current index to that of this string using .setCurrentIndex(). This will automatically connect to a combo box's currentIndexChanged() signal.
Here an example program:
import sys
from PyQt4 import QtGui, QtCore
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.initUI()
def initUI(self):
centralwidget = QtGui.QWidget()
self.combo = QtGui.QComboBox(self)
self.combo.addItem("Serial 1")
self.combo.addItem("Serial 2")
self.combo.addItem("Serial 3")
self.combo.addItem("Serial 4")
self.combo.addItem("Serial 5")
self.combo.currentIndexChanged[str].connect(self.Show)
f = open("index.txt","rt")
index = f.read()
f.close()
self.combo.setCurrentIndex(int(index))
grid = QtGui.QGridLayout()
grid.addWidget(self.combo,0,0)
centralwidget.setLayout(grid)
self.setGeometry(300,300,280,170)
self.setCentralWidget(centralwidget)
def Show(self, item):
print("Connected to: ",item)
f = open("index.txt","rt")
index = f.read()
f.close()
index = self.combo.currentIndex()
f = open("index.txt","wt")
f.write(str(index))
f.close()
def main():
app = QtGui.QApplication(sys.argv)
main= Main()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Note: For this to work you need to create an index.txt file with a number in it, in the same directory as your program is.
hello there
i am making a text editor in Tkinter (python)
and so i made a menu and wanted to know how i can call a function that will display the windows Save-as or open boxes that every program uses.
For example in notepad you can click file-save and then it opens the windows save box.
I already have the menu but how can i open the save box.
Thanks a lot.
Here is an example from http://www.daniweb.com/forums/thread39327.html:
import tkFileDialog
def open_it():
filename = tkFileDialog.askopenfilename()
print filename # test
def save_it():
filename = tkFileDialog.askopenfilename()
print filename # test
def save_as():
filename = tkFileDialog.asksaveasfilename()
print filename # test