I am writing a simple code using pyqt
In the code, I invoke a QFileDialog, however when I invoke it using the static functions all works fine, but with the normal method i.e. using dialog.exec_(), I do not see any files in the file dialog window.
Only after typing the complete path of the file can I see the file in the file dialog window.
Note that this issue is only when I invoke the FileDialoghandler function, If I don't do that, no matter how I invoke the QFileDialog, everything works fine.
And also this issue is only on Linux, on Windows7 everything works ok.
I am wondering whether this is a PyQt bug or am I missing something here?
Code is as follows:
import sys
from PyQt4.QtCore import Qt
from PyQt4.QtGui import *
from PyQt4.QtCore import QAbstractFileEngine
from PyQt4.QtCore import QAbstractFileEngineHandler
from PyQt4.QtCore import QFSFileEngine
class FileDialogHandler(QAbstractFileEngineHandler):
def create(self,filename):
if str(filename).startswith(':'):
return None # Will be handled by Qt as a resource file
print("Create QFSFileEngine for {0}".format(filename))
return QFSFileEngine(filename)
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.textEdit = QTextEdit()
self.setCentralWidget(self.textEdit)
self.statusBar()
openFile = QAction(QIcon('open.png'), 'Open', self)
openFile.setShortcut('Ctrl+O')
openFile.setStatusTip('Open new File')
openFile.triggered.connect(self.showDialog)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(openFile)
self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('File dialog')
self.show()
def showDialog(self):
handler = FileDialogHandler()
#using QFileDialog.getOpenFileName works fine
fname = QFileDialog.getOpenFileName(None, 'Open file', '/home','All files (*.*)')
#dialog = QFileDialog()
#dialog.setOption(QFileDialog.DontUseNativeDialog,False)
#if dialog.exec_():
#fname = dialog.selectedFiles()
#else:
#fname = None
f = open(fname, 'r')
with f:
data = f.read()
self.textEdit.setText(data)
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I encountered a similar problem not long ago with the getOpenFilename. For me the solution was to change the backend from native to Qt's own implementation of the dialog. This can be achieved withan extended calling syntax which looks like:
filename = QtGui.QFileDialog.getOpenFileName(self,
'Open file',
'/home',
'All files (*.*)',
options=QtGui.QFileDialog.DontUseNativeDialog)
After I changed to this calling syntax I never had any problems again.
Encountered the same problem in Windows 10 running the code from command prompt without any IDE. Including options=QtGui.QFileDialog.DontUseNativeDialog did solve the problem. (with python 3.10). For Example:
self.path_open, _ = QFileDialog.getOpenFileName(self, "Open file", "", "e-documents (*.docx *.pdf)",
options=QFileDialog.DontUseNativeDialog)
Related
I am using the code below for opening and reading text files in pyqt.
But what I want is:
I will choose any text file on my hard disk. Then right click on it and choose open with and browse for my pyqt script and the file will be open
with my sript.
I know that I can do it using 'sys.argv' in terminal. But how to do it with gui program? Please let me know.
Current code:
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class OpenFile(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self)
self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('OpenFile')
self.textEdit = QtGui.QTextEdit()
self.setCentralWidget(self.textEdit)
self.statusBar()
self.setFocus()
exit = QtGui.QAction(QtGui.QIcon('open.png'), 'Open', self)
exit.setShortcut('Ctrl+O')
exit.setStatusTip('Open new File')
self.connect(exit, QtCore.SIGNAL('triggered()'), self.showDialog)
menubar = self.menuBar()
file = menubar.addMenu('&File')
file.addAction(exit)
def showDialog(self):
filename = QtGui.QFileDialog.getOpenFileName(self, 'Open file',
'/home')
file=open(filename)
data = file.read()
self.textEdit.setText(data)
app = QtGui.QApplication(sys.argv)
cd = OpenFile()
cd.show()
app.exec_()
I am trying to return a path from a browse folder dialog box.
I have tried passing the instance object or even attribute to the call and setting it there:
self.browseBtn.clicked.connect(myExporter.browseFolder(self))
or
self.browseBtn.clicked.connect(myExporter.browseFolder(self.path))
But this doesn't work. It causes the browser dialog to pop open immediately upon load and then once you choose a folder it errors out with : Failed to connect signal clicked().
I have tried to set the clicked call to a return, with no luck:
result = self.browseBtn.clicked.connect(myExporter.browseFolder)
Can someone lead me in the right direction as far as how to return a value, when you are dealing with separate classes handling the UI and logic? Also... is it bad practice to be separating them like this? I know I could probably easily solve this if I threw everything into just one python file, but I figured that is not proper.
Here is my ui file (ui.py):
from PySide import QtCore, QtGui
class Ui_Dialog(object):
def __init__(self):
self.path =""
def setupUi(self, Dialog, myExporter):
Dialog.setObjectName("Dialog")
Dialog.resize(382, 589)
...
.......
.............
.................
self.retranslateUi(Dialog)
self.tabWidget.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.browseBtn.clicked.connect(myExporter.browseFolder)
Here is my exporter file (exporter.py):
class Exporter(object):
def __init__(self):
...
......
def browseFolder(self):
...
.......
do something
...........
return path
Here is my load/test file (loadExporter.py):
import ui as interface
import exporter as exporter
from PySide import QtCore, QtGui
app = QtGui.QApplication.instance()
if app is None:
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
myExporter = exporter.Exporter()
myUI = interface.Ui_Dialog()
myUI.setupUi(Dialog, myExporter)
Dialog.show()
app.exec_()
It's not necessarily bad to have them in separate files. Having a separate file for certain widgets is a good thing especially if those widgets can be reused.
I would have my main file have a QMainWindow class.
class MyWindow(QtGui.QMainWindow):
pass
if __name__ == "__main__":
QtGui.QApplication([])
mywindow = MyWindow()
mywindow.show()
sys.exit(QtGui.qApp.exec_())
Wrapping the app functionality in if __name__ == "__main__" prevents this code from being run when another file tries to import this file.
A signal (self.browserBtn.clicked) calls a callback method. Everything is an object in python.
def my_func():
pass
new_func_name = my_func # my_func can be reassigned like any variable
my_func is an object. self.browseBtn.clicked.connect(my_func) passes my_func as a variable to be called later.
When self.browserBtn.clicked.emit() happens (on user click) it is the same as calling the connected functions my_func(). Other signals may pass values to callback functions self.lineEdit.textChanged.connect(my_func) calls 'my_func(new_text)'
You want your function to call everything for you.
def open_file(filename=None):
"""Open a file."""
# If a filename isn't given ask the user for a file
if filename is None:
filename, ext = QtGUi.QFileDialog.getOpenFileName(None, "Open File", ".../My Documents/")
# You may have to use the ext to make a proper filename
# Open the file
with open(filename, "r") as file:
file.read()
self.browserBtn.clicked.connect(open_file)
Structure
...
import mywidget
class MyWindow(QtGui.QMainWindow):
def __init__(self):
super().__init__()
...
self.show_file = QtGui.QLineEdit()
self.setCentralWidget(self.show_file)
self.exporter = mywidget.Exporter()
self.browserBtn.clicked.connect(self.open_file)
def open_file(self, filename=None):
"""Open a file."""
path = self.exporter.browseFolder()
# Do something with the path
self.show_file.setText(path)
if __name__ == "__main__":
QtGui.QApplication([])
mywindow = MyWindow()
mywindow.show()
sys.exit(QtGui.qApp.exec_())
I don't think I fully understand what you're trying to achieve, but may I suggest the following solution.
exporter.py
# implementation
dialog.py (Main UI)
import PyQt4.QtGui as qg
from exporter import Exporter
class Dialog(qg.QDialog):
def __init__(self):
super().__init__()
self.path = None
self.setup_widgets()
def setup_widgets(self):
self.browse.clicked.connect(self.on_browse_clicked)
def on_browse_clicked(self):
self.path = Exporter().browse_folder()
main.py
import sys
import PyQt4.QtGui as qg
from dialog import Dialog
if __name__ == '__main__':
app = qg.QApplication(sys.argv)
dialog = Dialog()
dialog.show()
sys.exit(app.exec_())
This way you still have three files, but dialog.py imports exporter.py instead of main.py importing both of them.
As for returning values from signals, I don't know; I think signals are voids (do not return values).
Signals pass arguments to slots via their formal parameters. Usually slots have the same or fewer parameters than their signal counterparts'. It's slots that return values.
I have to write a program with an option to open an image from a file. I have to use QFileDialog and display image in QLabel, using QPixmap. I am able to use them individually but I didn't manage to combine them.
I think I need to take my image name from dlg.selectedFiles but I don't know how to choose the moment when there is useful data in it. Do I need to make a loop in my main program, and constantly check if there is image to open? Can I send a signal to my label using openAction.triggered.connect(...)?
from PyQt4 import QtGui
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
dlg = QtGui.QFileDialog(self)
openAction = QtGui.QAction('Open', self)
openAction.triggered.connect(dlg.open)
fileMenu.addAction(openAction)
#label = QtGui.QLabel(self)
#pixmap = QtGui.QPixmap('')
#label.setPixmap(pixmap)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
app.exec_()
if __name__ == '__main__':
sys.exit(main())
You need to make your own slot and connect it to the openAction signal.
In your __init__ function do:
openAction.triggered.connect(self.openSlot)
In your class MainWindow define the following function:
def openSlot(self):
# This function is called when the user clicks File->Open.
filename = QtGui.QFileDialog.getOpenFileName()
print(filename)
# Do your pixmap stuff here.
I am using PyQt5 5.5.1 (64-bit) with Python 3.4.0 (64-bit) on Windows 8.1
64-bit.
I am having trouble restoring the position and size (geometry) of my
very simple PyQt app.
Here is minimal working application:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
class myApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
view = myApp()
sys.exit(app.exec())
What I read online is that this is the default behavior and we need to
use QSettings to save and retrieve settings from Windows registry,
which is stored in
\\HKEY_CURRENT_USER\Software\{CompanyName}\{AppName}\
Here are some of the links I read.
I could have followed those tutorials but those tutorials/docs were
written for C++ users.
C++ is not my glass of beer, and converting those codes are impossible to me.
Related:
QSettings(): How to save to current working directory
This should do.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import QSettings, QPoint, QSize
class myApp(QWidget):
def __init__(self):
super(myApp, self).__init__()
self.settings = QSettings( 'My company', 'myApp')
# Initial window size/pos last saved. Use default values for first time
self.resize(self.settings.value("size", QSize(270, 225)))
self.move(self.settings.value("pos", QPoint(50, 50)))
def closeEvent(self, e):
# Write window size and position to config file
self.settings.setValue("size", self.size())
self.settings.setValue("pos", self.pos())
e.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
frame = myApp()
frame.show()
app.exec_()
I simplified this example: QSettings(): How to save to current working directory
Similar to #Valentin's response, because I feel settings are being written to registry, which will be issue for cross compatiblity. Here is the relevant startEvent() and closeEvent() for the job.
def startEvent()
self.settings = QSettings(QSettings.IniFormat,QSettings.SystemScope, '__MyBiz', '__settings')
self.settings.setFallbacksEnabled(False) # File only, not registry or or.
# setPath() to try to save to current working directory
self.settings.setPath(QSettings.IniFormat,QSettings.SystemScope, './__settings.ini')
# Initial window size/pos last saved
self.resize(self.settings.value("size", QSize(270, 225)))
self.move(self.settings.value("pos", QPoint(50, 50)))
self.tab = QWidget()
def closeEvent(self, e):
# Write window size and position to config file
self.settings.setValue("size", self.size())
self.settings.setValue("pos", self.pos())
startEvent() should be initiated at startup and closeEvent() should be taken care before quitting the main window.
You should indeed use QSetting for this.
All the Qt examples have been converted to Python. They are included in the source packages of PyQt (or PySide), which you can download here
You can also look online in the github repo, particularly in application.py of mainwindows example.
def readSettings(self):
settings = QSettings("Trolltech", "Application Example")
pos = settings.value("pos", QPoint(200, 200))
size = settings.value("size", QSize(400, 400))
self.resize(size)
self.move(pos)
def writeSettings(self):
settings = QSettings("Trolltech", "Application Example")
settings.setValue("pos", self.pos())
settings.setValue("size", self.size())
Fire writeSettings() before quitting and initiate readSettings() on startup.
In my case I use .ini files to store settings (language, default user, ...). the same code works on both Debian and Windows.
An example:
from PySide.QtCore import QSettings
self.settings = QSettings('settings.ini', QSettings.IniFormat)
...
self.settings.setValue('size', self.size())
I am trying to use smc.FreeImage to load a .NEF files (Nikon Camera RAW) and Display with PySide.
I found this example that loads and displays the commented .JPG file just fine, but it crashes when I replace the pixmap with a FI.Image NEF.
I added the print pixmap.getInfoHeader to make sure the .NEF actually loads which it does, I see the correct Header information in the output window.
How do I translate the read pixmap = FI.Image so that PySide understands it ? I've seen people using numpy and PIL tostring but none of those examples seems to cover this case.
import sys
from PySide import QtGui, QtCore
from smc import freeimage as FI
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout(self)
#pixmap = QtGui.QPixmap("Somefile.jpg")
pixmap = FI.Image("Anotherfile.NEF")
print( pixmap.getInfoHeader() )
lbl = QtGui.QLabel(self)
lbl.setPixmap(pixmap)
hbox.addWidget(lbl)
self.setLayout(hbox)
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Da window Title')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I have tested your minimal example.
Instead of using the smc module you can simple create a new QPixmap object and giving the path to the *.nef file as constructor parameter.
pixmap = QtGui.QPixmap("Path_To_File.NEF")
lbl = QtGui.QLabel(self)
lbl.setPixmap(pixmap)
I have tested your example and it worked without any problems.