Overriding PyQt signals in child class - python

I'm trying to subclass a generic data class to perform some additional operations on the data computed by the parent. I would like to reuse the dataReady signal in the subclass. The problem is that the signal is still emitted from the parent, and triggers the connected slot(s) before the additional computations have completed.
Is it possible to override/suppress signals emitted from the parent class, or will I simply have to choose a different signal name?
Here's a simplified example of my classes:
class Generic(QtCore.QObject):
dataReady = pyqtSignal()
def __init__(self, parent=None):
super(Generic, self).__init__(parent)
def initData(self):
# Perform computations
...
self.dataReady.emit()
class MoreSpecific(Generic):
dataReady = pyqtSignal()
def __init__(self, parent=None):
super(MoreSpecific, self).__init__(parent)
def initData(self):
super(MoreSpecific, self).initData()
# Further computations
...
self.dataReady.emit()

You can use blockSignals:
def initData(self):
self.blockSignals(True)
super(MoreSpecific, self).initData()
self.blockSignals(False)

I would just restructure the classes a bit.
class Generic(QtCore.QObject):
dataReady = pyqtSignal()
def __init__(self, parent=None):
super(Generic, self).__init__(parent)
def initData(self):
self.computations()
self.dataReady.emit()
def computations(self):
# put your computations in a method
...
class MoreSpecific(Generic):
def __init__(self, parent=None):
super(MoreSpecific, self).__init__(parent)
def computations(self):
super(MoreSpecific, self).computations()
# further computations
Now your initData method, which is supposed to do some calculations and then send a signal, doesn't have to change and your MoreSpecific class will only send the signal once.

Related

How can I make a button be used repeatedly to make text fields appear one by one using PyQt5

This is the current code I am using:
class Opening(QDialog):
def __init__(self):
super(Opening, self).__init__()
loadUi("reminder2.ui", self)
self.startbutton.clicked.connect(self.gotomain)
def gotomain(self):
main = MainWindow()
widget.addWidget(main)
widget.setCurrentIndex(widget.currentIndex()+1)
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("reminder.ui",self)
self.typebutton.clicked.connect(self.med)
self.searchbutton.clicked.connect(self.medd)
self.med2.hide()
self.med3.hide()
self.med4.hide()
self.med5.hide()
self.med6.hide()
self.med7.hide()
self.med8.hide()
self.addbutton.clicked.connect(self.clickAdd)
def med(self):
self.stackedWidget.setCurrentWidget(self.typemed)
def medd(self):
self.stackedWidget.setCurrentWidget(self.searchmed)
def clickAdd(self):
self.med2.show()

Dialog widgets values are not being updated in PyQt

I'm trying to send variables from a dialog back to the Main Window. However, so far I have only been able to pass the default values. My code looks like this:
class OptionsDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Advanced_Options()
self.ui.setupUi(self)
self.ui.buttonbox_options.accepted.connect(self.Get_Data)
def Get_Data(self):
self.value = self.ui.sellingSpin.value()
return self.value
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
"""data about MainWindow"""
def get_input_data(self):
Options = OptionsDialog(self)
self.value = Options.Get_Data()
print(self.value) # this is just an example to see what variable I got
In the dialog I count with many spinboxes. Since the default value is 1, I always get 1. No matter if I had changed it before or not.

QGraphicsItem multiple class inheritance not working [duplicate]

I'm trying to create a set of PySide classes that inherit QWidget, QMainWindow, and QDialog. Also, I would like to inherit another class to overrides a few functions, and also set the layout of the widget.
Example:
Mixin:
class Mixin(object):
def __init__(self, parent, arg):
self.arg = arg
self.parent = parent
# Setup the UI from QDesigner
ui = Ui_widget()
ui.setupUi(self.parent)
def setLayout(self, layout, title):
self.parent.setWindowTitle(title)
self.parent.setLayout(layout)
def doSomething(self):
# Do something awesome.
pass
Widget:
class Widget(Mixin, QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent, arg=arg)
This won't work, but doing this through composition works
Widget (Composition):
class Widget(QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent)
mixin = Mixin(parent=self, arg=arg)
self.setLayout = mixin.setLayout
self.doSomething = mixin.doSomething
I would like to try to have the widget inherit everything instead of having part of it done through composition. Thanks!
Keep class Widget(Mixin, QtGui.Widget):, but add a super call in Mixin.__init__. This should ensure the __init__ method of both Mixin and QWidget are called, and that the Mixin implementation of the setLayout method is found first in the MRO for Widget.
class Mixin(object):
def __init__(self, parent=None, arg=None):
super(Mixin, self).__init__(parent=parent) # This will call QWidget.__init__
self.arg = arg
self.parent = parent
# Setup the UI from QDesigner
ui = Ui_widget()
ui.setupUi(self.parent)
def setLayout(self, layout, title):
self.parent.setWindowTitle(title)
self.parent.setLayout(layout)
def doSomething(self):
# Do something awesome.
pass
class Widget(Mixin, QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent, arg=arg) # Calls Mixin.__init__

QAction not triggered for added QMenu

The issue that I'm facing is when I want to split the functionality of the menubar into multiple files (classes), each of them specific for handling options (File/Help/Edit and so on).
In the Main UI class I have:
class MyFrame(QMainWindow):
def __init__(self):
super().__init__()
self.menu_bar = self.menuBar()
# Create menu
self.add_menu()
def add_menu(self):
help_menu = MenuHelp(self)
def getMenuBar(self):
return self.menu_bar
In the MenuHelp (class):
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__()
self.menu_variable = parrent_widget.getMenuBar().addMenu('Help')
about_action = self.menu_variable.addAction('About')
about_action.setStatusTip('About')
about_action.triggered.connect(self.handle_trigger)
def handle_trigger(self):
print('Im here')
The menubar is correctly shown, but handle_trigger method is never called, any ideas on what am I doing wrong?
You must pass a parent to your QMenu. You must change:
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__()
to:
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__(parrent_widget)

PyQt's Signal / SLOT different classes

can i connect two objects that are in different classes ?
lets say i want button1's clicked() signal to clear line2
class A(QGroupBox):
def __init__(self, parent=None):
super(A, self).__init__(parent)
self.button1= QPushButton('bt1')
self.button1.show()
class B(QGroupBox):
def __init__(self, parent=None):
super(B, self).__init__(parent)
self.line2 = QLineEdit()
self.line2.show()
ob1 = A()
ob2 = B()
Yes, create a method in object B that's tied to a signal in object A. Note how connect is called (this is just an example):
self.connect(self.okButton, QtCore.SIGNAL("clicked()"),
self, QtCore.SLOT("accept()"))
The third argument is the object with the slot, and the fourth the slot name. The sending and receiving objects can definitely be different.

Categories

Resources