2013-07-04 4 views
1

Я программирую приложение в python, используя twisted и PyQt. проблема, с которой я сталкиваюсь, заключается в том, что когда функция в моем скрученном коде выполняется, мне приходится печатать строку в графическом интерфейсе, я пытаюсь добиться этого, выбирая сигнал (класс Non PyQt). Это, похоже, не работает, я сомневаюсь, что витая петля событий закручивает вещи для PyQt. Поскольку сигнал closeEvent не попадает в ловушку программы.Как испустить сигнал из класса не PyQt?

Вот фрагмент кода:

from PyQt4 import QtGui, QtCore 
import sys 
from twisted.internet.protocol import Factory, Protocol 
from twisted.protocols import amp 
import qt4reactor 

class register_procedure(amp.Command): 
    arguments = [('MAC',amp.String()), 
         ('IP',amp.String()), 
         ('Computer_Name',amp.String()), 
         ('OS',amp.String()) 
         ] 
    response = [('req_status', amp.String()), 
     ('ALIGN_FUNCTION', amp.String()), 
         ('ALIGN_Confirmation', amp.Integer()), 
         ('Callback_offset',amp.Integer()) 
         ] 

class Ui_MainWindow(QtGui.QMainWindow): 

    def __init__(self,reactor, parent=None): 
     super(Ui_MainWindow,self).__init__(parent) 
     self.reactor=reactor 
     self.pf = Factory() 
     self.pf.protocol = Protocol 
     self.reactor.listenTCP(3610, self.pf) # listen on port 1234 

     def setupUi(self,MainWindow): 
     MainWindow.setObjectName(_fromUtf8("MainWindow")) 
     MainWindow.resize(903, 677) 
     self.centralwidget = QtGui.QWidget(MainWindow) 
     sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) 
     sizePolicy.setHorizontalStretch(0) 
     sizePolicy.setVerticalStretch(0) 
     sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) 
     self.centralwidget.setSizePolicy(sizePolicy) 

     self.create_item() 


     self.retranslateUi(MainWindow) 
     self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent) 
     QtCore.QObject.connect(self,QtCore.SIGNAL('registered()'),self.registered) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
     MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) 
     self.pushButton_4.setText(_translate("MainWindow", "Delete System ", None)) 
     self.pushButton.setText(_translate("MainWindow", "Add System", None)) 
     self.label_2.setText(_translate("MainWindow", "SYSTEM STATUS", None)) 
     self.label.setText(_translate("MainWindow", "Monitoring Output", None)) 


    def registered(self):# this function is not being triggered 
     print "check" 
     self.textbrowser.append() 

    def closeEvent(self, event):#neither is this being triggered 
     print "asdf" 
     self.rector.stop() 
     MainWindow.close() 
     event.accept() 


class Protocol(amp.AMP): 
    @register_procedure.responder 
    def register_procedure(self,MAC,IP,Computer_Name,OS): 
     self.bridge_conn=bridge() 
     cursor_device.execute("""select * FROM devices where MAC = ?;""",[(MAC)]) 
     exists_val=cursor_device.fetchone() 
     cursor_device.fetchone() 
     print "register" 
     if not exists_val== "": 
      cursor_device.execute("""update devices set IP= ? , Computer_name= ? , OS = ? where MAC= ?;""",[IP,Computer_Name,OS,MAC]) 
      QtCore.QObject.emit(QtCore.SIGNAL('registered')) # <--emits signal 
      return {'req_status': "done" ,'ALIGN_FUNCTION':'none','ALIGN_Confirmation':0,'Callback_offset':call_offset(1)} 
     else: 
      cursor_device.execute("""INSERT INTO devices(Mac,Ip,Computer_name,Os) values (?,?,?,?);""",[MAC,IP,Computer_Name,OS]) 
      QtCore.QObject.emit(QtCore.SIGNAL('registered'))#<--emits signal 
      return {'req_status': "done" ,'ALIGN_FUNCTION':'main_loop()','ALIGN_Confirmation':0,'Callback_offset':0} 



if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 

    try: 
     import qt4reactor 
    except ImportError: 
     from twisted.internet import qt4reactor 
    qt4reactor.install() 

    from twisted.internet import reactor 
    MainWindow = QtGui.QMainWindow() # <-- Instantiate QMainWindow object. 
    ui = Ui_MainWindow(reactor) 
    ui.setupUi(MainWindow) 
    MainWindow.show() 
    reactor.run() 

ответ

0

Две основные проблемы заключаются в следующем:

1) Что должен знать отправитель и получатель сигналов

Рассмотрим более частый случай в Qt, где у вас может быть несколько кнопок, каждый с сигналом «нажал». Слоты должны знать, какая кнопка была нажата, поэтому улавливание общего сигнала не имеет большого смысла.

и 2) Сигналы должны исходить из QObject.

Сказав это, я не уверен, какова реализация канонической формы. Вот один из способов сделать это, используя идею моста, который у вас был на одной из ваших предыдущих должностей, и специальный класс эмиттеров внутри протокола. Запуск этого кода будет просто напечатать «Working it», когда вызывается protocol.register().

from PyQt4 import QtGui, QtCore 
import sys 

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

    def work(self): 
     print "Working it" 

class Protocol(object): 
    class Emitter(QtCore.QObject): 
     registered = QtCore.pyqtSignal() 
     def __init__(self): 
      super(Protocol.Emitter, self).__init__() 

    def __init__(self): 
     self.emitter = Protocol.Emitter() 

    def register(self): 
     self.emitter.registered.emit() 

