PyQt - Track Sender for contextMenu - python

What is the way of getting the Sender of a right-mouse-click on a QLabel()? I want to know on which Widget the right-mouse-click happened. I have code to get the position, but how can i get the Sender?
Getting the Sender i could retrieve the accessibleName()
Here is my current minimal Code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import * #!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# qbtn = QtGui.QPushButton('Quit', self)
label = QLabel("BG Sessions", self)
label.setContextMenuPolicy(Qt.CustomContextMenu)
label.setObjectName("title")
label.customContextMenuRequested.connect(self.clearCache)
label.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def clearCache(self, pos):
print pos
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

if you want to use sender() as suggested by Alexander Lutsenko keep this in mind:
QT-documentation
Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.
if all widgets sending the signal are from the same type,findChild() can be used instead. this is working with my tableViews:
# create signalMapper
self.signalMapper = QtCore.QSignalMapper(self)
self.signalMapper.mapped[str].connect(<slot>)
# connect the widgets with signalMapper
self.<widget>.<yourSignal>.connect(self.signalMapper.map)
self.signalMapper.setMapping(self.<widget>, self.<widget>.objectName()) # sends objectName() to slot
# in slot:
obj = self.findChild(QtWidgets.QLabel,objectname)

You could change the way you connect your signal such that you pass in a reference to the object you are connecting the signal from.
For instance:
my_object.customContextMenuRequested.connect(lambda pos, obj=my_object: self.clearCache(pos, obj))
(you will of course need to modify clearCache() so that it accepts this extra argument)
Note: the obj=my_object line is not redundant, see here for details.

self.sender() inside the slot does this job.

Related

PyQT QListWidget drag and drop does not work

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

Python2 + PyQt5: how to get value of QDoubleSpinBox?

I would like ask how to get the value of QDoubleSpinBox. It confuses me as a new user. Hier is my code:
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QDoubleSpinBox
import sys
class MyApp(QWidget):
def __init__(self, parent=None):
super(MyApp, self).__init__(parent)
dsbox = QDoubleSpinBox(self)
dsbox.setDecimals(1)
dsbox.setValue(100.00)
dsbox.setMinimum(1.00)
dsbox.setMaximum(3500.00)
dsbox.setSingleStep(1.00)
dsbox.setSuffix("mm")
dsbox.valueChanged.connect(self.on_value_changed)
self.show()
def on_value_changed(self):
print "You are now in the sub function."
print self.dsbox.value() #Problem is hier
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyApp()
sys.exit(app.exec_())
The result is:
You are now in the sub function.
Process finished with exit code 1
It means something is wrong with this line: print self.dsbox.value()
I have checked that there is a "value" public function for QDoubleSpinBox Class:
http://doc.qt.io/qt-5/qdoublespinbox.html
So what have I done wrong hier? Thanks for your help!

Signal emitting in Python causes exit code 139

