Python: Drag from pyqt5 to folder/desktop - python

I have this script that allows dragging a file to a pyqt5 gui and receiving its path:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from idna import unicode
class MainWidget(QMainWindow):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.setWindowTitle("Drag to here")
self.resize(720, 480)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
files = [unicode(u.toLocalFile()) for u in event.mimeData().urls()]
for f in files:
print(f)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = MainWidget()
demo.show()
sys.exit(app.exec_())
The only problem is that I would like to drag a file from the pyqt5 gui to the desktop/folder. Is there any way to do this?

Related

How to do override closeEvent functions to make it working

I'm using pyside2 and pyqt5 lib to loading my UI file.
from PySide2 import QtWidgets
from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
class A(QtWidgets.QWidget):
def __init__(self, parent=None):
super(A, self).__init__(parent)
self.ui = QUiLoader().load('uiFile.ui')
def closeEvent(self, event):
event.ignore()
app = QApplication([])
mainWin = A()
mainWin.ui.show()
app.exec_()
In my thought, it will show '11111' when I clicked the X button.
However, it's not working at all.
here is the ui file
The problem is that "A" is a widget that is not displayed, it is not the window, so override closeEvent does not make sense. Instead you should use an event filter to monitor the window's events.
from PySide2.QtCore import QEvent, QObject
from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
class Manager(QObject):
def __init__(self, ui, parent=None):
super(Manager, self).__init__(parent)
self._ui = ui
self.ui.installEventFilter(self)
#property
def ui(self):
return self._ui
def eventFilter(self, obj, event):
if obj is self.ui:
if event.type() == QEvent.Close:
event.ignore()
return True
super().eventFilter(obj, event)
def main():
app = QApplication([])
manager = Manager(QUiLoader().load("uiFile.ui"))
manager.ui.show()
app.exec_()
if __name__ == "__main__":
main()
If you want to override the closeEvent method of the QMainWindow used in the .ui then you must promote it and register it as this other answer shows.

How can i disable mouse press event for special widget?

