2013-05-30 10 views
6

Tahrip olduktan sonra bazı el ile temizlik yapmak zorunda kalacağım bir widget'ım var (bazı konuları durdur). Ancak bazı sebeplerden dolayı widget'in "yokedilmiş" sinyali ateş etmiyor. Sorunu gösteren bu küçük örneği yaptım.Widget'ın "yok edilmiş" sinyali tetiklenmiyor (PyQT)

import sys 
from PyQt4 import QtGui 

class MyWidget(QtGui.QWidget): 
    def __init__(self, parent): 
     super(MyWidget, self).__init__(parent) 

     def doSomeDestruction(): 
      print('Hello World!') 

     self.destroyed.connect(doSomeDestruction) 


class MyWindow(QtGui.QMainWindow): 
    def __init__(self): 
     super(MyWindow, self).__init__() 

     self.widget = MyWidget(self) 

app = QtGui.QApplication(sys.argv) 
window = MyWindow() 
window.show() 
ret = app.exec_() 
sys.exit(ret) 

"Merhaba Dünya!" Ana pencere kapandığında. Ancak, hiçbir şey yazdırmıyor.

cevap

5

Birkaç denemeden sonra, doSomeDestruction sınıfının dışında bildirirseniz, 'un çalıştığını öğrendim. (bkz. Alttaki)
Ama nedenini bilmiyorum. this yanıtında yazıldığı gibi, bunun nedeni At the point destroyed() is emitted, the widget isn't a QWidget anymore, just a QObject (as destroyed() is emitted from ~QObject).
Bu, işlevin çağrılacağı zaman, sınıfta yazıyorsanız zaten silinmiş demektir. (Qt-faiz posta listesindeki da here bak: Ok , I am sorry for stupid question. The signal is emitted, but the slot is not called for the obvious reason, that is because object is already deleted. )

EDIT: Ben iki yolu gerçekten iş yapmak buldum:

  1. ret = app.exec_() sonra basit del window ekleyin.
  2. Set ana penceresinde (değil widget) içinde WA_DeleteOnClose özellik:
    programın üst kısmında:

    from PyQt4 import QtCore 
    

    değişti __init__ fonksiyonu:

    class MyWindow(QtGui.QMainWindow): 
        def __init__(self): 
         super(MyWindow, self).__init__() 
         self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) 
         self.widget = MyWidget(self) 
    
+0

Büyük olasılıkla Hello World'ü bana yazdıran kodu paylaşabilir misiniz? Kodu talimatlarınıza göre düzenlemeye çalıştım ama hala çalışmıyor. http://pastebin.com/ZCgteHu4 – Scintillo

+0

Bu çok garip. Kodumdaki tek fark, 'doSomeDestruction' iki sınıf arasında tanımlanmış olmasıdır. Ama şimdi bunun sadece bazen çalıştığını öğrendim. Ayrıca bir ['gc.collect'] (http://docs.python.org/3.3/library/gc.html#gc.collect), ancak hiçbir etkisi yoktu. Umarım birileri çalışmasını sağlayacak bir yol bulabiliriz. – TobiMarg

+0

Güncellenmiş yanıtımı görün. Şimdi çalışmalıyım. (doSomeDestruction öğesinin nerede tanımlandığı farketmez) – TobiMarg

0

The python sınıf örneği (veya en azından pyqt < -> qt bağlantısı), destroyed emitte bulunmaz. d. Bu konuda destroyed işleyiciyi bir staticmethod sınıfında yaparak çalışabilirsiniz. Bu şekilde, destroyed sinyali yayıldığında python yöntemi hala geçerli olacaktır. sınıf örneğine özel bilgiye gerek duyulursa

class MyWidget(QWidget): 

    def __init__(self, parent): 
     super(MyWidget, self).__init__(parent) 
     self.destroyed.connect(MyWidget._on_destroyed) 

    @staticmethod 
    def _on_destroyed(): 
     # Do stuff here 
     pass 

Eğer imha yöntemine bu bilgi geçmek functools.partial ve örneği __dict__ kullanabilirsiniz.

from functools import partial 

class MyWidget(QWidget): 

    def __init__(self, parent, arg1, arg2): 
     super(MyWidget, self).__init__(parent) 
     self.arg1 = arg1 
     self.arg2 = arg2 
     self.destroyed.connect(partial(MyWidget._on_destroyed, self.__dict__)) 

    @staticmethod 
    def _on_destroyed(d): 
     print d['arg1'] 
+0

Neden sadece: 'self.destroyed.connect (lambda: baskı (kendinden .__ dict __)) '? Veya OPs orijinal örneğinde olduğu gibi bir kapatma kullanın. (Örneğin çalışmasının tek nedeni, widget'ların hiçbir zaman açıkça silinmemesiydi). – ekhumoro

+0

@ekhumoro Normalde sadece tek bir baskıdan çok daha önemli operasyonlar yapıyorsunuz.lambda'nın tek bir açıklaması var. Normalde, bu nesne yok edildiğinde temizlenmesi gereken bir miktar başka kütüphane ve nesnelerle arayüzleşirsiniz. İlginç, orijinal örneğin bir sınıf örneği yöntemi değil bir kapatma kullandığını bile fark etmedim. Bence bir kapanış da işe yarayacaktı. –

+0

Sanırım şunu sormalıydım: “staticmethod” kullanmanın özel avantajı nedir? Neden bir örnek yönteminin aksine * herhangi bir * sıradan işlevi (bir kapatma olmak zorunda değil) kullanmayın? – ekhumoro