Im trying to make function, which passes 8 values to the progress bars in window app made with QtDesigner.
That is there is a function which actually generates this values. I want to execute it every second in order to get theese values and update progress bars which displays values.
I combined tutorials about making a graphic app with Python and making an app with dynamically updating progess bars:
Python Qt Development: https://www.youtube.com/watch?v=eD91nE8q8Nk
PyQt Progress bar with Thread: https://www.youtube.com/watch?v=ivcxZSHL7jM
The problem is that values are passed correctly, but when it comes to send the signal, the whole app crashes with message:
Process finished with exit code 139 (interrupted by signal 11:
SIGSEGV)
Here is my code:
Module which generates the values (probkowanie.py):
import time
from random import randint
import threading
def getSignals():
time.sleep(1)
signals = (randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), )
return signals
and here is main program code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide.QtCore import *
from PySide.QtGui import *
from PyQt4 import QtCore
import sys
import time
import signalPreview # window library
import probkowanie # values generating library
class MainDialog(QDialog, signalPreview.Ui_mainDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
def updateProgressBars(self, signals):
self.progressBar.setValue(signals[0])
class ThreadClass(QtCore.QThread):
def __init__(self, parent = None):
super(ThreadClass, self).__init__(parent)
def run(self):
while 1:
signals = probkowanie.getSignals()
self.emit(QtCore.SIGNAL('MYO_SIGNALS'), 5) # this line causes crash
print signals # it works correctly
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()
I think it may be caused by mixing libraries. I use QtCore from PySide even though tutorial number 2 is based on PyQt4. My decision is because tutorial number 1 is based on PySide.
I tried changing:
from PySide import QtCore
to
from PyQt4 import QtCore
but then I get another bunch of errors, which I don't know what to do with:
Traceback (most recent call last):
File "/usr/lib/pycharm/helpers/pydev/pydevd.py", line 1580, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "/usr/lib/pycharm/helpers/pydev/pydevd.py", line 964, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/mnt/Grubas/Projekty/Biomed/MYO/myo.py", line 36, in <module>
form = MainDialog()
File "/mnt/Grubas/Projekty/Biomed/MYO/myo.py", line 20, in __init__
self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
TypeError: 'PySide.QtCore.QObject.connect' called with wrong argument types:
PySide.QtCore.QObject.connect(ThreadClass, str, instancemethod)
Supported signatures:
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, callable, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, PySide.QtCore.QMetaMethod, PySide.QtCore.QObject, PySide.QtCore.QMetaMethod, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, PySide.QtCore.QObject, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection) PySide.QtCore.QObject.connect(str, callable, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(str, PySide.QtCore.QObject, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
#EDIT
After providing changes proposed by #ekhumoro script doens't crash, but now I'm getting another error:
QObject::connect: Cannot queue arguments of type 'object' (Make sure
'object' is registered using qRegisterMetaType().)
I tried to look for solution on my own, but I didn't find the exact code which I need. I also tried transforming type of signal from (object) to (tuple) or (list), but it leads to another errors:
TypeError: Unknown type used to call meta function (that may be a
signal): tuple
The most solutions I found are based on PyQT. Is there an easy way to rewrite it for PySide?
Here is an example of solution, which seems to be correct but is made using PyQT:
https://stackoverflow.com/a/2595607/2550466
You are right to think that mixing PySide and PyQt will cause problems, so you will need to remove one of them. However, the crash itself is probably caused by a bug in PySide. There is an SO question with a similar problem shown here:
How to send None with Signals across threads?
So you also need to change the way you define and emit MYO_SIGNALS.
Below is a fixed version of your script (the changed lines are commented):
# from PySide.QtCore import *
# from PySide.QtGui import *
# from PyQt4 import QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import time
import signalPreview # window library
import probkowanie # values generating library
class MainDialog(QDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
# self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
self.connect(self.threadclass, SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
def updateProgressBars(self, signals):
self.progressBar.setValue(signals[0])
# class ThreadClass(QtCore.QThread):
class ThreadClass(QThread):
def __init__(self, parent = None):
super(ThreadClass, self).__init__(parent)
def run(self):
while 1:
signals = probkowanie.getSignals()
# self.emit(QtCore.SIGNAL('MYO_SIGNALS'), 5) # this line causes crash
self.emit(SIGNAL('MYO_SIGNALS'), signals)
print signals # it works correctly
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()

PyQt 4 - global name 'SIGNAL' is not defined

I am trying to connect a push button signal to a callable I created, but for some reason this error keeps on popping up. I've checked to make sure QtCore is imported ... what else am I missing?
Sample code:
from PyQt4 import QtCore
from PyQt4 import QtGui
import sys
class guiFindFiles(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
#Create window
self.setFixedSize(400,180)
self.setWindowTitle("Choose the files to use")
#Create all layouts to be used by window
self.windowLayout = QtGui.QVBoxLayout()
self.fileLayout1 = QtGui.QHBoxLayout()
self.fileLayout2 = QtGui.QHBoxLayout()
self.fileLayout3 = QtGui.QHBoxLayout()
#Create the prompt for user to load in the q script to use
self.qFileTF = QtGui.QLineEdit("Choose the q script file to use")
self.qFileButton = QtGui.QPushButton("Open")
self.qFileButton.setFixedSize(100,27)
self.fileLayout1.addWidget(self.qFileTF)
self.fileLayout1.addWidget(self.qFileButton)
#Connect all the signals and slots
self.connect(self.qFileButton, SIGNAL("pressed()"), self.loadFile)
def loadFile():
fileName = []
selFile = QtGui.QFileDailog.getOpenFileName(self)
print selFile
SIGNAL is inside QtCore, so the line should be:
self.connect(self.qFileButton, QtCore.SIGNAL("pressed()"), self.loadFile)
but you really should use the new style connections:
self.qFileButton.pressed.connect(self.loadFile)
And, unless you meant to differentiate a click from press/release couple, you'd better use clicked signal:
self.qFileButton.clicked.connect(self.loadFile)
SIGNAL is defined inside QtCore, so you must use it within QtCore namespace if you've imported QtCore as a whole. So use:
QtCore.SIGNAL(...)
instead of:
SIGNAL(...)
Or you can import SIGNAL from QtCore explicitly:
from PyQt4.QtCore import SIGNAL

pyside QGraphicsScene: Why it is not working?

I am new to Qt and PySyde. I trying to create a small app to visualize sime line drawings.
In order to do that I try to use QGraphicsView an QGraphicsScene. I made a test to learn how it is working but it isn't. I googled a lot around, I do not understan why it isn't working.
Can somebody explain me the reason and bring me the light?
My code (just want to put a line and a sample text on the scene):
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PySide import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox=QtGui.QHBoxLayout()
leftpanel=QtGui.QFrame()
leftpanel.setGeometry(0,0,300,400)
scene=QtGui.QGraphicsScene()
scene.addText("Hello, world!")
view=QtGui.QGraphicsView(scene,leftpanel)
view.setSceneRect(0,0,300,400)
pen=QtGui.QPen(QtCore.Qt.black,2)
scene.addLine(0,0,200,200,pen)
hbox.addWidget(leftpanel)
rightpanel=QtGui.QFrame()
hbox.addWidget(rightpanel)
szoveg=QtGui.QLabel(rightpanel)
szoveg.setText(u"Hello World!")
self.setLayout(hbox)
self.resize(500,500)
self.setWindowTitle('blabla')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You need to save reference to scene somewhere, e.g. in Example instance:
def initUI(self):
# ...
scene = QtGui.QGraphicsScene()
self.scene = scene # save reference to scene, or it will be destroyed
scene.addText("Hello, world!")
# ...
In another function, you'll be able to add more items to the scene:
def anotherFunction(self):
self.scene.addText("Another Hello, world!")

Categories

Resources