I tried to disable it by using attribute QtCore.Qt.WA_TransparentForMouseEvents, also I tried to disable my frame, but ef mousePressEvent(self, event) is still working
import sys
from b import *
from PyQt5 import QtCore, QtGui, QtWidgets
class main_interface(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.ui.frame.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
def mousePressEvent(self, event):
print('pressed')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = main_interface()
myapp.show()
sys.exit(app.exec_())

Why does the QMainWindow not show? [duplicate]

I am loading a QMainWindow from an .ui file - it's working fine but window events like resize won't be triggered. I can't really figure out what I am doing wrong.
This is the code:
class TestWindow(QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QUiLoader()
file = QFile(abspath("ui/mainwindow.ui"))
file.open(QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
def resizeEvent(self, event):
print "resize"
app = QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
The .ui file can be found here.
It seems that you have a confusion, but for you to understand call the test method of TestWindow:
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
And if you move the small window observe that the event is triggered.
Why does that happen?: QUiLoader creates a widget based on the .ui that unlike uic.loadUi() or ui.loadUiType() of PyQt5 does not load in the main widget but creates a new widget, maybe that's a disadvantage but that's the limitations.
So depending on what you want to do there are several options:
To load the .ui with QUiLoader() it is not necessary to have TestWindow as a parent since it can be a QObject that monitors the events through an event filter.
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class Manager(QtCore.QObject):
def __init__(self, parent_widget=None, parent=None):
super(Manager, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent_widget)
file.close()
self.window.installEventFilter(self)
self.window.show()
self.setParent(self.window)
self.window.destroyed.connect(lambda *args: print(">>>>>>"))
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.Close and self.window is obj:
self.window.removeEventFilter(self)
elif event.type() == QtCore.QEvent.Resize and self.window is obj:
print("resize")
return super(Manager, self).eventFilter(obj, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = Manager()
sys.exit(app.exec_())
Another option is to make the self.widow the centralwidget (the QMainWindow in the .ui will be the centralwidget of the TestWindow, so the resize will be from the TestWindow not from the .ui but as if the size of the .ui is changed, the same will happen with TestWindow):
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
if file.open(QtCore.QFile.ReadOnly):
self.window = loader.load(file, parent)
file.close()
self.setCentralWidget(self.window)
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
The previous methods only serve to notify you of the event but if you want to overwrite it is better that you use pyuic converting the .ui to .py

PySide2 display same icon in file dialog as main window

I have a simple pyside2 application which looks kinda like this:
import sys
from PySide2.QtWidgets import QApplication, QDialog, QPushButton, QFileDialog, QVBoxLayout
from PySide2 import QtGui
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.setWindowTitle("My Form")
self.setWindowIcon(QtGui.QIcon("myicon.png"))
layout = QVBoxLayout()
self.button = QPushButton("Open dialog")
self.button.clicked.connect(self.browse)
layout.addWidget(self.button)
self.setLayout(layout)
def browse(self):
qfd = QFileDialog()
qfd.setWindowIcon(QtGui.QIcon("myicon.png"))
filename, _ = qfd.getOpenFileName(None, "Load Data", ".", "*.txt")
if __name__ == '__main__':
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the form
form = Form()
form.show()
# Run the main Qt loop
sys.exit(app.exec_())
I want to setup the same icon for the QFileDialog as the main window icon but for some reason it does not work. Is there a way to set it like I'm trying above? Thanks for ideas, pointers and help in advance! (I'm using Ubuntu 20.04)
The getOpenFileName method is a static method that creates an internal QFileDialog other than "qfd" so the icon is not applied. One possible option is not to use getOpenFileName but to create the logic only using the QFileDialog class, and another solution is to access the QFileDialog object created inside getOpenFileName using the characteristic that is a toplevel:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class Form(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.setWindowTitle("My Form")
self.setWindowIcon(QtGui.QIcon("myicon.png"))
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Open dialog")
self.button.clicked.connect(self.browse)
layout.addWidget(self.button)
def browse(self):
QtCore.QTimer.singleShot(0, self.handle_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
None,
"Load Data",
".",
"*.txt",
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
def handle_timeout(self):
for w in QtWidgets.QApplication.topLevelWidgets():
if isinstance(w, QtWidgets.QFileDialog):
w.setWindowIcon(QtGui.QIcon("myicon.png"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
form = Form()
form.show()
sys.exit(app.exec_())

PyQt: clicking X doesn't trigger closeEvent

I'm a total newbie in PyQt trying to develop simple application. I have designed simple ui with Qt-designer. I want extra confirmation if the user really want to exit application when clicking X or ,,Exit'' button or choosing Exit from menu.
Here's the code:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('main_window.ui')
self.ui.show()
self.ui.btnExit.clicked.connect(self.close)
self.ui.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
The problem is that:
When I click X on main window the closeEvent function doesn't trigger
When I click Exit button or choose ,,Exit'' from menu, the function
is called, but clicking Yes doesn't close application.
I have found some questions on SO and searched for tutorials, but nothing covered such problem. What am I doing wrong?
Note that you're doing:
self.ui = uic.loadUi('main_window.ui')
self.ui.show()
Your actual window is an instance attribute (ui) inside win. Not the win itself. And it doesn't have closeEvent implemented.
loadUi can load the .ui file inside an instance.
PyQt4.uic.loadUi(uifile[, baseinstance=None[, package='']])
You should use that. With that, your code would be:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
uic.loadUi('main_window.ui', self)
self.btnExit.clicked.connect(self.close)
self.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Note: I'm not a fan of showing the window in __init__. Explicit is better. So, I moved that to main. Feel free to modify it.
it works for me, just adding this line
self.ui.closeEvent = self.closeEvent
so your code would be:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('main_window.ui')
self.ui.closeEvent = self.closeEvent
self.ui.show()
self.ui.btnExit.clicked.connect(self.close)
self.ui.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Another simple solution for this is using the app.aboutToQuit.connect(self.close_event) to run the code in the closeEvent function whenever the user clicks the close button.
Sample code here
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
#--------------------------------------------------------------------------------
app.aboutToQuit.connect(self.closeEvent) #this line is what ur looking for !!!!!!
#--------------------------------------------------------------------------------
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle('Demo')
#{______________________________________
def closeEvent(self):
#Your code here
print('User has pressed the close button')
import sys
sys.exit(0)
#}______________________________________
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
From the designer you can connect events to the main window, and add new slots to it in the designer, then just implement the methods in python and the event->slot connection will be done automatically.

Categories