Qt 5에서 과부하 신호 및 슬롯 연결
New Signal Slot Syntax에 설명 된 것처럼 Qt 5에서 새로운 신호 / 슬롯 구문 (멤버 함수에 대한 포인터 사용)을 파악하는 데 문제가 있습니다. 나는 이것을 바꾸려고 노력했다.
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
이에:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
그러나 컴파일하려고하면 오류가 발생합니다.
오류 : 호출에 대한 일치 기능이 없습니다.
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
Linux에서 clang 및 gcc를 모두 사용해 보았습니다 -std=c++11
.
내가 뭘 잘못하고 있으며 어떻게 해결할 수 있습니까?
문제는 여기에 있다는 것입니다 이 : 그 이름을 가진 신호가 QSpinBox::valueChanged(int)
와 QSpinBox::valueChanged(QString)
. Qt 5.7부터는 원하는 과부하를 선택하기 위해 제공되는 도우미 기능이 있으므로 작성할 수 있습니다
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
Qt 5.6 및 이전 버전의 경우 올바른 유형으로 캐스팅하여 Qt에게 선택하려는 것을 알려야합니다.
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
나는 알고있다, 그건 추한 . 그러나이 문제를 해결할 방법이 없습니다. 오늘의 교훈은 신호와 슬롯에 과부하를주지 마십시오!
부록 : 캐스트에 대해 정말로 짜증나는 것은
- 하나는 클래스 이름을 두 번 반복합니다
- 일반적으로
void
(신호 의 경우) 반환 값을 지정해야합니다 .
그래서 나는 때때로이 C ++ 11 스 니펫을 사용하는 것을 발견했습니다.
template<typename... Args> struct SELECT {
template<typename C, typename R>
static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
return pmf;
}
};
용법:
connect(spinbox, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged), ...)
나는 개인적으로 그것이 실제로 유용하지 않다는 것을 알았습니다. PMF를 수행하는 작업을 자동 완성 할 때 Creator (또는 IDE)가 올바른 캐스트를 자동으로 삽입하면이 문제가 저절로 사라질 것으로 기대합니다. 그러나 그 동안에 ...
참고 : PMF 기반 연결 구문 에는 C ++ 11이 필요하지 않습니다 !
부록 2 : Qt 5.7의 도우미 기능이 위의 해결 방법을 모델로하여이를 완화하기 위해 추가되었습니다. 주요 도우미는 qOverload
(당신이 또한있어 qConstOverload
하고 qNonConstOverload
).
사용 예 (문서에서) :
struct Foo {
void overloadedFunction();
void overloadedFunction(int, QString);
};
// requires C++14
qOverload<>(&Foo:overloadedFunction)
qOverload<int, QString>(&Foo:overloadedFunction)
// same, with C++11
QOverload<>::of(&Foo:overloadedFunction)
QOverload<int, QString>::of(&Foo:overloadedFunction)
부록 3 : 과부하 신호의 문서를 보면 과부하 문제에 대한 해결책이 문서 자체에 명확하게 나와 있습니다. 예를 들어 https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 은
참고 :이 클래스에서는 Signal valueChanged가 오버로드됩니다. 함수 포인터 구문을 사용하여이 신호에 연결하기 위해 Qt는 다음 예제와 같이 함수 포인터를 얻는 편리한 도우미를 제공합니다.
connect(spinBox, QOverload<const QString &>::of(&QSpinBox::valueChanged), [=](const QString &text){ /* ... */ });
오류 메시지는 다음과 같습니다.
오류 : 호출에 대한 일치 기능이 없습니다.
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
The important part of this is the mention of "unresolved overloaded function type". The compiler doesn't know whether you mean QSpinBox::valueChanged(int)
or QSpinBox::valueChanged(QString)
.
There are a handful of ways to resolve the overload:
Provide a suitable template parameter to
connect()
QObject::connect<void(QSpinBox::*)(int)>(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue);
This forces
connect()
to resolve&QSpinBox::valueChanged
into the overload that takes anint
.If you have unresolved overloads for the slot argument, then you'll need to supply the second template argument to
connect()
. Unfortunately, there's no syntax to ask for the first to be inferred, so you'll need to supply both. That's when the second approach can help:Use a temporary variable of the correct type
void(QSpinBox::*signal)(int) = &QSpinBox::valueChanged; QObject::connect(spinBox, signal, slider, &QSlider::setValue);
The assignment to
signal
will select the desired overload, and now it can be substituted successfully into the template. This works equally well with the 'slot' argument, and I find it less cumbersome in that case.Use a conversion
We can avoid
static_cast
here, as it's simply a coercion rather than removal of the language's protections. I use something like:// Also useful for making the second and // third arguments of ?: operator agree. template<typename T, typename U> T&& coerce(U&& u) { return u; }
This allows us to write
QObject::connect(spinBox, coerce<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, &QSlider::setValue);
Actually, you can just wrap your slot with lambda and this:
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
will be look better. :\
The solutions above work, but I solved this in a slightly different way, using a macro, So just in case here it is:
#define CONNECTCAST(OBJECT,TYPE,FUNC) static_cast<void(OBJECT::*)(TYPE)>(&OBJECT::FUNC)
Add this in your code.
Then, your example:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
Becomes:
QObject::connect(spinBox, CONNECTCAST(QSpinBox, double, valueChanged),
slider, &QSlider::setValue);
참고URL : https://stackoverflow.com/questions/16794695/connecting-overloaded-signals-and-slots-in-qt-5
'Programming' 카테고리의 다른 글
“__attribute __ ((packed, align (4)))”의 의미는 무엇입니까 (0) | 2020.07.21 |
---|---|
XSLT를 사용하여 문자열을 대문자 또는 소문자로 변환하려면 어떻게해야합니까? (0) | 2020.07.21 |
안드로이드에서 열거 형 작업 (0) | 2020.07.20 |
IntelliJ에서 치명적인 오류가 발생 함 : classpath 또는 bootclasspath에서 java.lang 패키지를 찾을 수 없음 (0) | 2020.07.19 |
PHP에서 객체를 인스턴스화하고 같은 줄에서 메소드를 호출 할 수 있습니까? (0) | 2020.07.19 |