I try to read dataframe from excel file and print it after button click.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
from PyQt5.QtGui import QIcon
from excel_reading import *
class MyWin(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.hello)
def hello(self):
data_input_from_file = QtWidgets.QFileDialog.getOpenFileName(self,'header','filename','Excel (*.xlsx *.xls)')
print(data_input_from_file)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = MyWin()
myapp.show()
sys.exit(app.exec_())
When I click button, I have such message:
Gtk-Message: 00:03:53.573: GtkDialog mapped without a transient parent. This is discouraged.
('', '')
How should I solve that problem?
I solved the problem:
def hello(self):
data_input_from_file = QtWidgets.QFileDialog.getOpenFileName(self, 'header', 'filename', 'Excel (*.xlsx *.xls)')
print(type(data_input_from_file))
print(data_input_from_file)
print(pd.read_excel(data_input_from_file[0]))
The Gtk warning is just what it is: a warning. You can ignore that. Qt tries to use the system native file dialogs whenever possible, which might result in some warnings in the consolle output.
Your issue is related to something else: there are rare cases for which PyQt functions don't return the same signature as reported in the official Qt (C++) documentation.
QFileDialog static methods is one of such cases, as QFileDialog.getOpenFileName() always returns a tuple: the selected file path and the selected file type filter. This is also clear from the output of your code (which I suppose is caused by cancelling the dialog):
('', '')
The first value is the selected file (in this case, none) and filter (again, none, as there was no selected file).
The solution is to assign two values for what the static returns:
filePath, filters = QtWidgets.QFileDialog.getOpenFileName(
self,'header','filename','Excel (*.xlsx *.xls)')
if filePath:
# do something
Related
is there any way to open a folder with pyqt5 file dialog
I tried taking the quotes, I want to open a folder or a directory with subdirectories or subfolders
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog, QTextEdit, QPushButton, QLabel, QVBoxLayout
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(800, 600)
self.button1 = QPushButton('Open Project Folder')
self.button1.clicked.connect(self.get_folder)
self.labelImage = QLabel()
self.textEditor = QTextEdit()
layout = QVBoxLayout()
layout.addWidget(self.button1)
layout.addWidget(self.labelImage)
layout.addWidget(self.button2)
layout.addWidget(self.textEditor)
self.setLayout(layout)
def get_folder(self):
file_name, _ = QFileDialog.getOpenFileName(
self, 'Project Data', r"", "")
print(file_name)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())```
There are various static functions available for QFileDialog, if you need to open a directory, don't use getOpenFileName but getExistingDirectory().
As you can see from the documentation, the arguments are slightly different, and
if you run help(QtWidgets.QFileDialog.getExistingDirectory) from the python shell, you'll see the full argument signature and the returned value written in the python syntax.
getExistingDirectory(parent: QWidget = None, caption: str = '', directory: str = '', options: Union[QFileDialog.Options, QFileDialog.Option] = QFileDialog.ShowDirsOnly) -> str
The last part ( -> str) means that there is only one returned value, which is the string of the selected directory (which will be empty if the user cancels the dialog).
def get_folder(self):
folder = QFileDialog.getExistingDirectory(
self, 'Project Data', '')
if folder:
print(folder)
I suggest you to always study the documentation of each class you're using, and using the official documentation; even if it's C++ oriented, the functions have the same names on PyQt, and their arguments/returned values are the same in 99% of the cases. Whenever you've a doubt or you face a problem about wrong arguments or returned data, you can check the official PyQt documentation or just use help(class.function) in the python shell.
I'm trying to make a GUI for a small program I wrote with the help of some people from here, anyway, I made the GUI in PyQt and it looks fine. I added a button called dirButton that says "Choose Directory"
self.dirButton = QtGui.QPushButton(self.buttonWidget)
self.dirButton.setGeometry(QtCore.QRect(0, 0, 91, 61))
self.dirButton.setObjectName(_fromUtf8("dirButton"))
self.dirButton.clicked.connect(self.browse)
and in the bottom line there I've made it call self.browse when I click it, which is:
def browse(self):
filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
fname = open(filename)
data = fname.read()
self.textEdit.setText(data)
fname.close()
However, this is the error I get:
Traceback (most recent call last):
File "C:\Users\Kevin\Desktop\python-tumblr-0.1\antearaGUI.py", line 88, in browse
filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
TypeError: QFileDialog.getOpenFileName(QWidget parent=None, QString caption=QString(), QString directory=QString(), QString filter=QString(), QString selectedFilter=None, QFileDialog.Options options=0): argument 1 has unexpected type 'Ui_mainWindow'
So, ui_mainWindow is the class that all of my GUI buttons and the GUI itself is stored in.
class Ui_mainWindow(object):
I don't understand why I'm getting an error, does anyone have any ideas?
Here is a pastebin link to the entire GUI: http://pastebin.com/BWCcXxUW
As I understand, you are using Ui_mainWindow generated from .ui file. As you can see Ui_mainWindow is just python class which contains widgets. getOpenFileName recieves QWidget instance as first parameter. So you need to subclass QWidget or QMainWindow and define methods in that class.
Code will look like this:
import sys
from PyQt4 import QtCore, QtGui
from file_with_ui import Ui_MainWindow
class Main(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
def browse(self):
filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
fname = open(filename)
data = fname.read()
self.textEdit.setText(data)
fname.close()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
Alternatively you can store ui as instance attribute:
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
And acces your controls through self.ui, e.g.: self.ui.textEdit.setText(data)
Consider reading tutorial about pyuic usage PyQt by Example (Session 1)
import the following:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
In class Ui_MainWindow(object), replace object with QWidget:
Ui_MainWindow(QWidget)
def browseFiles(self):
text, placeholder = QFileDialog.getOpenFileName(None, 'Select file')
The way it worked out for me is to use None, rather than self, as self inherits the type of the window above it, which is expected to be None, but is given QMainWindow as a type.
I also unpacked the tuple it returns, since this function returns two objects to work with.
I hope this helps, perhaps someone else could explain this better, as to why it works.
TLDR: The function expects None as the first parameter, but inherits a QmainWindow as type, due to self.
file = str(QFileDialog.getExistingDirectory(None, "Select Directory"))
I want to design my QWizardPages in Qt Designer and I want to load them into my Python program with PySide2. Previously I have been using PyQt5 without any problems but making the switch to PySide2 seems harder then expected.
The problem I am facing is that when I am adding a QWizardPage to my QWizard , the page is indeed added to the Wizard, but also an other (empty) page is added. I'm not able to find what I'm doing wrong so I was wondering if someone can have a look.
I have tried to add the pages with both the functions addPage() and setPage(), but they give the same results. What I also noticed is that when I explicitely set the Title of the page with setTitle(), the empty (unwanted) page gets this title, but not the page I designed in Qt Designer.
import os
import sys
from PySide2.QtWidgets import QWizard, QWizardPage, QApplication
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
from enum import Enum
class MyWizard(QWizard):
def __init__(self):
super().__init__()
self.setPage(PageNumbers.page_one.value, PageOne(self))
class PageOne(QWizardPage):
def __init__(self, parent):
super().__init__(parent)
ui_file = os.path.join(__file__, '..', 'pageOne.ui')
file = QFile(ui_file)
file.open(QFile.ReadOnly)
loader = QUiLoader()
loader.load(file, parent)
file.close()
self.setTitle("This is another test Title")
class PageNumbers(Enum):
page_one = 1
if __name__ == '__main__':
app = QApplication(sys.argv)
wizard = MyWizard()
wizard.show()
app.exec_()
What I would expect is to have just one QWizardPage showing up with directly the Finish button. Instead I get two QWizardPages as shown in this image:
Can someone tell me what's going on?
(I get the expected result using PyQt5 with the following code: https://pastebin.com/6W2sx9M1)
The developers of PyQt implement functions to be able to create classes based on the .ui that is not implemented in Qt by default (Qt/C++ uses the MOC to do this work), but in the case of PySide2-Qt for python it does not implement it, only has the QUiLoader class that allows to create a widget based on the .ui unlike PyQt that allows filling a class.
In conclusion there is no equivalent in PySide2 of the loadUi function so you can not implement the same logic. PySide2 is not PyQt5, there are own equivalences since they use the same base but they have implementations, limitations and advantages.
Going to the practical problem, considering that the .ui is next to the .py the solution is the following:
import os
import sys
from PySide2 import QtCore, QtWidgets, QtUiTools
from enum import Enum
class PageNumbers(Enum):
page_one = 0
class MyWizard(QtWidgets.QWizard):
def __init__(self):
super().__init__()
ui_file = os.path.join(os.path.dirname(os.path.abspath(__file__)) ,'PageOne.ui')
page_one = create_widget(ui_file, self)
self.setPage(PageNumbers.page_one.value, page_one)
def create_widget(filename, parent=None):
file = QtCore.QFile(filename)
if not file.open(QtCore.QFile.ReadOnly):
return
loader = QtUiTools.QUiLoader()
widget = loader.load(file, parent)
return widget
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
wizard = MyWizard()
wizard.show()
sys.exit(app.exec_())
I'm learning pyqt5, and specifically how to use it with the QT Designer. I'm sort of following the turorial HERE. However in this tutorial they are converting the XML interface to Python code with pyuic5, while I'm trying to import it dynamically with uic.loadUi("myui.ui"). In the tutorial we define a slot with the signals and slot editor named " browseSlot".
When I try to run/compile, at the line
dlg = uic.loadUi("myui.ui")
I get the error:
AttributeError: 'QMainWindow' object has no attribute 'browseSlot'
I think what's going on is that QT Designer connects a signal to the slot 'browseSlot' but because a 'browseSlot' method isn't defined in the myui.ui, the error is thrown, because there is no way for the interpreter to know I'm referring to a method that is outside the UI interface file. (In this case, in the module that loads the interface). As far as I can tell QT Designer only lets me connect signals to slots, not define a whole new one. I think that way this is handled in other frameworks is that there will be an abstract method that needs over riding. So what can I do in this situation to make it work?
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import QObject, pyqtSlot
import sys
app = QtWidgets.QApplication([])
dlg = uic.loadUi("myui.ui")
#pyqtSlot
def returnPressedSlot():
pass
#pyqtSlot
def writeDocSlot():
pass
#pyQt
def browseSlot():
pass
dlg.show()
sys.exit(app.exec())
The slots belong to the class that is used returns loadUi(), they are not any functions since they do not magically not connect them, if you want to use loadUi() and implement these methods you must inherit from the class corresponding to the template that you used, in the example of the link Main Window was used so it must be inherited from QMainWindow:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
#QtCore.pyqtSlot()
def returnPressedSlot():
pass
#QtCore.pyqtSlot()
def writeDocSlot():
pass
#QtCore.pyqtSlot()
def browseSlot():
pass
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
try this out
from PyQt5 import QtWidgets, uic
app = QtWidgets.QApplication([])
form = uic.loadUi("login.ui")
form2.show()
app.exec()
the above python code should display your gui app properly as long as you have install PyQt5 and PyQt5-tools,if you haven't then open CMD and typeenter code here "pip install PyQt5" and click enter.once installation is done type "pip install PyQt5-tools" then you are good to go
import sys
from PyQt5.QtWidgets import QSystemTrayIcon, QApplication, QMenu
from PyQt5.QtGui import QIcon
class autoparse():
def __init__(self):
self.main()
def main(self):
app = QApplication(sys.argv)
self.trayIcon = QSystemTrayIcon(QIcon("icons\icon-windowed.ico"), app)
self.menu = QMenu()
self.autopconfig = self.menu.addAction('Config')
self.autopconfig.triggered.connect(self.swapicon)
self.trayIcon.setContextMenu(self.menu)
self.trayIcon.show()
sys.exit(app.exec_())
def swapicon(self):
QSystemTrayIcon.setIcon(QIcon("icons\python.ico"))
test1 = autoparse()
I can get the initial icon to set just fine and I can work around the issue by creating 2 icons for app and then doing a self.trayIcon.hide() and self.newicon.show() but I don't feel this is the right way to do it.
Pycharm shows a notice saying "Expected QSystemTrayIcon, got QIcon" but if I swap QIcon with QSystemTrayIcon then it says Qicon is missing. SOOOOOO I change it to QSystemTrayIcon(QIcon("icons\python.ico") and it still says QIcon is unfilled. It seems like the problem detection is going in circles.
Running the code as is gives me "setIcon (self, QIcon): first argument of unbound method must have type 'QSystemTrayIcon'" when I run the swapicon function. If I remove QIcon so its just setIcon (file) then I get "setIcon (self, QIcon): not enough arguments"
QSystemTrayIcon is not a static element so to change some property you must use the instance, in your case you must change:
QSystemTrayIcon.setIcon(QIcon("icons\python.ico"))
to:
self.trayIcon.setIcon(QIcon("icons\python.ico"))
You may have been confused with QSystemTrayIcon(QIcon("icons\icon-windowed.ico"), app), this is a constructor and can receive the icon.