2015. 8. 12. 23:47

Signals & Slots 소개

Signals & Slots

시그널과 슬롯

Signals and slots are used for communication between objects. The signals and slots mechanism is a central feature of Qt and probably the part that differs most from the features provided by other frameworks.

시그널과 슬롯은 객체들 간에 통신하는데 사용됩니다. 시그널과 슬롯 메커니즘은 Qt 의 핵심적인 특징이며, 아마도 다른 프레임워크들이 제공하는 대부분의 특징들과도 구분될 것입니다. (고유한 기능)

Introduction

소개

In GUI programming, when we change one widget, we often want another widget to be notified. More generally, we want objects of any kind to be able to communicate with one another. For example, if a user clicks a Close button, we probably want the window's close() function to be called.

GUI 프로그래밍에서, 우리는 하나의 위젯을 수정할 때에 또다른 위젯에게도 알려주길 원할 때가 잇습니다. 더 일반적으로 생각해보면, 우리는 어떤 종류의 객체들이라도 또 다른 객체들간에 통신이 되길 원합니다. 예를 들어 사용자가 Close 버튼을 클릭 했다면, 아마도 우리는 윈도우의 close() 함수가 불리길 원할 것입니다.

Older toolkits achieve this kind of communication using callbacks. A callback is a pointer to a function, so if you want a processing function to notify you about some event you pass a pointer to another function (the callback) to the processing function. The processing function then calls the callback when appropriate. Callbacks have two fundamental flaws: Firstly, they are not type-safe. We can never be certain that the processing function will call the callback with the correct arguments. Secondly, the callback is strongly coupled to the processing function since the processing function must know which callback to call.

오래된 툴킷들은 이런 종류의 통신을 콜백(특정 조건에서 부릴 것을 예약을 한 뒤 그 조건이 되었을 때, 이를 다시 부름)을 사용하여 이뤄내고 있습니다. 콜백은 함수의 포인터이므로, 만약에 당신에게 몇가지 이벤트를 알려주는 처리 함수를 원한다면, 해당 처리 함수에게 또다른 함수의 포인터를 (콜백으로) 전달해야 합니다. 적절할 때 처리 함수가 콜백을 부르게 됩니다. 콜백 함수는 근본적으로 2가지 약점을 가지고 있습니다: 첫째로, 그들은 자료형에-안전하지 않습니다. 우리는 처리 함수가 콜백을 불를 때 정확한 인수를 사용하고 있다는 확신을 할 수 가 없습니다. 두번째로, 콜백은 처리 함수가 어떤 콜백을 부를 건지 반드시 알아야 하므로 강하게 결합되어 있습니다. (다른 함수가 이 콜백을 활용할 재사용하기가 어려움)

Signals and Slots

시그널과 슬롯

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal. Qt's widgets have many pre-defined slots, but it is common practice to subclass widgets and add your own slots so that you can handle the signals that you are interested in.

Qt 에서 우리는 콜백 기술의 대안을 가지고 있습니다 : 우리는 시그널과 슬롯을 사용합니다. 시그널은 특정 이벤트가 발생 했을 때 생성됩니다. Qt 의 위젯들은 다수의 미리정의된 슬롯들을 가지고 있습니다만, 당신이 다룰수 있게 하기 위해 위젯을 상속 받아 확장할 수 있습니다. 슬롯은 특정 시그널에 대응하는 함수로 보시면 됩니다. Qt 의 위젯들은 미리-정의된 다수의 슬롯들을 가지고 있지만, 이를 상속 받은 뒤에 관심 있는 시그널을 다루는 목적으로 자신만의 슬롯을 만들어 추가하는 게 보통 그렇게 하고 있습니다.



The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches. Signals and slots are loosely coupled: A class which emits a signal neither knows nor cares which slots receive the signal. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type. They are completely type safe.

