I am trying to implement in my project a QListWidget with the possibility of moving elements by drag and drop
I try to integrate it into the project in the simplest way without success, while outside I have no problem executing it.
EDIT:The problem seems to come from the realsense library, without its, DAD works
Here is its implementation:
priorityContainer.py:
class priorityContainer(QListWidget):
def __init__(self):
super().__init__()
self.setIconSize(QSize(124, 124))
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDefaultDropAction(Qt.MoveAction)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setAcceptDrops(True)
self.setDragEnabled(True)
for i in range(5):
QListWidgetItem( 'Item '+str(i), self)
main_interface.py:
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
import traceback, sys, os
import pyrealsense2 as rs
from ressource.interface import priorityContainer
class UI_main(QMainWindow):
def __init__(self):
super(UI_main, self).__init__()
self.setupUi()
self.show()
def setupUi(self):
self.centralwidget = QWidget(self)
self.mainVcontainer = QVBoxLayout(self.centralwidget)
self.listWidget = priorityContainer.priorityContainer()
self.mainVcontainer.addWidget(self.listWidget)
self.setCentralWidget(self.centralwidget)
def root_path(self):
return os.path.abspath(os.sep)
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = UI_main()
sys.exit(app.exec_())
I have solved my problem by adding these lines before any other imports where I import my pyrealsense2 librairies:
import sys
sys.coinit_flags = 2
import pythoncom
Reference to the fix: https://github.com/IntelRealSense/librealsense/issues/6174
So I have 2 GUIs. One is the main gui which has one push button to activate the second gui. The second gui is a simple calculator which sums two numbers when I push the button with external function.The second gui (the calculator) runs fine standalone However when I try to activate the second gui from the main one the program crashes so I probably doing something wrong.
Also if I change the code in main to this:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.SumCalcBtn.clicked.connect(self.OpenSecondWindow)
def OpenSecondWindow(self):
self.ex = SumCalculator(self)
self.ex.show()
It runs but doesn't do anything in second gui when I push the button to sum the numbers.(it seems the methods didn't pass to the instance)
I attach the code for better understanding:
Main.py
import sys
from calculators import summary
from PyQt5 import QtCore, QtGui, QtWidgets
from SummaryUI import Ui_SummaryUI
from SummaryMain import SumCalc
from MainWindow import Ui_MainWindow
class SumCalculator(SumCalc):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.SumCalcBtn.clicked.connect(self.OpenSecondWindow)
def OpenSecondWindow(self):
self.ex = SumCalc(self)
self.ex.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
SummaryMain.py
import sys
from calculators import summary
from PyQt5 import QtCore, QtGui, QtWidgets
from SummaryUI import Ui_SummaryUI
class SumCalc(QtWidgets.QMainWindow, Ui_SummaryUI):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_SummaryUI.__init__(self)
self.setupUi(self)
self.CalculateSumBtn.clicked.connect(self.sum_function)
def sum_function(self):
number_a = int(self.FirstNumberInput.text())
number_b = int(self.SecondNumberInput.text())
sum = summary(number_a, number_b)
self.SumResultsValue.setText(str(sum))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = SumCalc()
window.show()
sys.exit(app.exec_())
replace self.ex = SumCalc(self) with self.ex = SumCalc() because the constructor(__init__) function of SumCalc does not take any argument (def __init__(self))
or juts add parameter parent to SumCalc's constructor so it becomes def __init__(self, parent=none)
Either I don't understand completely how Qt's event propagation works or something, but I cannot understand why exactly closeEvent is not being called both for QPushButton-derived class and for QWidget-derived one itself.
Shouldn't wid.closeEvent() trigger closeEvents of all children widgets?
#!/bin/env python
# -*- coding: utf-8 -*-
import sys, os
from Qt.QtCore import *
from Qt.QtWidgets import *
from Qt.QtGui import *
class butt(QPushButton):
def __init__(self, parent, name='Button'):
super(self.__class__, self).__init__(parent)
self.name = name
def closeEvent(self, e):
print('butt closeevent')
e.accept()
class wid(QWidget):
def __init__(self, parent=None):
super(self.__class__, self).__init__(parent)
self.initUI()
def initUI(self):
#self.setAttribute(Qt.WA_DeleteOnClose)
self.vl = QVBoxLayout(self)
self.button = butt(self)
self.button.setText('test1')
self.vl.addWidget(self.button)
self.button.clicked.connect(QCoreApplication.quit)
def closeEvent(self, e):
print('wid closeevent')
e.accept()
def show():
app = QApplication(sys.argv)
win = QMainWindow()
widget = wid(win)
win.setCentralWidget(widget)
win.show()
app.exec_()
if __name__ == "__main__":
show()
I'm expecting to see 2 lines
wid closeevent
butt closeevent
as an output, but I see nothing. Why closeEvent it not being called for them?
In the following examples when you press the button visually you will observe the same behavior: the window will close, but we see the difference, in the first one it is called closeEvent(), and in the second one it is not.
Example1:
#!/bin/env python
# -*- coding: utf-8 -*-
from Qt import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def closeEvent(self, event):
print("button closeEvent")
event.accept()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
button = Button(text="Press me")
button.clicked.connect(button.close)
button.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Example2:
#!/bin/env python
# -*- coding: utf-8 -*-
from Qt import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def closeEvent(self, event):
print("button closeEvent")
event.accept()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
button = Button(text="Press me")
button.clicked.connect(QtCore.QCoreApplication.quit)
button.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Why do not you call closeEvent when you call QCoreApplication::quit?
Because this method is used to exit the event loop of Qt, and if there is no event loop the events(QCloseEvent) do not work.
When a widget is closed, the children widget is not closed, that is, only if a widget is closed, only its own closeEvent will be called. So if you want the closeevent of the widget to be called, call your method close.
#!/bin/env python
# -*- coding: utf-8 -*-
from Qt import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def __init__(self, name="Button", parent=None):
super(Button, self).__init__(parent)
self.m_name = name
def closeEvent(self, event):
print("button closeEvent")
event.accept()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.initUI()
def initUI(self):
vl = QtWidgets.QVBoxLayout(self)
button = Button()
button.setText("test1")
vl.addWidget(button)
button.clicked.connect(self.close)
def closeEvent(self, event):
print("Widget closeevent")
event.accept()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QMainWindow()
widget = Widget()
w.setCentralWidget(widget)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
In the previous example depending on how you interact with the widget you will get the following behavior:
If you press the button the widget will close so it will be called closeEvent, and will not call the closeEvent of the button because even your child is not closing it.
If you press the "X" button in the window it will not be called the closeEvent of the widget but the QMainWindow, the explanation is the same as the previous one.
Conclusions:
Each type of event has its own workflow, some events are only received by the widget and not by the children, while others send the information to the children.
The close method uses the event loop to notify that the widget is to be closed, but QCoreApplication::quit() terminates the event loop.
Update:
why wid.closeEvent is not called when user pressing "X" button on Qt window? Aren't main window supposed to call closeEvent on all it's children widgets and then destroy them properly?
No, one thing is the closing of a widget and another thing is the destruction of the widget, it can be destroyed without closing and closing the window does not involve destroying the object.
As already pointed out closing a window does not imply deleting it, there may be other windows open, but if the last QApplication window is closed by default the eventloop that implies the destruction of the widget will be terminated which does not necessarily imply calling the close method.
To be understood, let's use the following code:
from Qt import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def closeEvent(self, event):
print("closeEvent Button")
super(Button, self).closeEvent(event)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
button_quit = Button(
text="quit",
clicked=QtCore.QCoreApplication.quit
)
button_close = Button(
text="close",
clicked=self.close
)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button_quit)
lay.addWidget(button_close)
def closeEvent(self, event):
print("closeEvent Widget")
super(Widget, self).closeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
There are 2 buttons, in the case of the first button that calls QCoreApplication::quit() that will end the eventloop so all the widgets will be destroyed, and in that case no closeEvent will be called, in the case of the second button it will be call near the window so it will call its closeEvent but not the closeEvents of its children.
my actual problem is that I have saveUI() func in closeEvent, and it's not being called upon widgets hierarchical destruction on window close
If you want the closeEvent method to be called hierarchically then you must call the close method manually since Qt does not design it that way. In the next part there is an example:
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButton(QtWidgets.QPushButton):
def closeEvent(self, event):
for children in self.findChildren(
QtWidgets.QWidget, options=QtCore.Qt.FindDirectChildrenOnly
):
children.close()
print("closeEvent PushButton")
super(PushButton, self).closeEvent(event)
class LineEdit(QtWidgets.QLineEdit):
def closeEvent(self, event):
for children in self.findChildren(
QtWidgets.QWidget, options=QtCore.Qt.FindDirectChildrenOnly
):
children.close()
print("closeEvent LineEdit")
super(LineEdit, self).closeEvent(event)
class ComboBox(QtWidgets.QComboBox):
def closeEvent(self, event):
for children in self.findChildren(
QtWidgets.QWidget, options=QtCore.Qt.FindDirectChildrenOnly
):
children.close()
print("closeEvent ComboBox")
super(ComboBox, self).closeEvent(event)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
button_close = PushButton(text="close", clicked=self.close)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button_close)
lay.addWidget(LineEdit())
lay.addWidget(ComboBox())
def closeEvent(self, event):
for children in self.findChildren(
QtWidgets.QWidget, options=QtCore.Qt.FindDirectChildrenOnly
):
children.close()
print("closeEvent Widget")
super(Widget, self).closeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I am quite new to python. For my problem I cannot seem to find an answer. And sadly I didn't find anything that could held me. I try to call a function from another file in the same folder but it won't work. If I call the same function from the same file, it works just fine. The same goes for external classes.
This code works:
import sys
from PyQt5 import QtWidgets
from ui.mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.show()
self.ui.pushButton.clicked.connect(test_function)
def test_function():
window.ui.stackedWidget.setCurrentIndex(1)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
The following code won't work:
import sys
from PyQt5 import QtWidgets
from ui.mainwindow import Ui_MainWindow
from other_file import test_function
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.show()
self.ui.pushButton.clicked.connect(test_function)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
other_file.py
def test_function():
window.ui.stackedWidget.setCurrentIndex(1)
Error: cannot import name 'test_function'
I am trying to learn how to use python and pyQt.
I have done a window with Qtcreator then I used pyuic4, I have also created a class called Ruban I would like to use it with my window interface. In my window I have a button called nouveauRuban. I would like to create an object from my class Ruban when this button is clicked.
I know my code is wrong, the problem may be at the initial part of mainTN, on the __init__ ?
# -*- coding: utf-8 -*-
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from mainwindow import Ui_MainWindow
from Ruban import Ruban
class mainTM(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None): #, parent=None ??
super (mainTM, self).__init__(self, parent) #(parent) ??
self.createWidgets()
self.nouveauRuban.connect(nouveauRuban, QtCore.SIGNAL(_fromUtf8("clicked()")), self.nvRuban)
def nvRuban(self):
self.ruban=Ruban()
self.ruban.info_ruban()
def createWidgets(self):
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
if __name__== "__main__":
app=QApplication(sys.argv)
myapp=mainTM()
myapp.show()
sys.exit(app.exec_())
Here is a re-write of your script which should fix all the problems:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from mainwindow import Ui_MainWindow
from Ruban import Ruban
class mainTM(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(mainTM, self).__init__(parent)
self.setupUi(self)
self.nouveauRuban.clicked.connect(self.nvRuban)
def nvRuban(self):
self.ruban = Ruban()
self.ruban.info_ruban()
if __name__== '__main__':
app = QApplication(sys.argv)
myapp = mainTM()
myapp.show()
sys.exit(app.exec_())
If you're connecting a signal to a slot, you need to define that slot using a decorator:
#QtCore.pyqtSlot()
def nvRuban(self):
self.ruban=Ruban()
self.ruban.info_ruban()
Then connect it:
self.nouveauRuban.clicked.connect(nvRuban)