QT 신호 및 슬롯 - QT 신호와 홈 - 문맹 퇴치 기사

https://doc.qt.io/qt-5/signalsandslots.html

신호 및 슬롯
신호 슬롯 개체 사이의 통신에 사용된다. 신호 및 슬롯 Qt는기구의 중심 기능 아마도 일부 대부분 다른 프레임 워크에 의해 제공되는 기능이 다르다.

신호 및 슬롯 Qt의 메타 오브젝트 시스템에 의해 가능하게된다.

소개
우리는 하나의 위젯을 변경하면 GUI 프로그래밍에서, 우리는 종종 다른 위젯을 통보하고 싶습니다. 더 일반적으로, 우리는 어떤 종류의 객체가 서로 통신 할 수 있어야합니다. 사용자가 닫기 버튼을 클릭하면, 예를 들어, 우리는 아마 윈도우의 닫기 () 함수를 호출하고 싶습니다.

다른 툴킷 콜백을 사용하여 통신이 종류를 달성한다.
콜백 유 유 처리 기능의 또 다른 기능 (콜백)에 대한 포인터를 전달 어떤 이벤트에 대한 U 통지하는 처리 기능을 할 그렇다면 함수에 대한 포인터이다.
처리 기능은 적절한 경우 콜백을 호출한다.

이 방법을 사용하여 성공적인 프레임 워크가 존재 할 때, 콜백은 직관적이지 수 CNA 및 콜백 인수의 형식 정확성을 보장 문제로 고통을 수 있습니다.

신호 및 슬롯
QT에서, 우리는 콜백 기법에 대한 대안을 가지고 : 우리는 신호와 슬롯을 사용합니다.
특정 이벤트가 발생할 때 신호가 방출된다. Qt의 widges는 미리 정의 된 여러 신호를 가지고
있지만, 우리는 항상 하위 위젯은 그들에게 우리 자신의 신호를 추가 할 수 있습니다.
슬롯은 특정 신호에 응답하여 호출되는 함수이다.

Qt의 위젯은 많은 사전 정의 된 슬롯이 있지만, 서브 클래스 위젯에 대한 일반적인 관행입니다 및 u는 u는에 관심이 있다는 신호를 처리 할 수 ​​있도록 우리 자신의 슬롯을 추가 할 수 있습니다.

0그림 삽입 설명 여기

신호 및 슬롯 형기구 안전 :
시그나의 서명이 수신 슬롯의 서명과 일치한다. 两个签名要匹配
(사실 슬롯은. 여분의 인수를 무시할 수 있기 때문에 수신 신호보다 짧은 서명이있을 수 있습니다)
서명이 호환되기 때문에 함수 포인터 기반 구문을 사용하는 경우, 컴파일러는 우리가 유형 불일치를 감지 할 수 있습니다 . 문자열 기반 SIGNAL과 SLOT 구문은 런타임에 유형 mismathches을 감지합니다.
신호들 및 슬롯들은 느슨하게 결합되어解耦的
신호를 방사하지도 않는다 알고 슬롯이나 슬롯의 신호를 수신 할 염려 클래스.
u는 슬롯에 신호를 연결하면 Qt의 신호와 슬롯기구 보장하지만, 상기 슬롯은 정확한 시간에 신호의 파라미터를 호출 할 것이다. 신호와 슬롯은 모든 유형의 인수를 임의의 수를 취할 수 있습니다. 그들은 완전히 안전 입력된다.

모든 클래스는 QObject를 또는 하위 클래스 중 하나 (예를 들어,는 QWidget) 상속은 신호 및 슬롯들을 포함 할 수있다.
그들은 다른 목적에 흥미있을 수있는 방식으로 자신의 상태를 변경할 때, 신호는 개체가 방출된다.
이 모든 객체가 commnicate을 수행합니다.
아무것도가 방출하는 신호를 수신 여부를 모르거나 상관하지 않는다.
이는 진정한 정보를 캡슐화信息的封装
객체가 소프트웨어 구성 요소로 사용할 수 있고 보장합니다. 组件

슬롯이 신호를 수신하기 위해 사용될 수 있지만, 또한 통상 멤버 함수이다.
아무것도 그 신호를 수신하는 경우 객체가 모르는 것처럼 그것은 어떤 경우, 슬롯은 모르는
연결된 신호를.
이 진정으로 독립적 인 구성 요소가 Qt를 만들 수 있습니다 보장합니다.

U가 단일 슬롯에 원하는 U 많은 신호로 연결할 수 있으며, U가 필요로 한 많은 슬롯으로 연결될 수있다. 다른 신호를 직접 신갈 coonect하는 것도 가능하다. (제이 방출 될 때마다 즉시 제 2 신호를 방출한다).

동시에, 신호는 슬롯 poweful 성분 프로그래밍 메카니즘을 구성한다.

신호의
내부 상태가 obejct의 클라이언트 또는 소유자에게 흥미로운 일이 될 수있는 몇 가지 방법으로 변경되었을 때 신호는 물체에서 방출된다.
신호는 공용 액세스 기능이며, 어디에서 방출 될 수 있지만, 우리는 신호와 그 서브 클래스를 정의하는 클래스를 방출하는 것이 좋습니다.