시그널과 슬롯 메커니즘은 자료형에-안전 합니다 : 시그널의 시그너쳐(서명) 은 슬롯의 시그너쳐과 반드시 맞아야 합니다. (사실은 슬롯이 추가적인 인수들을 무시할 수 있기 때문에, 시그널보다 시그너쳐 값이 짧을 수 있습니다.) 시그너쳐 값은 서로 호환이 되므로, 컴파일러는 형이 맞지 않는 것을 우리가 확인하는데 도움을 줍니다. Qt 의 시그널과 슬롯 메커니즘은 만약 당신이 시그널을 슬롯과 연결 했을 때,  시그널의 파라미터를 사용해 슬롯이 적절하게 불려졌는지를 확인 합니다. 시그널과 슬롯은 다수의 어떠한 종류의 인수들도 받을 수 있습니다. 그리고 완전히 자료형에 안전합니다.

All classes that inherit from QObject or one of its subclasses (e.g., QWidget) can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to other objects. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component.

QObject 또는 그것을 상속한 클래스를 이어받은 모든 클래스 (예. QWidget) 들은 시그널과 슬롯을 확보 할 수 있습니다. 시그널은 객체가 자신의 상태를 다른 객체들에게 관심을 가질 수 있게 변경할 때 그 객체에 의해서 발산(전달) 합니다. 그것이 그 객체가 통신하는데, 하는 동작의 전부 입니다. 누가 발산된 그 시그널을 받던지 모르고 또한 관여할 필요도 없습니다. 그것이 진정한 정보 캡슐화이고, 소프트웨어 컴포넌트로써 사용되는 것을 보장합니다.

Slots can be used for receiving signals, but they are also normal member functions. Just as an object does not know if anything receives its signals, a slot does not know if it has any signals connected to it. This ensures that truly independent components can be created with Qt.

슬롯은 시그널을 받는데 사용될 수 있습니다만, 또한 일반 맴버 함수이기도 합니다. 단순히 그 신호를 누군가가 받았는지를 알지 않듯이, 슬롯은 그 신호가 어디서 연결되었는지를 알수 없습니다. (시그널을 받는 슬롯을 기준으로 그 시그널의 발원지를 알 수 없음) 이것은 Qt 가 만들어낸 진정한 독립적인 컴포넌트를 보증합니다.

You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal. (This will emit the second signal immediately whenever the first is emitted.)

단일 슬롯으로 얼마든지 많은 시그널을 연결 할 수 있으며, 반대로 하나의 시그널에서 필요에 따라 다수의 슬롯에 연결될 수 있습니다. 심지어 시그널을 다른 시그널끼리 직접 연결하는 것도 가능합니다. (이는 첫번째 시그널이 발산하면 즉각 연계된 두번쨰 시그널이 발산 할 것입니다.)

Together, signals and slots make up a powerful component programming mechanism.

시그널과 슬롯을 함께하면, 강력한 프로그래밍 메커니즘을 구성할 수 있습니다.

A Small Example

작은 예제

A minimal C++ class declaration might read:

조그만 C++ 클래스는 (예제로) 다음과 같이 읽혀질 수 있습니다:

class Counter
{
public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }
    void setValue(int value);

private:
    int m_value;
};

A small QObject-based class might read:

QObject-기반 클래스는 다음과 같이 읽혀 질 수 있습니다:

#include <QObject>

class Counter : public QObject
{
    Q_OBJECT

public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }

public slots:
    void setValue(int value);

signals:
    void valueChanged(int newValue);

private:
    int m_value;
};

The QObject-based version has the same internal state, and provides public methods to access the state, but in addition it has support for component programming using signals and slots. This class can tell the outside world that its state has changed by emitting a signal, valueChanged(), and it has a slot which other objects can send signals to.

QObject-기반 버전에서는 같은 내부 상태를 가지고 있고, 그 상태를 공개적으로 접근하는 퍼블릿 메소드가 제공되지만, 시그널과 슬롯을 사용한 컴포넌트 프로그래밍 지원을 가지고 있습니다. 이 클래스는 다른 세상(객체들) 에게 상태가 변경이 되면 valueChanged() 라고 불리는 시그널을 발산 한다는 것을 알려주며, 다른 객체들이 시그널을 전달 할 수 있을 때 받는 슬롯을 가지고 있습니다.

All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration. They must also derive (directly or indirectly) from QObject.

시그널과 슬롯을 가진 모든 클래스들은 최상위 선언 부에 Q_OBJECT 라는 언급을 포함 해야합니다. 그들은 (직접 또는 간접적으로) QObject 를 상속 받아야 합니다.

Slots are implemented by the application programmer. Here is a possible implementation of the Counter::setValue() slot:

