문서의 이전 판입니다!
Signals & Slots
레퍼런스: http://qt-project.org/doc/qt-5/signalsandslots.html
콜백 함수보다 더욱 발전된 스타일의 객체 통신 기법. 이벤트와는 약간 다르다. 메시지를 보내 메시지 큐에 쌓인 메시지를 하나씩 처리하는 것이 이벤트 구동 방식이라면, 이것은 시그널을 보냈을 때 즉시즉시 받아 처리하며, 그러므로 거의 callback과 유사하다고 보면 된다.
'시그널'은 의미 그대로 한 객체에서 다른 객체로 어떤 데이터를 전달할 것을 지시하는 신호이고, '슬롯'은 신호를 받은 다른 객체가 어떻게 동작할지를 정의하기 위한 수단이다. 시그널은 moc가 생성하는 C++ 확장인 반면 슬롯은 그냥 일반 함수이다. 다시 말해 어떤 한 객체에서 시그널을 보내면 그 시그널을 받아 처리하기로 한 다른 객체에서는 슬롯으로 정의된 함수를 호출한다는 것.
여기서 시그널과 슬롯을 선언한다고만 해서 무조건 두 객체간에 통신이 이뤄지는 것은 아니다. 둘을 명시적으로 엮어 주어야 시그널의 메시지가 슬롯으로 전달된다. 이 역할을 하는 것이 QObject::connect()
함수이다. 반대의 역할을 하는 함수는 QObject::disconnect()
connect() 함수의 슬롯 인자로는 함수 포인터도 가능하지만, 람다 함수의 형태도 가능하다. 또한 함수 포인터를 입력하는 곳에 각각 SIGNAL()
, SLOT()
매크로를 사용 가능한데 함수 포인터 형태가 아닌 함수 형태로 입력 가능하다. 즉,
connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);
이렇게 함수를 호출할 수도 있지만, 아래와 같이도 가능하다.
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*)));
이 때 SIGNAL의 인자 개수가 SLOT의 인자 개수보다 적어서는 안 된다. 런타임 에러가 날 것이다.
어떤 객체의 시그널을 특정한 객체와 매핑하는 방법이 있다. QSignalMapper
를 이용해 특정 객체의 시그널은 다른 특정 객체의 슬롯으로 매핑 가능하다.
signalMapper = new QSignalMapper(this); signalMapper->setMapping(taxFileButton, QString("taxfile.txt")); signalMapper->setMapping(accountFileButton, QString("accountsfile.txt")); signalMapper->setMapping(reportFileButton, QString("reportfile.txt")); connect(taxFileButton, &QPushButton::clicked, signalMapper, &QSignalMapper::map); connect(accountFileButton, &QPushButton::clicked, signalMapper, &QSignalMapper::map); connect(reportFileButton, &QPushButton::clicked, signalMapper, &QSignalMapper::map);
taxFileButton은 texfile.txt 문자열을, accountFileButton은 accountsfile.txt 문자열을 보내도록 매핑되어 있다. 각 버튼을 클릭할 때 해당 문자열의 파일을 읽으려 한다면 다음처럼 connect를 사용하면 된다.
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(readFile(QString)));