I have a huge traits application, which is running into the limitations of enthought traits. Mainly performance issues when using the @on_traits_changed decorator. It would be pretty straightforward to circumvent those issues with PyQt4 (or PyQt5) signals, if i could do:
from traits.api import *
from PyQt4 import QtCore
class Foo(HasTraits, QtCore.QObject):
pass
Error stack:
TypeError Traceback (most recent call last)
<ipython-input-3-ecdfa57492f7> in <module>()
2 from PyQt4 import QtCore
3
----> 4 class Foo(HasTraits, QtCore.QObject):
5 pass
C:\Python27\lib\site-packages\traits\has_traits.pyc in __new__(cls, class_name,
bases, class_dict)
427
428 # Finish building the class using the updated class dictionary:
--> 429 klass = type.__new__( cls, class_name, bases, class_dict )
430
431 # Fix up all self referential traits to refer to this class:
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict)
subclass of the metaclasses of all its bases
But from all i know that is not possible. Is there some workaround?
EDIT: added imports
EDIT2: added error stack
My suggested solution is to forget about Qt. Anything you can do with custom Qt Signals and Slots you can do with pure Python. Here is an example of a class, PSignal, that has exactly the same public interface as Signal in Qt. Instances of PSignal can be added to any Python object without the necessity of subclassing QObject, or even without using the Qt library at all. Unlike Qt Signals they can be instantiated as instance variables inside the __init__
method of any class, rather than at class level (as Qt requires). Also, emit
is a standard Python method and takes any number of arguments and keywords, thus making the whole mechanism more 'Pythonic'. The only thing lacking here is the thread-switching behavior of Signals and Slots, which does not seem to be a requirement here.
By overriding methods emit
and _emit
in subclasses you can adapt this simple gadget to a variety of situations, something you can't do easily with Qt Signals.
DEBUG = False
class PSignal:
def __init__(self):
self.__handlers = []
def connect(self,f):
"""f is a python function."""
if not callable(f):
raise ValueError("Object {!r} is not callable".format(f))
self.__handlers.append(f)
if DEBUG:
print("Connecting",f,self.__handlers)
def disconnect(self,f):
for f1 in self.__handlers:
if f == f1:
self.__handlers.remove(f)
return
def emit(self,*x,**y):
self._emit(*x,**y)
def _emit(self,*x,**y):
for f in self.__handlers:
try:
if DEBUG:
print("emit",f,len(x),x,y)
f(*x,**y)
except Exception:
print("Error in signal",f)
traceback.print_exc()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With