슬롯은 응용 프로그래머에 의해 구현되어야 합니다. 여기 Counter::setValue() 슬롯의 활용 가능 예가 있습니다.

void Counter::setValue(int value)
{
    if (value != m_value) {
        m_value = value;
        emit valueChanged(value);
    }
}

The emit line emits the signal valueChanged() from the object, with the new value as argument.

emit 줄에서 객체에서 valueChanged() 라는 시그널을 발산하며, 새로 변경되는 값인 value 을 인수로 하고 있습니다.

In the following code snippet, we create two Counter objects and connect the first object'svalueChanged() signal to the second object's setValue() slot using QObject::connect():

    Counter a, b;
    QObject::connect(&a, SIGNAL(valueChanged(int)),
                     &b, SLOT(setValue(int)));

    a.setValue(12);     // a.value() == 12, b.value() == 12
    b.setValue(48);     // a.value() == 12, b.value() == 48

Calling a.setValue(12) makes a emit a valueChanged(12) signal, which b will receive in its setValue() slot, i.e. b.setValue(12) is called. Then b emits the same valueChanged() signal, but since no slot has been connected to b's valueChanged() signal, the signal is ignored.

a.setValue(12) 는 b 의 setValue() 슬롯이 받을 valueChanged(12) 시그널을 발산하게 되므로, a.setValue(12) 가 호출시 b.setValue(12) 가 불려집니다. 그리고 b 는 같은 valueChanged() 시그널을 발산하지만, b 의 valueChanged() 시그널에 연결된 슬롯이 존재하지 않으므로, 해당 시그널은 무시됩니다.

Note that the setValue() function sets the value and emits the signal only if value != m_value. This prevents infinite looping in the case of cyclic connections (e.g., if b.valueChanged() were connected to a.setValue()).

setValue() 함수는 value != m_value 조건에 한에서만 (value) 값을 설정하고 시그널을 전달 하는 것을 주목하시기 바랍니다. 이는 순환 연결의 경우를 대비해 무한 반복 (루프) 를 막을 수 있습니다. (예. b.valueChanged() 가 a.setValue() 에 연결 된 경우)

By default, for every connection you make, a signal is emitted; two signals are emitted for duplicate connections. You can break all of these connections with a single disconnect() call. If you pass the Qt::UniqueConnection type, the connection will only be made if it is not a duplicate. If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false

기본 값으로, 당신이 연결 만들어 시그널이 발생될 때마다; 중복 연결을 위해 두 개의 시그널이 발산됩니다. 당신은 disconnect() 호출을 한번 하여 이들의 모든 연결들을 깰 수 있습니다. 만약 Qt:UniqueConnection 형을 전달한다면, 그 연결은 중복이 아닐 때만 연결이 생성될 것입니다. 만약 이미 중복이 되어 있다면 (정확히 같은 시그널과 슬롯이 같은 객체에 생성), 그 연결은 실패할 것이고 false 값을 반환할 것입니다.

This example illustrates that objects can work together without needing to know any information about each other. To enable this, the objects only need to be connected together, and this can be achieved with some simple QObject::connect() function calls, or with uic's automatic connections feature.

아래 예제는 객체들의 정보를 알 필요 없이 서로 연결하여 동작하는 것을 보여줍니다. 이를 위해, 객체가 알아야 할 것은 단순 QObject:connect() 함수 호출이나 uic (User Interface Compiler) 의 자동 연결 기능들을 활용해 이룰 수 있습니다.

Building the Example

예제를 만들기

The C++ preprocessor changes or removes the signalsslots, and emit keywords so that the compiler is presented with standard C++.

C++ 전처리기는 (작업 내용을) 표준 C++ 로 구성된 컴파일러에서 사용하기 위해 signals, slots, emit 키워드를 삭제하거나 변경합니다.

By running the moc on class definitions that contain signals or slots, a C++ source file is produced which should be compiled and linked with the other object files for the application. If you use qmake, the makefile rules to automatically invoke moc will be added to your project's makefile.

