2015-08-07 11 views
6

Mam aplikację o ogromnych cechach, która podlega ograniczeniom cech enthought. Głównie problemy z wydajnością podczas korzystania z dekoratora @on_traits_changed. Byłoby całkiem prosta do obejścia tych problemów z PyQt4 (lub PyQt5) sygnałów, jeśli mogę zrobić:Używaj sygnałów HasTraits i PyQt w jednej klasie

from traits.api import * 
from PyQt4 import QtCore 

class Foo(HasTraits, QtCore.QObject): 
    pass 

Błąd stosu:

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 

Ale ze wszystkich wiem, że nie jest to możliwe. Czy jest jakieś obejście?

EDIT: dodano import

EDIT2: dodano błąd stos

+0

Dlaczego uważasz, że to niemożliwe? Jakie testy wykonałeś? – ekhumoro

+0

Przetestowałem napisany przeze mnie kod i wygenerowałem błąd. Nie znalazłem żadnego rozwiązania tego problemu, więc proszę o to teraz. – HeinzKurt

+1

@ HeinzKurt. Dlaczego musisz używać dziedziczenia wielokrotnego? Dlaczego po prostu nie stworzysz wewnętrznej instancji 'QObject' i nie przeniesiesz się do tego? Czy przetestowałeś również najnowszą wersję PyQt5? – ekhumoro

Odpowiedz

1

Moja proponowane rozwiązanie jest zapomnieć o Qt. Wszystko, co możesz zrobić dzięki niestandardowym Qt Signals i Slots, które możesz wykonać za pomocą czystego Pythona. Oto przykład klasy, PSignal, która ma dokładnie taki sam publiczny interfejs jak Signal in Qt. Instancje PSignal można dodać do dowolnego obiektu Python bez konieczności podklasowania QObject, a nawet bez użycia biblioteki Qt. W przeciwieństwie do sygnałów Qt mogą być one tworzone jako zmienne instancji wewnątrz metody dowolnej klasy, a nie na poziomie klasy (jak wymaga Qt). Ponadto, emit jest standardową metodą Pythona i przyjmuje dowolną liczbę argumentów i słów kluczowych, dzięki czemu cały mechanizm jest bardziej "Pythoniczny". Brakuje tu tylko przełączania wątków Signals i Slots, co nie jest tutaj wymogiem.

Przez przesłonięcie metod emit i _emit w podklasach można dostosować ten prosty gadżet do różnych sytuacji, czego nie można z łatwością wykonać za pomocą sygnałów Qt.

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() 
+0

Bardzo zgrabny kawałek kodu! Niestety udostępnienie jednego wystąpienia PSignal między wszystkimi wystąpieniami mojej aplikacji w specjalnym przypadku powoduje zbyt dużą złożoność. – HeinzKurt

+1

Dzięki, ale intencją PSignal nie jest "dzielenie się" między innymi obiektami, ale używanie go dokładnie tak jak Sygnału Qt: dołączasz do niego klientów wywołując connect(), dokładnie tak jak Sygnał. Ma to samo API co Signal i jest praktycznie zamiennikiem, więc nie widzę, aby jakakolwiek aplikacja korzystająca z Signals nie mogła używać PSignals, które są przecież bardziej lekkie. Możesz dowolnie łączyć i dopasowywać PSignals i sygnały, migrując z jednego do drugiego zgodnie z potrzebami.Używam go od miesięcy i zastąpił Signal z PSignal w wielu miejscach i nigdy nie miałem problemu. –

+0

Dzięki za wyjaśnienia. Chociaż twoja odpowiedź ściśle nie odpowiada na moje pytanie, nadal jest to bardzo miłe obejście, więc i tak ją zaakceptowałem. – HeinzKurt

Powiązane problemy