2015-08-07 21 views
6

Gönüllü özelliklerin sınırlamalarına giren büyük bir özellik uygulamasına sahibim. @on_traits_changed dekoratörünü kullanırken esas performans sorunları.HasTraits ve PyQt sinyallerini tek bir sınıfta kullanın

from traits.api import * 
from PyQt4 import QtCore 

class Foo(HasTraits, QtCore.QObject): 
    pass 

Hata yığını: yapabileceğim eğer, PyQt4 (veya PyQt5) sinyallerle bu sorunları aşmak için oldukça basit olurdu

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 

Ama bütün dan ben bu mümkün olmadığını biliyorum. Bazı geçici çözüm var mı?

DÜZENLEME: eklenen ithalatı

EDIT2: eklendi

+0

Neden bunun mümkün olmadığını düşünüyorsunuz? Hangi testi yaptın? – ekhumoro

+0

Gönderdiğim kodu test ettim ve bir hata attı. Bu soruna herhangi bir çözüm bulamadım, bu yüzden şimdi burada soruyorum. – HeinzKurt

+1

@HeinzKurt. Neden birden fazla kalıtım kullanmanız gerekiyor? Neden sadece bir "QObject" örneğini oluşturmuyorsunuz ve ona delege edemiyorsunuz? Ayrıca, PyQt5'in son sürümünü kullanarak test ettiniz mi? – ekhumoro

cevap

1

Benim önerilen çözüm Qt unutmak etmektir hata yığını. Saf Python ile yapabileceğiniz özel Qt Sinyalleri ve Yuvaları ile yapabileceğiniz her şey. Burada, Qt'deki Signal ile aynı genel arayüze sahip olan bir sınıf olan PSignal örneği verilmiştir. PSignal örnekleri herhangi bir Python nesnesine QObject alt sınıfının gerekliliği olmadan veya hatta Qt kütüphanesi kullanılmadan bile eklenebilir. Qt İşaretlerinden farklı olarak, sınıf seviyesinde (Qt'nin gerektirdiği gibi) değil, herhangi bir sınıfın __init__ yönteminde örnek değişkenler olarak örneklendirilebilirler. Ayrıca, emit standart bir Python yöntemidir ve herhangi bir sayıda argüman ve anahtar kelimeyi alır, böylece tüm mekanizmayı daha 'Pythonic' yapar. Burada eksik olan tek şey, burada bir gereklilik gibi görünmeyen, İşaretler ve Yuvaların iplik değiştirme davranışlarıdır.

Alt sınıflardaki emit ve _emit yöntemlerini geçersiz kılarak, bu basit gadget'ı Qt Signals ile kolayca yapamayacağınız çeşitli durumlara uyarlayabilirsiniz.

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

Çok düzgün bir kod parçası! Ne yazık ki özel durumumdaki başvurumun tüm örnekleri arasında bir PSignal örneğini paylaşmak çok fazla karmaşıklık katıyor. – HeinzKurt

+1

Teşekkürler, ancak PSignal'ın amacı diğer nesneler arasında "paylaşma" değil, tam olarak bir Qt Sinyali gibi kullanmaktır: istemciyi buna bir sinyal gibi connect() öğesini çağırarak eklersiniz. Sinyalle aynı API'ye sahiptir ve hemen hemen bir değiştirme uygulamasıdır, bu yüzden, Sinyalleri kullanan herhangi bir uygulamanın, daha hafif olduktan sonra PSignals'ı nasıl kullanamadığını göremiyorum. İstediğiniz gibi birinden diğerine geçiş yaparak serbest PSignals ve Sinyalleri karıştırabilir ve eşleştirebilirsiniz.Aylardır kullanıyorum ve birçok yerde PSignal ile Signal'ı değiştirdim ve hiçbir zaman bir sorunum olmadı. –

+0

Açıklama için teşekkürler. Cevabınız kesinlikle konuştuğum halde soruma cevap vermese de, yine de çok güzel bir çözümdür, bu yüzden yine de kabul ettim. – HeinzKurt