시그널이나 슬롯을 포함하는 클래스 내용에 대해 moc (Meta Object Compiler) 를 실행함으로, 해당 응용 프로그램을 위해 만들어지는 다른 객체 파일들과 결합, 컴파일 되게끔 C++ 소스 파일이 생성됩니다. 만약 qmake 를 사용한다면, 사용자의 프로젝트에 있는 makefile 에 추가가 될 moc 호출 내용이 자동으로 추가될 것입니다.

Signals

시그널들

Signals are emitted by an object when its internal state has changed in some way that might be interesting to the object's client or owner. Only the class that defines a signal and its subclasses can emit the signal.

시그널은 관여되는 객체의 클라이언트나 소유주가 관심 있어하는 방법으로 내부 상태가 변경이 될 때 (설계된) 객체에 의해 발산 됩니다. 시그널을 정의한 클래스와 그의 자식 클래스들 만이 (설계된) 시그널을 발산할 수 있습니다.

When a signal is emitted, the slots connected to it are usually executed immediately, just like a normal function call. When this happens, the signals and slots mechanism is totally independent of any GUI event loop. Execution of the code following the emit statement will occur once all slots have returned. The situation is slightly different when using queued connections; in such a case, the code following the emit keyword will continue immediately, and the slots will be executed later.

일단 시그널이 발산되면, 일반 함수와 비슷하게 그와 연결된 슬롯들이 자동으로 실행됩니다. 이런 일이 일어날 때는 시그널과 슬롯 메커니즘은 GUI 의 어떠한 이벤트 루프와도 완전히 동자적으로 작동합니다. 연결된 모든 슬롯들에서의 동작이 끝나서 반환되면, emit 구문 이후의 코드들이 실행 될 것입니다. 이런 상황은 대기된 연결 (큐드 커낵션) 을 사용할 때는 약간 다릅니다; 이런 경우, emit 이후의 구문들은 바로 이어서 실행되고, 슬롯들은 이후 수행 될 것입니다.

If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.

만약 하나의 시그널에 다수의 슬롯들이 연결되어 있다면, 시그널이 발산될 때 (이를 받은) 슬롯들은 연결된 순서대로 각각 하나씩 실행이 됩니다

Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void).

시그널들은 moc 에 의해 자동으로 생성되며, cpp 파일 내에서는 구현 되어서는 안됩니다. 그들은 반환 자료 형을 가질 수 없습니다. (다시 말해 void 형을 사용합니다.)

A note about arguments: Our experience shows that signals and slots are more reusable if they do not use special types. If QScrollBar::valueChanged() were to use a special type such as the hypothetical QScrollBar::Range, it could only be connected to slots designed specifically for QScrollBar. Connecting different input widgets together would be impossible.

인수에 대해서 참고사항: 우리의 경험으로 시그널과 슬롯은 그들이 특정한 자료형을 사용하지 않는다면, 재사용을 많이 한다는 경향(사례)가 있습니다. 만약 QScrollBar:valueChanged() 가 가상의 QScrollBar::Range 와 같은 특정 자료형에 사용된다면, QScrollBar 자료형을 위해 설계된 슬롯과 연결이 될 수 있습니다. 다른 입력 위젯들을 묶어서 연결하는 것은 불가능 할 것입니다.

Slots

슬롯들

A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them.

하나의 시그널이 연결된 곳으로 발산될 때 슬롯이 호출됩니다. 슬롯들은 일반 C++ 함수들이고 일반 방법으로 호출이 될 수 잇습니다; 그들의 유일한 특징은 시그널들이 이들을 부를 수 있다는 것입니다.

Since slots are normal member functions, they follow the normal C++ rules when called directly. However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection. This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class.

슬롯들은 일반 맴버 함수들이기 때문에, 그들을 직접 부를 때에는 일반 C++ 규칙을 따라야 합니다. 하지만, 슬롯으로써 그들은 시그널-슬롯 연결을 통해 접근 수준과 관계 없이 어떠한 컴포넌트에 의해서도 불려질 수 있습니다. 이것은 임의의 클래스에서 만들어진 인스턴스에서 불려지는 시그널은 관계 없는 클래스의 인스턴스에서 불려지는 프라이빗 (개인) 슬롯으로 전달이 될 수 있게 할 수 있습니다.

You can also define slots to be virtual, which we have found quite useful in practice.

사용자는 실제로 꽤 실용적으로 여겨질 수 있는 가상화(버추얼) 형태로 슬롯을 정의할 수 있습니다.