신호가 방출되는 경우, 접속 슬롯은 대개 일반 함수 호출처럼 바로 실행된다. 이 경우, 신호 및 슬롯 장치는 GUI 이벤트 루프가 완전히 독립적이다.
모든 슬롯이 반환 일단 발생합니다 발광 문 다음의 코드의 실행. 상황은 대기 연결을 사용하는 경우 약간 다릅니다; 이러한의 경우, 발광 키워드를 다음 코드는 즉시 계속하고, 슬롯은 나중에 실행됩니다.

몇몇 슬롯은 하나 개의 신호에 연결되어있는 경우, 슬롯은 신호가 방출 될 때 위해 그들이 연결되어, 하나씩 실행한다.

신호는 자동 MOC (메타 오브젝트 컴파일러)에 의해 생성되고 .cpp 파일로 구현 될 안된다. 그들은 (즉 무효 사용) 반환 유형을 가질 수 없다.

그들은 특별한 종류를 사용하지 않는 경우 신호와 슬롯이 더 재사용하는 것이 우리의 경험 쇼 : 인수에 대한주의 사항. QScrollBar ::의 valueChanged는 ()와 같은 가상 QScrollBar :: 범위로 특별한 형식을 사용한다면, 그것은 단지 QScrollBar을 위해 특별히 설계된 슬롯에 연결 할 수있다. 서로 다른 입력 위젯을 연결하는 것은 불가능하다.

슬롯
연결된 신호가 방출 될 때 슬롯이라한다. 슬롯은 일반 C ++ 기능이며, 일반적으로 호출 할 수 있습니다; 그들의 유일한 특징은 신호가 그들에 연결 될 수 있다는 것이다.

슬롯은 일반 멤버 함수이기 때문에 직접 호출 할 때, 그들은 일반적인 C ++ 규칙을 따릅니다.
그러나, 슬롯, 그들은 신호 슬롯을 통해 연결 관계없이 액세스 레벨의 구성 요소에 의해 호출 될 수있다. 임의의 클래스의 인스턴스로부터 방출 신호가 전용 슬롯을 일으킬 수있는 수단이 관련되지 않은 클래스의 인스턴스를 호출한다.

u는 또한 우리가 실제로 매우 유용하다고하는, 가상으로 슬롯을 정의 할 수 있습니다.

실제 애플리케이션에 차이가 미미하지만 콜백에 비해 신호 슬롯은 약간 느린 때문에 제공하는 증가 된 유연성이다. 일반적으로, 일부 슬롯들에 접속되는 발광 Singal의 10 배 느린 비 가상 함수 호출을 직접 호출 수신기보다 약이다. 이 오버 헤드는 일반적인 방식으로 매개 변수를 모든 연결을 통해 안전하게 반복, 연결 개체를 찾는 데 필요한 (이후 수신기가 방출 동안 파괴되지 않았 음을, 즉 검사), 그리고 마샬이다.

열이 아닌 가상 함수 호출이 많은 것처럼 들릴 수도 있지만, 그것은 예를 들어, 훨씬 적은 오버 헤드를 신규 또는 삭제 작업에 비해입니다.
즉시 u는 문자열, 벡터 또는 장면이 신규 또는 삭제 요구의 뒤에, 신호 및 슬롯은 오버 헤드 전체 함수 호출 비용의 아주 작은 비율에 대해서만 책임이 있다는 목록 작업을 수행한다.

u는 슬롯에 시스템 호출을 할 때마다 마찬가지입니다;

Qt를 기반 응용 프로그램과 함께 컴파일 할 때 신호 또는 슬롯라는 변수를 정의하는 다른 라이브러리 컴파일러 경고 및 오류가 발생할 수 있습니다. 잘못된 처리기 기호 #undef를,이 문제를 해결합니다.

작은 예
최소한의 C ++ 클래스 선언 읽을 수 있습니다

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

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

private:
    int m_value;
};

작은 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;
};

QObject를 기반 버전은 동일한 내부 상태를 가지며, 상기 상태를 액세스하는 공용의 방법을 제공하지만, 추가로 그 신호 슬롯을 사용하여 구성 요소의 프로그래밍을 지원한다. 이 클래스는 그 상태가 신갈,의 valueChanged ()를 발광으로 변경되었음을 외부 말할 수 있고, 다른 물체가 신호를 보낼 수있는 슬롯을 갖는다.

신호 또는 슬롯을 포함하는 모든 클래스는 선언의 상단에 Q_OBJECT를 언급해야합니다. 그들은 또한 QObject를에서 (직접 또는 간접적으로) 유도해야합니다.

슬롯은 애플리케이션 프로그래머에 의해 구현된다. 여기에 가능한 카운터의 구현 ::의 setValue () 슬롯은 다음과 같습니다

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