class Bridge(QtCore.QObject): 
    def __init__(self, gui, protocol): 
     super(Bridge, self).__init__() 
     self.gui = gui 
     self.protocol = protocol 

    def bridge(self): 
     self.protocol.emitter.registered.connect(self.gui.work) 

app = QtGui.QApplication(sys.argv) 
gui = Ui_MainWindow() 
protocol = Protocol() 
bridge = Bridge(gui, protocol) 
bridge.bridge() 
#protocol.register() #uncomment to see 'Working it' printed to the console 
+0

только что подтвержденный в приведенном выше коде, класс протокола не является классом Pyqt? правильно ? – TheCreator232

+0

Да, это просто общий объект Python –

3

Это то, что я использую в моем одном коде для передачи сигналов от QGraphicsItems (потому что они не являются производными от QObject и не может передавать/принимать сигналы по умолчанию). Это в основном упрощенная версия ответа Radio.

from PyQt4 import QtGui as QG 
from PyQt4 import QtCore as QC 

class SenderObject(QC.QObject): 
    something_happened = QC.pyqtSignal() 

SenderObject крошечное класс, унаследованный от QObject, где вы можете поместить все сигналы, необходимые для излучения. В этом случае определяется только одно.

class SnapROIItem(QG.QGraphicsRectItem): 
    def __init__(self, parent = None): 
     super(SnapROIItem, self).__init__(parent) 
     self.sender = SenderObject() 
    def do_something_and_emit(self): 
     ... 
     self.sender.something_happened.emit() 

В классе не-QObject добавления SenderObject как sender переменной. В любом месте, где используется класс, отличный от QObject, вы можете подключить сигнал от sender ко всему, что вам нужно.

class ROIManager(QC.QObject): 
    def add_snaproi(self, snaproi): 
     snaproi.sender.something_happened.connect(...) 

UPDATE

Полный код этого и должен напечатать "Что-то случилось ...":

from PyQt4 import QtGui as QG 
from PyQt4 import QtCore as QC 

class SenderObject(QC.QObject): 
    something_happened = QC.pyqtSignal() 

class SnapROIItem(QG.QGraphicsItem): 
    def __init__(self, parent = None): 
     super(SnapROIItem, self).__init__(parent) 
     self.sender = SenderObject() 
    def do_something_and_emit(self): 
     self.sender.something_happened.emit() 

class ROIManager(QC.QObject): 
    def __init__(self, parent=None): 
     super(ROIManager,self).__init__(parent) 
    def add_snaproi(self, snaproi): 
     snaproi.sender.something_happened.connect(self.new_roi) 
    def new_roi(self): 
     print 'Something happened in ROI!' 

if __name__=="__main__":) 
    roimanager = ROIManager() 
    snaproi = SnapROIItem() 
    roimanager.add_snaproi(snaproi) 
    snaproi.do_something_and_emit() 

UPDATE 2

Вместо

QtCore.QObject.connect(self,QtCore.SIGNAL('registered()'),self.registered) 

вы должны иметь:

protocol.sender.registered.connect(self.registered) 

Это означает, что вы также должны достать экземпляр в self.pf (кстати, вы импортировать Protocol и затем определить его самостоятельно, а?)

В классе протокола вместо

QtCore.QObject.emit(QtCore.SIGNAL('registered') 

вам нужно, во-первых, создать экземпляр SenderObject в Протоколе.

class Protocol(amp.AMP): 
    def __init__(self, *args, **kw): 
     super(Protocol, self).__init__(*args, **kw) 
     self.sender = SenderObject() 

, а затем, в register_procedure излучают сигнал через sender: self.sender.registered.emit()

За все это работать, вам придется определили SenderObject как:

class SenderObject(QC.QObject): 
    registered = QC.pyqtSignal() 
+0

@adroi: я пробовал этот метод, но он дает мне ошибку «QtCore.pyqtSignal: не имеет атрибута connect()». – TheCreator232

+0

Пожалуйста, попробуйте с полным кодом и посмотрите, есть ли у вас такая же ошибка. – numentar

+0

хорошо, если и вижу мой код, есть две функции, Ui_MainWindow - класс PyQt, где в качестве протокола нет. im пытается установить связь протокола с Ui_mainWindow. – TheCreator232

1

Это старый пост, но это мне помогло. Вот моя версия. Один элемент, который не является QObject, сигнализирующий двум другим не QObject'у, чтобы запускать их методы.

from PyQt4 import QtGui, QtCore 

class Signal(object): 
    class Emitter(QtCore.QObject): 
     registered = QtCore.pyqtSignal() 
     def __init__(self): 
      super(Signal.Emitter, self).__init__() 

    def __init__(self): 
     self.emitter = Signal.Emitter() 

    def register(self): 
     self.emitter.registered.emit() 

    def connect(self, signal, slot): 
     signal.emitter.registered.connect(slot) 

class item(object): 
    def __init__(self, name): 
     self.name = name 
     self.signal = Signal() 

    def something(self): 
     print self.name, ' says something' 

>>> itemA = item('a') 
>>> itemB = item('b') 
>>> itemC = item('c') 
>>> itemA.signal.connect(itemA.signal, itemB.something) 
>>> itemA.signal.connect(itemA.signal, itemC.something) 
>>> itemA.signal.register() 

b says something 
c says something 
Смежные вопросы