Compared to callbacks, signals and slots are slightly slower because of the increased flexibility they provide, although the difference for real applications is insignificant. In general, emitting a signal that is connected to some slots, is approximately ten times slower than calling the receivers directly, with non-virtual function calls. This is the overhead required to locate the connection object, to safely iterate over all connections (i.e. checking that subsequent receivers have not been destroyed during the emission), and to marshall any parameters in a generic fashion. While ten non-virtual function calls may sound like a lot, it's much less overhead than any new or delete operation, for example. As soon as you perform a string, vector or list operation that behind the scene requires new or delete, the signals and slots overhead is only responsible for a very small proportion of the complete function call costs.

콜백 함수와 비교해 봤을 때, 실사용시에는 큰 차이가 없지만, 동작의 유연성을 제공하기 위해 시그널과 슬롯이 조금 느립니다. 일반적으로 하나의 시그널이 몇몇 슬롯으로 전달되는 과정이 비-가상화 함수 호출을 사용하여 수신자에게 직접 전달하는 방법보다 10배정도 느립니다. 이는 객체간 모든 연결들을 안전하게 반복 처리 하고(시그널 발산 도중에 연결된 수신자들이 제거 되었는지 아닌지를 확인), 제네릭(일반화) 형태로 어떠한 파라미터들을 다루는데 요구되는 오버헤드(비용) 입니다. 비-가상화 함수를 호출이, 예를 들어 어떠한 new 또는 delete 연산들 보다도 훨씬 덜 비용이 발생하는 걸로 보여질 수 있습니다. string, vector, list 연산 뒤에 new 또는 delete 연산들을 를 요구하듯이 시그널과 슬롯은 함수 호출비용에 각자의 역할 만큼의 작은 부분을 차지할 뿐입니다.

The same is true whenever you do a system call in a slot; or indirectly call more than ten functions. On an i586-500, you can emit around 2,000,000 signals per second connected to one receiver, or around 1,200,000 per second connected to two receivers. The simplicity and flexibility of the signals and slots mechanism is well worth the overhead, which your users won't even notice.

시스템이 직접 또는 간접적으로 슬롯을 호출할 때마다, 10개 이상의 함수들이 호출이 됩니다. i586-500 시스템에서, 하나의 수신자 (슬롯) 에게 초당 약 2,000,000 번을 호출하거나 두 군데의 수신자에게 초당 1,200,000 번 호출합니다. 사용자가 알지 못할 정도의 부하로 시그널과 슬롯의 단순함과 유연함을 제공합니다.

Note that other libraries that define variables called signals or slots may cause compiler warnings and errors when compiled alongside a Qt-based application. To solve this problem, #undef the offending preprocessor symbol.

signals 과 slots 으로 불려지는 변수를 정의한 다른 라이브러리들은 Qt-기반 응용 프로그램과 함께 컴파일 될 때, 컴파일러 경고나 오류를 발생시킬 수 있습니다. 이를 해결하기 위해서 #undef 전처리기 심볼을 사용합니다.

Meta-Object Information

메타-오브젝트 정보

The meta-object compiler (moc) parses the class declaration in a C++ file and generates C++ code that initializes the meta-object. The meta-object contains the names of all the signal and slot members, as well as pointers to these functions.

메타-오브젝트 컴파일러 (moc) 는 C++ 파일에 있는 클래스 선언을 분석하고 메타-오브젝트를 초기화 하는 C++ 코드를 생성합니다. 메타-오브젝트는 시그널과 슬롯 맴버들의 모든 이름을 포함하고, 또한 이들을 가리키는 포인터들도 가지고 있습니다.

The meta-object contains additional information such as the object's class name. You can also check if an object inherits a specific class, for example:

메타-오브젝트는 클래스의 이름과 같은 부가적인 정보들도 포함하고 있습니다. 사용자는 예를 들어 다음과 같이 오브젝트의 특정 클래스를 상속 받고 있는지도 확인할 수 있습니다.

    if (widget->inherits("QAbstractButton")) {
        QAbstractButton *button = static_cast<QAbstractButton *>(widget);
        button->toggle();
    }

The meta-object information is also used by qobject_cast<T>(), which is similar to QObject::inherits() but is less error-prone:

