Is there a way to make a loading button out of a QPushButton? I want to do something like https://coreui.io/docs/components/loading-buttons/ but in Qt. Is this possible?
I would like to make a loading/progress bar out of each list widget item like below.
You can use QMovie to load a gif and set it as an icon in a QPushButton, in the following example implement the start and stop method that starts and ends the animation, respectively, and the setGif method that passes the gif path:
from PyQt5 import QtCore, QtGui, QtWidgets
class LoadingButton(QtWidgets.QPushButton):
#QtCore.pyqtSlot()
def start(self):
if hasattr(self, "_movie"):
self._movie.start()
#QtCore.pyqtSlot()
def stop(self):
if hasattr(self, "_movie"):
self._movie.stop()
self.setIcon(QtGui.QIcon())
def setGif(self, filename):
if not hasattr(self, "_movie"):
self._movie = QtGui.QMovie(self)
self._movie.setFileName(filename)
self._movie.frameChanged.connect(self.on_frameChanged)
if self._movie.loopCount() != -1:
self._movie.finished.connect(self.start)
self.stop()
#QtCore.pyqtSlot(int)
def on_frameChanged(self, frameNumber):
self.setIcon(QtGui.QIcon(self._movie.currentPixmap()))
if __name__ == '__main__':
import sys
import random
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
for i in range(5):
button = LoadingButton("Install")
button.setGif("loading.gif")
QtCore.QTimer.singleShot(random.randint(3000, 6000), button.start)
QtCore.QTimer.singleShot(random.randint(8000, 12000), button.stop)
lay.addWidget(button)
w.show()
sys.exit(app.exec_())
loading.gif
Related
I am trying to display a loading gif after a button is pressed. This is the code I currently have
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainWindow (QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow,self).__init__(parent)
self.setGeometry(50,50,240,320)
self.home()
def home(self):
but = QtGui.QPushButton("Example", self)#Creates the brew coffee button
but.clicked.connect(self.gif_display)
but.resize(200,80)
but.move(20,50)
self.show()
def gif_display(self):
l = QMovieLabel('loading.gif')
l.show()
class QMovieLabel(QLabel):
def __init__(self, fileName):
QLabel.__init__(self)
m = QMovie(fileName)
m.start()
self.setMovie(m)
def setMovie(self, movie):
QLabel.setMovie(self, movie)
s=movie.currentImage().size()
self._movieWidth = s.width()
self._movieHeight = s.height()
def run():
app = QtGui.QApplication(sys.argv)
GUI = MainWindow()
sys.exit(app.exec_())
run()
I would like to display the gif called "loading.gif" after the button is pressed. Nothing appears after pressing the button and I am unsure of what to do to get the gif to properly appear. The gif is the same size as the screen that I created (240x320).
The problem is that QMovieLabel is a local variable within gif_display so it will be deleted when the function finishes running, so the solution is to avoid deleting it. There are 2 options: make it an attribute of the class or make it a child of the window , I will show the second method since I think it is the one you want:
import sys
from PyQt4 import QtCore, QtGui
class MainWindow (QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow,self).__init__(parent)
self.setGeometry(50,50,240,320)
self.home()
def home(self):
but = QtGui.QPushButton("Example", self) # Creates the brew coffee button
but.clicked.connect(self.gif_display)
but.resize(200,80)
but.move(20,50)
self.show()
#QtCore.pyqtSlot()
def gif_display(self):
l = QMovieLabel('loading.gif', self)
l.adjustSize()
l.show()
class QMovieLabel(QtGui.QLabel):
def __init__(self, fileName, parent=None):
super(QMovieLabel, self).__init__(parent)
m = QtGui.QMovie(fileName)
self.setMovie(m)
m.start()
def setMovie(self, movie):
super(QMovieLabel, self).setMovie(movie)
s=movie.currentImage().size()
self._movieWidth = s.width()
self._movieHeight = s.height()
def run():
app = QtGui.QApplication(sys.argv)
GUI = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
run()
I have a widget that ends with pressing OK button. I want that the widget returns a value to the main program (which is in simple example below the obtained value increased by 1). How can I do this?
Also, is there any more elegant way to show the same QWidget with the different title?
MWE:
import sys
from PyQt5 import QtGui, QtCore, QtWidgets
class MainWindow(QtWidgets.QWidget):
def __init__(self,val):
self.val=val
super(MainWindow, self).__init__()
self.initUI()
def initUI(self):
self.End= QtWidgets.QPushButton('OK', self)
self.End.clicked.connect(self.end)
MainLayout = QtWidgets.QVBoxLayout()
MainLayout.addWidget(self.End)
self.setLayout(MainLayout)
self.setWindowTitle(str(self.val))
self.show()
def end(self):
# return self.val+1
self.close()
def main():
app = QtWidgets.QApplication(sys.argv)
for i in range(10):
ex = MainWindow(i)
ex.show()
res = app.exec_()
print(res)
sys.exit()
if __name__ == '__main__':
main()
If you want to use a widget to get some value after some processing, the correct thing is to use QDialog, that prevents any other window from opening if you use exec_():
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Dialog(QtWidgets.QDialog):
def __init__(self, val, parent=None):
super(Dialog, self).__init__(parent)
self.val = val
self.initUI()
def initUI(self):
endButton = QtWidgets.QPushButton('OK')
endButton.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(endButton)
self.setWindowTitle(str(self.val))
#QtCore.pyqtSlot()
def on_clicked(self):
self.val += 1
self.accept()
def main():
app = QtWidgets.QApplication(sys.argv)
for i in range(10):
ex = Dialog(i)
ex.setAttribute(QtCore.Qt.WA_DeleteOnClose)
if ex.exec_() == QtWidgets.QDialog.Accepted:
print(ex.val)
if __name__ == '__main__':
main()
It is unclear what exactly your intention is with this code. If val is supposed to be a counter for the number of MainWindow instances, then you must declare it as a static:
class MainWindow(QtWidgets.QWidget):
val = 0
def __init__(self):
super(MainWindow, self).__init__()
MainWindow.val += 1
self.initUI()
def initUI(self):
# ...
self.setWindowTitle(str(MainWindow.val))
# ...
def main():
# ...
for i in range(10):
ex = MainWindow()
# ...
# ...
There is nothing wrong in calling QWidget::setWindowTitle() so I don't see a problem here.
If you really want to have it as a non-static class member and each MainWindow uses it as some sort of ID, you can easily call the value right after the ex.show():
def main():
app = QtWidgets.QApplication(sys.argv)
for i in range(10):
ex = MainWindow()
ex.show()
print(MainWindow.val)
res = app.exec_()
print(res)
sys.exit()
Just because you close a widget doesn't mean you have destroyed it so calling the values stored inside the object is not an issue.
However it appears you are not familiar what QApplication::exec() is intended for. It runs the main loop of the given application and returns the exit status (you can set it when calling exit() as the parameter passed to that function). If you simply want to get the value of val upon closing a widget you can simply override the closeEvent handler and emit a signal. Create a QObject instance and connect each MainWindow instance's custom close signal to a slot and do with the value whatever you want to.
There has been a small problem with a little project of mine using PyQt5. I tried to add a random QWidget (in this example a QPushbutton) to a custom QWidget. However, I don't understand the behavior of the "setParent" function. When I use it outside of the custom QWidget, the QPushButton is displayed. When I use it in a declared function of the custom Widget, the QPushButton is occluded and I have no chance of displaying it outside of adding a layout (which I don't want). Here an example of the source code:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class customWidget(QWidget):
def __init__(self):
super().__init__()
self.addButton()
def addButton(self):
button = QPushButton('not_showing')
button.setParent(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
button = QPushButton('showing')
button.setParent(w)
button.move(50,50)
w.resize(600,600)
w.move(1000,300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
There is no change, when adding the parent during the initialization of the QPushButton.
When the function addButton exits, the button is removed.
If you want to see the button, try this:
class customWidget(QWidget):
def __init__(self):
super().__init__()
self.addButton()
self.button = None
def addButton(self):
if self.button is None:
self.button = QPushButton('not_showing')
self.button.setParent(self)
You do not have this problem in the main function because this function does not return until the application is stopped.
EDIT: The comment was right, but you also missed some arguments. This will work
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class customWidget(QWidget):
def __init__(self, parent=None):
super(customWidget, self).__init__(parent)
self.addButton()
def addButton(self):
button = QPushButton('not_showing')
button.setParent(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = customWidget()
button = QPushButton('showing')
button.setParent(w)
button.move(50,50)
w.resize(600,600)
w.move(1000,300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
I want use the autoconnection feature. I am using this example:
http://www.eurion.net/python-snippets/snippet/Connecting%20signals%20and%20slots.html
it works, but I want to create my own signals and own slots, the example using built in signals.
for example, here are a custom signal with a custom slot, but don't works:
import sys
from PyQt4 import QtGui, QtCore
class SignalsAndSlots(QtGui.QWidget):
testSignal = QtCore.pyqtSignal(str,name='testSignal')
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setObjectName('testObject')
self.label = QtGui.QLabel(self)
QtCore.QMetaObject.connectSlotsByName(self)
self.emitSignal()
def emitSignal(self):
self.testSignal.emit('message')
#QtCore.pyqtSlot(str,name='on_testObject_testSignal')
def autoSlot(self,msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
Thanks a lot
Ber is right. This what the pyqt documentation says:
QMetaObject.connectSlotsByName searches recursively for all child objects of the given object [...]
Here is a simple example with custom signals :
import sys
from PyQt4 import QtGui, QtCore
class CustomButton(QtGui.QPushButton):
custom_clicked = QtCore.pyqtSignal(str, name='customClicked')
def mousePressEvent(self, event):
self.custom_clicked.emit("Clicked!")
class SignalsAndSlots(QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
layout = QtGui.QHBoxLayout(self)
self.custom_button = CustomButton("Press Me", self)
self.custom_button.setObjectName('customButton')
self.label = QtGui.QLabel("Nothing...", parent=self)
layout.addWidget(self.custom_button)
layout.addWidget(self.label)
QtCore.QMetaObject.connectSlotsByName(self)
#QtCore.pyqtSlot(str, name='on_customButton_customClicked')
def autoSlot(self, msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
But I think you should consider not using the object names. New-style signal connection is way neater. Here is the same application :
import sys
from PyQt4 import QtGui, QtCore
class CustomButton(QtGui.QPushButton):
custom_clicked = QtCore.pyqtSignal(str)
def mousePressEvent(self, event):
self.custom_clicked.emit("Clicked!")
class SignalsAndSlots(QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
layout = QtGui.QHBoxLayout(self)
self.custom_button = CustomButton("Press Me", self)
self.custom_button.setObjectName('customButton')
self.label = QtGui.QLabel("Nothing...", parent=self)
layout.addWidget(self.custom_button)
layout.addWidget(self.label)
self.custom_button.custom_clicked.connect(self.on_clicked)
def on_clicked(self, msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
I investigated a bit into the doc. of QtCore.QMetaObject.connectSlotsByName().
For this, I made an MCVE to collect things not working vs. things working:
#!/usr/bin/python3
import sys
from PyQt5.QtCore import QT_VERSION_STR
from PyQt5.QtCore import QMetaObject, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QWidget
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
# build GUI
qMain = QWidget()
qVBox = QVBoxLayout()
qBtnPreview1 = QPushButton("Preview 1")
qBtnPreview1.setObjectName("preview1")
qVBox.addWidget(qBtnPreview1)
qBtnPreview2 = QPushButton("Preview 2")
qBtnPreview2.setObjectName("preview2")
qVBox.addWidget(qBtnPreview2)
qBtnPreview3 = QPushButton("Preview 3")
qBtnPreview3.setObjectName("preview3")
qVBox.addWidget(qBtnPreview3)
qBtnPreview4 = QPushButton("Preview 4")
qBtnPreview4.setObjectName("preview4")
qVBox.addWidget(qBtnPreview4)
qBtnPreview5 = QPushButton("Preview 5")
qBtnPreview5.setObjectName("preview5")
qVBox.addWidget(qBtnPreview5)
qBtnPreview6 = QPushButton("Preview 6")
qBtnPreview6.setObjectName("preview6")
qVBox.addWidget(qBtnPreview6)
qMain.setLayout(qVBox)
self.setCentralWidget(qMain)
# install signal handlers
qBtnPreview1.clicked.connect(lambda: print("preview1 clicked."))
qBtnPreview2.clicked.connect(lambda: print("preview2 clicked."))
qBtnPreview3.clicked.connect(lambda: print("preview3 clicked."))
qBtnPreview4.clicked.connect(lambda: print("preview4 clicked."))
qBtnPreview5.clicked.connect(lambda: print("preview5 clicked."))
qBtnPreview6.clicked.connect(lambda: print("preview6 clicked."))
QMetaObject.connectSlotsByName(self)
#pyqtSlot()
def preview1(self):
print("MainWindow.preview1() called.")
#pyqtSlot()
def preview2_clicked(self):
print("MainWindow.preview2_clicked() called.")
#pyqtSlot()
def on_preview3(self):
print("MainWindow.on_preview3() called.")
#pyqtSlot()
def on_preview4_clicked(self):
print("MainWindow.on_preview4_clicked() called.")
#pyqtSlot(name='on_preview5_clicked')
def preview5_clicked(self):
print("MainWindow.preview5_clicked() called.")
def on_preview6_clicked(self):
print("MainWindow.on_preview6_clicked() called.")
if __name__ == '__main__':
print("Qt Version: {}".format(QT_VERSION_STR))
app = QApplication(sys.argv)
# build GUI
qWinMain = MainWindow()
qWinMain.show()
# runtime loop
sys.exit(app.exec_())
Output:
$ ./testQMetaObjectConnectSlotsByName.py
Qt Version: 5.9.3
After clicking each of the six buttons once, I got:
preview1 clicked.
preview2 clicked.
preview3 clicked.
preview4 clicked.
MainWindow.on_preview4_clicked() called.
preview5 clicked.
MainWindow.preview5_clicked() called.
preview6 clicked.
MainWindow.on_preview6_clicked() called.
MainWindow.on_preview6_clicked() called.
Observations:
MainWindow.preview1(), MainWindow.preview2_clicked(), MainWindow.on_preview3() were not connected. They don't follow the required convention of QtCore.QMetaObject.connectSlotsByName().
MainWindow.on_preview4_clicked() is connected by name – properly following the required name convention.
MainWindow.preview5_clicked() is connected as well – by giving the required name by #pyqtSlot(name='on_preview5_clicked').
MainWindow.on_preview6_clicked() is connected as well – even without marking it as slot explicitly. (However, it is called twice for any reason which might be undesirable.)
Explicit connections work in any case and appear more robust to me.
Further readings:
QMetaObject::connectSlotsByName() (Qt5 C++ doc.)
Connecting Slots By Name (PyQt5 doc.)
PyQt5.QtCore.pyqtSlot() (PyQt5 doc.).
Actually, this was my answer to another question (SO: How to display two images in each Qlabel PyQt5) until I realized that QtCore.QMetaObject.connectSlotsByName() unlikely plays a role in that question.
So, I moved it here where it may be more appropriate even although the question is a bit aged.
First of all, I'm an experienced C programmer but new to python. I want to create a simple application in python using pyqt. Let's imagine this application it is as simple as when it is run it has to put an icon in the system tray and it has offer an option in its menu to exit the application.
This code works, it shows the menu (I don't connect the exit action and so on to keep it simple)
import sys
from PyQt4 import QtGui
def main():
app = QtGui.QApplication(sys.argv)
trayIcon = QtGui.QSystemTrayIcon(QtGui.QIcon("Bomb.xpm"), app)
menu = QtGui.QMenu()
exitAction = menu.addAction("Exit")
trayIcon.setContextMenu(menu)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
But this doesn't:
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu()
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
def main():
app = QtGui.QApplication(sys.argv)
trayIcon = SystemTrayIcon(QtGui.QIcon("Bomb.xpm"), app)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I probably miss something. There are no errors but in the second case when I click with the right button it doesn't show the menu.
Well, after some debugging I found the problem. The QMenu object it is destroyed after finish __init__ function because it doesn't have a parent. While the parent of a QSystemTrayIcon can be an object for the QMenu it has to be a Qwidget. This code works (see how QMenu gets the same parent as the QSystemTrayIcon which is an QWidget):
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
def main():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon("Bomb.xpm"), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I think I would prefer the following as it doesn't seem to depend upon QT's internal garbage collection decisions.
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.menu = QtGui.QMenu(parent)
exitAction = self.menu.addAction("Exit")
self.setContextMenu(self.menu)
def main():
app = QtGui.QApplication(sys.argv)
style = app.style()
icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_FileIcon))
trayIcon = SystemTrayIcon(icon)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here is the code with Exit action implemented
import sys
from PyQt4 import QtGui, QtCore
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
QtCore.QObject.connect(exitAction,QtCore.SIGNAL('triggered()'), self.exit)
def exit(self):
QtCore.QCoreApplication.exit()
def main():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon("qtLogo.png"), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here is the PyQt5 version (was able to implement the Exit action of demosthenes's answer).
Source for porting from PyQt4 to PyQt5
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5
#PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtWidgets.QMenu(parent)
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
menu.triggered.connect(self.exit)
def exit(self):
QtCore.QCoreApplication.exit()
def main(image):
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon(image), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
on=r''# ADD PATH OF YOUR ICON HERE .png works
main(on)
I couldn't get any of the above answers to work in PyQt5 (the exit in the system tray menu, wouldn't actually exit), but i managed to combine them for a solution that does work. I'm still trying to determine if exitAction should be used further somehow.
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtWidgets.QMenu(parent)
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
menu.triggered.connect(self.exit)
def exit(self):
QtCore.QCoreApplication.exit()
def main(image):
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon(image), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
on='icon.ico'
main(on)
With a pyqt5 connected event:
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtWidgets.QMenu(parent)
exitAction = menu.addAction("Exit")
self.setContextMenu(menu)
menu.triggered.connect(self.exit)
def exit(self):
QtCore.QCoreApplication.exit()
it can be easier
instead:
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
write:
super().__init__(self, icon, parent)
For PySide6:
in main.py:
import sys
try:
from PySide6 import QtWidgets
from PySide6.QtWidgets import QApplication
from PySide6.QtGui import (QIcon)
from PySide6.QtCore import (QSize)
except ImportError as e:
print("no pyside6")
print("use python.exe -m pip install pyside6")
print(str(e))
exit(0)
from silnik.mytray import SystemTrayIcon
if __name__ == "__main__":
app = QApplication(sys.argv)
ico = QIcon()
ico.addFile(u":/img/brylant_64x64.png", QSize(64, 64))
ico.addFile(u":/img/brylant_16x16.png", QSize(16, 16))
ico.addFile(u":/img/brylant_32x32.png", QSize(32, 32))
ico.addFile(u":/img/brylant_48x48.png", QSize(48, 48))
ico.addFile(u":/img/brylant_128x128.png", QSize(128, 128))
app.setWindowIcon(ico)
trayIcon = silnik.mytray.SystemTrayIcon(ico)
app.tray = trayIcon
trayIcon.show()
in folder silnik
create mytray.py:
import sys
from PySide6.QtWidgets import (QSystemTrayIcon, QMenu)
from PySide6.QtCore import (QCoreApplication)
class SystemTrayIcon(QSystemTrayIcon):
def __init__(self, icon):
super().__init__()
self.setIcon(icon)
self.menu = QMenu()
self.exitAction = self.menu.addAction("Wyjście")
self.setContextMenu(self.menu)
self.exitAction.triggered.connect(self.exit)
def exit(self):
QCoreApplication.exit()