개의 발광 라인 인수로 새로운 값으로, 물체로부터의 신호의 valueChanged ()을 방출한다.
다음 코드에서, 우리는 두 개의 카운터 객체를 생성하고) (QObject를 :: 연결 사용) (두 번째 객체의 setValue의에 슬롯을 첫 번째 개체의의 valueChanged () 신호를 conect :

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

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

(12) a.setValue를 호출하면, B가의 setValue (슬롯)에서 수신하는 발광의 valueChanged (12) 신호, 즉 수
b.setValue (12)가 호출된다.

어떤 슬롯의 B의 valueChanged () 신호에 연결되지 않았기 때문에 다음 B 방출 동일의 valueChanged () 신호, 그러나, 신호는 무시된다.

SetValue는 () 함수의 값을 설정하고 신호 인 경우에만 vlaue! = m_value 방출합니다.
이 환상의 연결의 경우에는 무한 루프 방지 (b.valueChanged ()가 a.setValue에 접속 된 경우, 예를 ()).

실제 예는
다음의 멤버 함수없이 간단한 Widget 클래스의 헤더의 일례이다.
목적은 u는 자신의 애플리케이션에서 신호와 슬롯을 활용할 수있는 방법을 보여주는 것입니다.

#ifndef LCDNUMBER_H
#define LCDNUMBER_H

#include <QFrame>

class LcdNumber : public QFrame
{
    Q_OBJECT

QFrame과는 QWidget 통해 신호 슬롯 지식의 대부분을 보유 LcdNumber QObject를 상속.
그것은 내장 QLCDNumber 위젯 다소 유사하다.

Q_OBJECT 매크로는 MOC 의해 구현되는 여러 부재 funtions 선언 전처리에 의해 확장되고; MOC上面提到过,自己找找
u는 "LcdNumber에 대한 vtable에 정의되지 않은 참조"의 라인을 따라 컴파일러 오류가 발생할 경우, u는 아마도 MOC를 실행하거나 링크 명령에 MOC 출력을 포함하도록 잊어 버린.
构造函数和信号:

public:
    LcdNumber(QWidget *parent = nullptr);

signals:
    void overflow();

클래스 생성자와 공공 멤버들 후에, 우리는 클래스 신호를 선언합니다. 불가능한 값을 표시하도록 요청 때 LcdNumber 클래스는, 신호, 오버 플로우 ()을 방출한다.

u는 오버 플로우에 대해 걱정하지 않는다, 또는 u가 오버 플로우가 발생할 수 없습니다 알고있는 경우에, u는 즉, 어떤 슬롯에 연결하지 마십시오, 오버 플로우 () 신호를 무시할 수 있습니다.

수가 오버 플로우 때 다른 한편으로는 u는 두 개의 서로 다른 오류 funtions를 호출 할 경우, 단순히 두 개의 서로 다른 슬롯에 신호를 연결합니다. 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

슬롯은 다른 위젯 안전 변화에 대한 정보를 얻기 위해 사용하는 수신 기능이다. LcdNumber 표시된 번호를 설정하기 위해 코드를 나타내는 전술 한 바와 같이이를 사용한다. 표시 ()가 프로그램의 나머지 부분과 클래스의 인터페이스의 일부 슬롯은 public입니다.

notet 디스플레이 ()는 오버 헤드이고; U 슬롯에 신호를 연결하면 Qt는 적절한 버전을 선택한다. 콜백, u는 다섯 가지 이름을 finid 및 유형 자신을 추적해야합니다.

기본 인수와 신호와 슬롯은
신호와 슬롯의 서명은 인수를 포함 할 수 있으며, 인수가 디폴트 값을 가질 수 있습니다. QObject를 고려 :: 파괴 () :

void destroyed(QObject* = nullptr);

QObject를가 삭제 될 때,이 QObject를 :: 파괴 () 신호를 방출한다.
우리는이 QObject를 삭제에 우리가 그것을 정리할 수 있도록 우리가 붙어 다니는 참조가있을 수 있습니다 곳이 신호를 잡으려면.
적절한 슬롯 서명이있을 수 있습니다 :

void objectDestroyed(QObject* obj = nullptr);

슬롯에 신호를 연결하기 위해, 우리는 QObject를 :: 연결 ()를 사용합니다. 연결 신호와 슬롯하는 방법은 여러 가지가 있습니다.
첫번째 이용 함수 포인터이다 :

connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);

슬롯에 신호를 연결하기위한 다른 방법은 : QObject를 연결 () 및 SIGNAL과 SLOT 매크로를 사용하는 것이다.
인수가 기본값이있는 경우 SIGNAL ()와 SLOT () macors에 인수를 포함할지 여부에 관한 규칙은, 신호 () 매크로 반드시에 전달 된 서명이 SLOT에 전달 된 서명보다 적은 인수가없는 것입니다 () 매크로.

이 모든 작동합니다 :

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

하지만이 사람은 작동하지 않습니다 :

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

... 슬롯이 신호를 보낼 것이라는 QObject를 기대되기 때문. 이 연결은 런타임 오류를보고합니다.

이 :: QObject를 연결 ()를 사용할 때 과부하 신호 및 슬롯 인수 컴파일러에 의해 확인되지 않습니다.

이상, 하, 하, 하, 하, 하, 하

게시 된 610 개 원래 기사 · 원 찬양 96 · 전망 (330) 000 +

추천

출처blog.csdn.net/wodownload2/article/details/104292325