메타-오브젝트 정보는 QObject::inherits() 과 유사하지만 오류가 더 적은 편인 qobject_cast<T>() 를 사용해서 얻을 수도 있습니다.

    if (QAbstractButton *button = qobject_cast<QAbstractButton *>(widget))
        button->toggle();

See Meta-Object System for more information.

메타-오브젝트 시스템에서 더 많은 정보를 확인 바랍니다.

A Real Example

실 사용 예

Here is a simple commented example of a widget.

여기 간단편 언급되는 위젯의 예가 있습니다.

#ifndef LCDNUMBER_H
#define LCDNUMBER_H

#include <QFrame>

class LcdNumber : public QFrame
{
    Q_OBJECT

LcdNumber inherits QObject, which has most of the signal-slot knowledge, via QFrame and QWidget. It is somewhat similar to the built-in QLCDNumber widget.

LcdNumber 는 QFrame 과 QWidget 을 사용하여 시그널-슬롯의 지식을 담은 QObject 을 상속 하고 있습니다. 이는 기본으로-제공되는 (내장-된) QLCDNumber widget 과 무언가 비슷합니다.

The Q_OBJECT macro is expanded by the preprocessor to declare several member functions that are implemented by the moc; if you get compiler errors along the lines of "undefined reference to vtable for LcdNumber", you have probably forgotten to run the moc or to include the moc output in the link command.

Q_OBJECT 매크로는 moc 에 의해 구현되는 몇가지 맴버 함수들을 선언하는 전처리기에 의해 확장됩니다. 만약 "undefined reference to vtable for LcdNumber" (LcdNumber 을 위한 vtable 에 대응되는 참조자가 없음) 이라는 컴파일러 오류를 발견하게 되면, 당신은 moc 실행하기 또는 link 명령문으로 출력되는 moc 결과물을 빼먹은 걸 수 있습니다.

public:
    LcdNumber(QWidget *parent = 0);

It's not obviously relevant to the moc, but if you inherit QWidget you almost certainly want to have the parent argument in your constructor and pass it to the base class's constructor.

이 부분은 아마도 moc 와는 직접 관련이 없지만, 만약 생성자에서 parent 인수를 받기를 뭔해서 QWidget 을 상속 했다면, 당신은 이를 부모 클래스의 생성자에게 전달을 해야 합니다.

Some destructors and member functions are omitted here; the moc ignores member functions.

여기서는 몇몇 파괴자와 맴버 변수들은 생략합니다; moc 는 맴버 함수들을 무시합니다.

signals:
    void overflow();

LcdNumber emits a signal when it is asked to show an impossible value.

LcdNumber 는 표현이 불가능한 값을 보여달라는 요청이 왔을 때 시그널을 발산합니다.

If you don't care about overflow, or you know that overflow cannot occur, you can ignore the overflow() signal, i.e. don't connect it to any slot.

오버플로우 (넘침/overflow) 에 대해서는 신경쓰고 싶지 않거나, 오버플로우가 일어날 수가 없다면, overflow() 시그널을 무시할 수 있습니다. 다시 말해 어떠한 슬롯과 연결 하지 않으면 됩니다.

If on the other hand you want to call two different error functions when the number overflows, simply connect the signal to two different slots. Qt will call both (in the order they were connected).

반면에 숫자가 오버플로우가 되었을 때, 두가지 다른 오류 처리 함수를 호출하고 싶다면, 그 시그널을 두개의 다른 슬롯으로 연결만 하면 됩니다. Qt 는 두개를 (연결한 순서 대로) 호출할 것입니다.

public slots:
    void display(int num);
    void display(double num);
    void display(const QString &str);
    void setHexMode();
    void setDecMode();
    void setOctMode();
    void setBinMode();
    void setSmallDecimalPoint(bool point);
};

#endif

A slot is a receiving function used to get information about state changes in other widgets. LcdNumber uses it, as the code above indicates, to set the displayed number. Since display() is part of the class's interface with the rest of the program, the slot is public.

슬롯은 다른 위젯들에게서 상태 변화가 있을 대 정보를 받는 함수로 사용됩니다. LcdNumber 는 숫자 표시를 설정하기 위해 위에서 언급된 코드를 사용합니다. display() 는 클래스 인터페이스의 남은 부분이므로, 해당 슬롯을 퍼블릭(public)으로 둡니다.

