2012-03-03 3 views
3

내보기와 응용 프로그램 컨트롤러간에 통신하는 데 signals을 사용하고 싶습니다. 나는 다음과 같은 접근법을 가지고있다. 그러나 내가 초보자 인 이래로 그것이 PyQt에 있는지 나는 알지 못한다. 아무도 내게 옳은 길을 가고 있거나 더 나은 해결책이 있다고 말할 수 있습니까?클래스 간의 통신을위한 신호 사용

편집 : 예제를 완전히 작동하는 예제로 변경했습니다.

import sys 
from PyQt4 import QtGui, QtCore 

class View(QtGui.QMainWindow): 

    sigFooChanged = QtCore.pyqtSignal() 
    sigBarChanged = QtCore.pyqtSignal() 

    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 

     central_widget = QtGui.QWidget() 
     central_layout = QtGui.QHBoxLayout() 

     self.__cbFoo = QtGui.QComboBox() 
     self.__cbBar = QtGui.QComboBox() 
     self.__cbFoo.currentIndexChanged[str].connect(lambda x: self.sigFooChanged.emit()) 
     self.__cbBar.currentIndexChanged[str].connect(lambda x: self.sigBarChanged.emit()) 

     central_layout.addWidget(QtGui.QLabel("Foo:")) 
     central_layout.addWidget(self.__cbFoo) 
     central_layout.addWidget(QtGui.QLabel("Bar:")) 
     central_layout.addWidget(self.__cbBar) 

     central_widget.setLayout(central_layout) 
     self.setCentralWidget(central_widget) 

    def setFooModel(self, model): 
     self.__cbFoo.setModel(model) 

    def setBarModel(self, model): 
     self.__cbBar.setModel(model) 

class Controller: 
    def __init__(self, view): 
     self.__view = view 
     # Connect all signals from view with according handlers 
     self.__view.sigFooChanged.connect(self.handleFooChanged) 
     self.__view.sigBarChanged.connect(self.handleBarChanged) 

     self.__fooModel = QtGui.QStringListModel(["Foo1", "Foo2", "Foo3"]) 
     self.__barModel = QtGui.QStringListModel(["Bar1", "Bar2", "Bar3"]) 

     self.__view.setFooModel(self.__fooModel) 
     self.__view.setBarModel(self.__barModel) 

    def handleFooChanged(self): 
     print("Foo Changed") 

    def handleBarChanged(self): 
     print("Bar Changed") 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    view = View() 
    controller = Controller(view) 
    view.show() 
    sys.exit(app.exec_()) 

답변

2

필자는 개인적으로 별도의 제너릭 컨트롤러 클래스를 만들지 않습니다. 내 자신의 환경 설정 일 수도 있지만 실제 컨트롤러 인 QWidget 클래스를 고려하는 경향이 있으며 뷰는 일반적으로 QtDesigner (예 : Ui_Dialog)에서 생성하거나 수동으로 생성하는 GUI 전용 정의입니다. 그리고 관련 QWidget에서 모든 연결을 만듭니다.

이제 코드에 대해이 스 니펫을 일반적인 것으로 생각하는 경우 알 수 없습니다. 의사 코드 복용 방향의 예 ...하지만 오류가 있습니다 ... 정상적으로 게시 작업을 제안합니다. 코드를 사용하여 사람들이 혼란스러워하지 않고 혼란스러워하지 않거나 코드를 작성하는 데 올바른 방향인지 여부를 묻는 것입니다.

QMainWindow 수퍼 클래스에서 __init__()을 호출하는 것을 잊고 있습니다.

메인 윈도우 객체에 show() 명령을 어떻게 전달할 것인지 예를 보지 못했기 때문에 controller.show()가 무슨 일을할지 확실하지 않습니다. 다시 나는 분리 된 클래스를 갖는 것이 왜 필요한지 정말로 알지 못한다. 여기

내가 다시 컨트롤러이기 위하여는 QWidget 클래스 자신을 고려,보다 현실적인 예를 볼 것입니다 방법은 다음과 같습니다

보기

## mainUI.py ## 

from PyQt4 import QtCore, QtGui 

class Ui_MyWidget(object): 

    def setupUi(self, obj): 
     obj.layout = QtGui.QVBoxLayout(obj) 

     obj.cbFoo = QtGui.QComboBox() 
     obj.cbBar = QtGui.QComboBox() 

     obj.layout.addWidget(self.cbFoo) 
     obj.layout.addWidget(self.cbBar) 

비 GUI 라이브러리 모듈 (컨트롤러)

## nonGuiModule.py ## 

class LibModule(object): 

    def handleBarChanged(self, *args): 
     print("Bar Changed: %s" % args) 

컨트롤러 스피 포인트)

## main.py ## 

import sys 
from PyQt4 import QtCore, QtGui 

from mainUI import Ui_MyWidget 
from nonGuiModule import LibModule 


class Main(QtGui.QMainWindow): 

    def __init__(self, parent=None): 
     super(Main, self).__init__(parent) 

     self.resize(640,480) 

     self._lib = LibModule() 

     self.myWidget = MyWidget(self) 
     self.setCentralWidget(self.myWidget) 

     self.myWidget.sigFooChanged.connect(self.handleFooChanged) 
     self.myWidget.sigBarChanged.connect(self._lib.handleBarChanged) 


    def handleFooChanged(self, *args): 
     print("Foo Changed: %s" % args) 


class MyWidget(QtGui.QFrame, Ui_MyWidget): 

    sigFooChanged = QtCore.pyqtSignal(str) 
    sigBarChanged = QtCore.pyqtSignal(str) 

    def __init__(self, parent=None): 
     super(MyWidget, self).__init__(parent) 

     # this is where you set up from the view 
     self.setupUi(self) 

     self.cbFoo.addItems(['Foo1', 'Foo2']) 
     self.cbBar.addItems(['Bar1', 'Bar2']) 

     self.layout.addWidget(self.cbFoo) 
     self.layout.addWidget(self.cbBar) 

     # going to forward private signals to public signals 
     self.cbFoo.currentIndexChanged[str].connect(self.sigFooChanged) 
     self.cbBar.currentIndexChanged[str].connect(self.sigBarChanged) 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv[1:]) 
    view = Main() 
    view.show() 
    sys.exit(app.exec_()) 
+0

음,이 방법은 코드 어쩌면 더 간단하지만 GUI 프로그래밍의 하나 개의 목표는'gui'and'비즈니스 logic'을 분리해야 생각? 어떻게 정상적으로 수행됩니까? – Razer

+0

당신이 gui dependecy와 분리하여 유지하고자하는 non gui 모듈을 가지고 있다면, 그 한 가지 방법은 신호를 그 메소드에 연결합니다. 하지만 Qt에서 모든 이벤트와 신호를 일반 컨트롤러 클래스로 전달하는 코드는 본 적이 없습니다. 복잡한 UI 클래스를 뷰 (레이아웃 및 논리 없음)로 사용할 때 여전히 로직을 분리하고 컨트롤러로 서브 클래 싱하는 QWidget을 고려해야합니다. 그게 내가 지금까지 한 일을 어떻게 보았는지. 수많은 코드 예제를 살펴보십시오. – jdi

+0

방금보기를 고려한 다음 컨트롤러를 표시하는 코드 예제를 업데이트했습니다. 저에게보기는 레이아웃 만 정의하고 비즈니스 로직은 정의하지 않는 별도의 Ui 모듈입니다. 그런 다음 당신은 그것으로부터 물려받은 모든 논리를 더하여 모든 것을 묶어주는 계급을 갖게됩니다. – jdi

관련 문제