Several of the example programs connect the valueChanged() signal of a QScrollBar to the display() slot, so the LCD number continuously shows the value of the scroll bar.

몇몇 예제 프로그램에서 QScrollBar 의 valueChanged() 시그널이 display() 슬롯으로 연결되고 있습니다. 따라서 지속적으로 LCD 숫자 부분은 스크롤 바의 값을 보여 줍니다.

Note that display() is overloaded; Qt will select the appropriate version when you connect a signal to the slot. With callbacks, you'd have to find five different names and keep track of the types yourself.

display() 함수가 중첩됨(오버로디드) 을 확인 바랍니다; Qt 는 시그널이 슬롯과 연결 될 때 적절한 버전(작성된 함수) 를 선택할 것입니다. 콜백에서는 사용자가 다섯가지의 다른 이름의 함수들을 찾아서 자료형을 계속 추적해야 할 것입니다.

Some irrelevant member functions have been omitted from this example.

이 예제에서는 몇가지 무관한 함수들이 생략 되었습니다.

Signals And Slots With Default Arguments

기본 값을 가진 시그널과 슬롯

The signatures of signals and slots may contain arguments, and the arguments can have default values. Consider QObject::destroyed():

시그널과 슬롯의 시그너쳐(특성) 들은 인수들을 가질 수 있으며, 이들 인수는 기본값을 가질수 있습니다. QObject::destroyed() 를 참조 바랍니다.

void destroyed(QObject* = 0);

When a QObject is deleted, it emits this QObject::destroyed() signal. We want to catch this signal, wherever we might have a dangling reference to the deleted QObject, so we can clean it up. A suitable slot signature might be:

QObject 가 삭제 될때, QObject::destroyed() 시그널을 발산합니다. QObject 가 삭제시 댕글링 참조자 (상위 객체/구조체가 삭제되면서 맴버 변수가 가지고 있는 반환할 Heap 영역을 찾을 수 없게 되어 Memory 누수의 원인이 되는 포인터/참조) 를 가지게 될수 있는 곳 마다, 이 신호를 잡는다면, 우리는 이들을 정리할 수 있습니다. 적절한 슬롯 시그너쳐는 다음이 될 것입니다.

void objectDestroyed(QObject* obj = 0);

To connect the signal to the slot, we use QObject::connect() and the SIGNAL() and SLOT() macros. The rule about whether to include arguments or not in the SIGNAL() and SLOT() macros, if the arguments have default values, is that the signature passed to the SIGNAL() macro must not have fewer arguments than the signature passed to the SLOT() macro.

시그널과 슬롯을 연결하기 위해, 우리는 QObject::connect() 과 SIGNAL() 과 SLOT() 매크로를 사용합니다. 인수를 사용할지 안할지의 여부는 SIGNAL() 과 SLOT() 매크로를 사용할지의 여부로 결정됩니다. 만약 인수에 기본 값을 가진다면, 그 시그너쳐는 SIGNAL() 매크로에 전달이 되어야 하며 SLOT() 매크로에 전달되는 인수의 갯수 보다 적어서는 안 됩니다.

All of these would work:

아래는 동작이 될 것입니다.

connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*)));
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed()));
connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));

But this one won't work:

그러나 이건 안 될 것입니다.

connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed(QObject*)));

...because the slot will be expecting a QObject that the signal will not send. This connection will report a runtime error.

... 왜냐하면, 그 슬롯은 시그널이 보내지 않을 QObject 이 올거라 예상하기 때문입니다. 이런 연결은 (컴파일 당시에는 나오지 않은) 런타임 오류를 발생할 것입니다.

Advanced Signals and Slots Usage

시그널과 슬롯의 고급 사용

For cases where you may require information on the sender of the signal, Qt provides the QObject::sender() function, which returns a pointer to the object that sent the signal.

시그널의 전달자에 대한 정보가 필요할 경우를 대비해, Qt 는 시그널을 전달한 객체를 가리키는 포인터를 반환하는 QObject::sender() 함수를 제공하고 있습니다.

The QSignalMapper class is provided for situations where many signals are connected to the same slot and the slot needs to handle each signal differently.

QSignalMapper 클래스는 다수의 시그널이 하나의 슬롯으로 전달되고 그 슬롯에서 시그널을 다르게 처리할 필요가 있을 때를 위해 제공됩니다.

Suppose you have three push buttons that determine which file you will open: "Tax File", "Accounts File", or "Report File".

예를 들어 "세금 파일"(Tax File) , "계좌 파일"(Accounts File) 또는 "보고서 파일"(Report File) 중 어떤 것을 열지를 결정하는 3개의 버튼을 가지고 있다고 가정합니다.

In order to open the correct file, you use QSignalMapper::setMapping() to map all the clicked() signals to a QSignalMapper object. Then you connect the file's QPushButton::clicked() signal to the QSignalMapper::map() slot.

맞는 파일을 열기 위해서, 당신은 모든 clicked() 시그널들을 QSignalMapper 객체의 위치에 대응하는 QSignalMapper::setMapping() 을 사용합니다. 그리고, 파일의 QPushButton::clicked() 시그널을 QSignalMapper::map() 슬롯에 연결합니다.

    signalMapper = new QSignalMapper(this);
    signalMapper->setMapping(taxFileButton, QString("taxfile.txt"));
    signalMapper->setMapping(accountFileButton, QString("accountsfile.txt"));
    signalMapper->setMapping(reportFileButton, QString("reportfile.txt"));

    connect(taxFileButton, SIGNAL(clicked()),
        signalMapper, SLOT (map()));
    connect(accountFileButton, SIGNAL(clicked()),
        signalMapper, SLOT (map()));
    connect(reportFileButton, SIGNAL(clicked()),
        signalMapper, SLOT (map()));

Then, you connect the mapped() signal to readFile() where a different file will be opened, depending on which push button is pressed.

그리고 mapped() 시그널을 어떤 버튼을 눌렀으냐에 따라 다른 파일이 열리게 끔 하는 readFile() (슬롯) 과 연결 합니다.

    connect(signalMapper, SIGNAL(mapped(QString)),
        this, SLOT(readFile(QString)));

Note: The following code will compile and run, but due to signature normalization, the code will be slower.

참고 : 아래 코드는 컴파일되고 동작은 하겠지만, 시그너쳐 정형화 (일반화) 작업으로 느릴 수 있습니다.

    //slower due to signature normalization at runtime

    connect(signalMapper, SIGNAL(mapped(const QString &)),
        this, SLOT(readFile(const QString &)));

Using Qt with 3rd Party Signals and Slots

서드파티 시그널과 슬롯을 이용한 Qt 사용

It is possible to use Qt with a 3rd party signal/slot mechanism. You can even use both mechanisms in the same project. Just add the following line to your qmake project (.pro) file.

서드파티 (Qt 와 직접 관련 없는 3자) 시그널/슬롯 메커니즘을 이용하여 Qt 를 사용하는게 가능합니다. 심지어 같은 프로젝트에서 동시에 해당 메커니즘을 사용할 수 도 있습니다. 단순히 당신의 qmake 프로젝트 (.pro) 파일에 아래 한줄을 추가하면 됩니다.

CONFIG += no_keywords

It tells Qt not to define the moc keywords signalsslots, and emit, because these names will be used by a 3rd party library, e.g. Boost. Then to continue using Qt signals and slots with the no_keywords flag, simply replace all uses of the Qt moc keywords in your sources with the corresponding Qt macros Q_SIGNALS (or Q_SIGNAL), Q_SLOTS (or Q_SLOT), and Q_EMIT.

이는 예를 들어 Boost 와 같은 서드파티 라이브러리에 의해 이들 이름들이 사용되므로 Qt 에게 moc 키워드인 signals, slots, emit 를 정의하지 말라는 지시를 내립니다. 그리고 Qt 시그널과 슬롯을 no_keywords 플래그를 사용하되 Qt moc 키워드를 다음과 같은 매크로를 사용해서 대응합니다. (Q_SIGNALS 또는 Q_SINGAL, Q_SLOTS 또는 Q_SLOT)

See also Meta-Object System and Qt's Property System.

같이 보기 : 메타-오브젝트 시스템 과 Qt 의 프로퍼티 시스템

© 2015 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners. 

Trackback 0 Comment 0