Bonjour,

Je suis entrain d'essayer de créer une classe template pouvant stocker n'importe quel type de widget par exemple, QPushButton, QComboBox, QCheckBox ...

Mon soucis, c'est que je n'arrive pas à récupérer les signaux que ces widgets peuvent envoyer.
Mais le peux t'on vraiment ???

Pour contourner le fait que le système de signal/slot n'est pas géré lorsqu'on part d'une classe template, j'ai découpé mon code en 2 une première partie qui fait la gestion du template et la seconde en classe de base qui gère les signaux et slots.


La classe template :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
 
#ifndef ELEMENT_H
#define ELEMENT_H
 
#include "SignalSlotBase.h"
 
#include <QWidget>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QVariant>
 
template<typename T>
class Element : public QWidget, public SignalSlotBase
{
public:
    enum class ePosition { TOP, BOTTOM, LEFT, RIGHT };
 
    explicit Element(T info, QString titre = "", QWidget *parent = Q_NULLPTR);
 
    ePosition positionLabel() const { return m_positionLabel; }
    void setPositionLabel(const ePosition &positionLabel);
    T* info() const { return m_info; }
    void setInfo(T info) { m_info = info; }
    QLabel *label() const{ return m_label; }
    void setLabel(QLabel *label){ if( label != Q_NULLPTR) m_label = label; }
 
protected:
    void mouseReleaseEvent(QMouseEvent *event);
 
 
public slots:
 
 
private:
    void initPositionLabel();
 
    T           m_info          ;
    QLabel*     m_label         ;
    ePosition   m_positionLabel ;
 
};
//template<typename T>
//Q_DECLARE_METATYPE(Element<T>::ePosition)
 
 
#endif // ELEMENT_H
 
 
template<typename T>
Element<T>::Element(T info, QString titre, QWidget *parent)
    : QWidget(parent)
    , m_info( info )
    , m_label( new QLabel(titre, this) )
    , m_positionLabel( Element<T>::ePosition::LEFT )
{
    initPositionLabel();
}
 
template<typename T>
void Element<T>::setPositionLabel(const ePosition &position) {
    if( position != m_positionLabel)
        m_positionLabel = position;
 
    initPositionLabel();
}
 
template<typename T>
void Element<T>::initPositionLabel() {
    QBoxLayout* layout;
 
    switch (m_positionLabel) {
    case ePosition::LEFT:
        layout = new QHBoxLayout(this);
        layout->addWidget(m_label, 1, Qt::AlignRight);
        layout->addWidget(m_info, 1);
        break;
    case ePosition::RIGHT:
        layout = new QHBoxLayout(this);
        layout->addWidget(m_info, 1);
        layout->addWidget(m_label, 1, Qt::AlignLeft);
        break;
    case ePosition::TOP:
        layout = new QVBoxLayout(this);
        layout->addWidget(m_label, 1, Qt::AlignCenter);
        layout->addWidget(m_info, 1);
        break;
    case ePosition::BOTTOM:
        layout = new QVBoxLayout(this);
        layout->addWidget(m_info, 1);
        layout->addWidget(m_label, 1, Qt::AlignCenter);
        break;
    default:
        break;
    }
 
    setLayout(layout);
}
 
template<typename T>
void Element<T>::mouseReleaseEvent(QMouseEvent *event) {
    Q_UNUSED(event)
    emit elementClicked(QVariant(this));
}
la classe de base
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
#include <QObject>
 
class SignalSlotBase : public QObject
{
    Q_OBJECT
 
signals:
    void elementClicked(QVariant element);
 
 
public slots:
//    virtual void slotElementClicked(QVariant element) = 0;
 
 
};
Ma classe .h d'appel:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
#include "Utility/Element.h"
 
#include <QMainWindow>
#include <QObject>
#include <QPushButton>
#include <QVariant>
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = Q_NULLPTR);
    ~MainWindow();
 
signals:
 
 
public slots:
    template<typename T>
    void traitementElement(QVariant element);
 
private:
    Element<QPushButton*>* m_test;
 
};
Ma classe cpp d'appel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
#include "MainWindow.h"
 
#include <QDebug>
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
 
    setGeometry(200,150,800,600);
 
    m_test = new Element<QPushButton*>(new QPushButton(this), "Test de QPushButton", parent);
    m_test->label();
    QObject::connect(m_test, &Element<QPushButton*>::elementClicked, this, &MainWindow::traitementElement );
 
    setCentralWidget(m_test);
 
}
 
MainWindow::~MainWindow()
{
    if( m_test != Q_NULLPTR )
        delete m_test;
}
 
template<typename T>
void MainWindow::traitementElement(QVariant element)
{
    qDebug() << "je passe par le slot de test";
    Element<QPushButton*> sender = element.value<Element<QPushButton*>>();
 
    if (sender.info()->isChecked() ) {
        qDebug() << "Le bouton a été clické";
    } else {
        qDebug() << "Le bouton n'a pas été clické";
    }
 
}
Les erreurs remontées :
F:\Projets\TestElementWidget\MainWindow.cpp: In constructor 'MainWindow::MainWindow(QWidget*)':
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: error: no matching function for call to 'MainWindow::connect(Element<QPushButton*>*&, void (SignalSlotBase::*)(QVariant), MainWindow* const, <unresolved overloaded function type>)'
QObject::connect(m_test, &Element<QPushButton*>::elementClicked, this, &MainWindow::traitementElement );
^
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: note: candidates are:
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1:0,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:198:36: note: static QMetaObject::Connection QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:198:36: note: no known conversion for argument 2 from 'void (SignalSlotBase::*)(QVariant)' to 'const char*'
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:201:36: note: static QMetaObject::Connection QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType)
static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:201:36: note: no known conversion for argument 2 from 'void (SignalSlotBase::*)(QVariant)' to 'const QMetaMethod&'
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:479:32: note: QMetaObject::Connection QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:479:32: note: no known conversion for argument 2 from 'void (SignalSlotBase::*)(QVariant)' to 'const char*'
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:215:43: note: static QMetaObject::Connection QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (SignalSlotBase::*)(QVariant); Func2 = void (MainWindow::*)(QVariant); typename QtPrivate::FunctionPointer<Func>::Object = SignalSlotBase; typename QtPrivate::FunctionPointer<Func2>::Object = MainWindow]
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:215:43: note: no known conversion for argument 4 from '<unresolved overloaded function type>' to 'void (MainWindow::*)(QVariant)'
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:247:13: note: template<class Func1, class Func2> static typename QtPrivate::QEnableIf<((int)(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, Func2)
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:247:13: note: template argument deduction/substitution failed:
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: note: candidate expects 3 arguments, 4 provided
QObject::connect(m_test, &Element<QPushButton*>::elementClicked, this, &MainWindow::traitementElement );
^
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1:0,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:256:13: note: template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(((int)(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0) && (! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:256:13: note: template argument deduction/substitution failed:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h: In substitution of 'template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(((int)(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0) && (! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType) [with Func1 = void (SignalSlotBase::*)(QVariant); Func2 = void (MainWindow::*)(QVariant)]':
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: required from here
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:256:13: error: invalid use of incomplete type 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
Makefile.Debug:447: recipe for target 'debug/MainWindow.o' failed
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qnamespace.h:45:0,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qobjectdefs.h:49,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:48,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qglobal.h:1040:45: error: declaration of 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
template <bool B, typename T = void> struct QEnableIf;
^
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1:0,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:287:13: note: template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, Func2)
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:287:13: note: template argument deduction/substitution failed:
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: note: candidate expects 3 arguments, 4 provided
QObject::connect(m_test, &Element<QPushButton*>::elementClicked, this, &MainWindow::traitementElement );
^
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1:0,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:295:13: note: template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
^
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:295:13: note: template argument deduction/substitution failed:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h: In substitution of 'template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType) [with Func1 = void (SignalSlotBase::*)(QVariant); Func2 = void (MainWindow::*)(QVariant)]':
F:\Projets\TestElementWidget\MainWindow.cpp:13:107: required from here
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:295:13: error: invalid use of incomplete type 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qnamespace.h:45:0,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qobjectdefs.h:49,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/qobject.h:48,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtCore/QObject:1,
from F:\Projets\TestElementWidget\../WIN9010/Utility/SignalSlotBase.h:4,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:4,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qglobal.h:1040:45: error: declaration of 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
template <bool B, typename T = void> struct QEnableIf;
^
F:\Projets\TestElementWidget\MainWindow.cpp: In member function 'void MainWindow::traitementElement(QVariant)':
F:\Projets\TestElementWidget\MainWindow.cpp:31:24: error: request for member 'isChecked' in 'sender.Element<T>::info<QPushButton*>()->', which is of pointer type 'QPushButton*' (maybe you meant to use '->' ?)
if (sender.info()->isChecked() ) {
^
mingw32-make[1]: Leaving directory 'D:/Dev/Build/TestElement'
Makefile:34: recipe for target 'debug' failed
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtGui/qevent.h:52:0,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtGui/QMouseEvent:1,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:10,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h: In instantiation of 'void Element<T>::mouseReleaseEvent(QMouseEvent*) [with T = QPushButton*]':
F:\Projets\TestElementWidget\MainWindow.cpp:37:1: required from here
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qvariant.h:466:12: error: 'QVariant::QVariant(void*)' is private
inline QVariant(void *) Q_DECL_EQ_DELETE;
^
In file included from F:\Projets\TestElementWidget\MainWindow.h:4:0,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:103:10: error: within this context
emit elementClicked(QVariant(this));
^
F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:103:10: error: use of deleted function 'QVariant::QVariant(void*)'
In file included from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtGui/qevent.h:52:0,
from ..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include\QtGui/QMouseEvent:1,
from F:\Projets\TestElementWidget\../WIN9010/Utility/Element.h:10,
from F:\Projets\TestElementWidget\MainWindow.h:4,
from F:\Projets\TestElementWidget\MainWindow.cpp:1:
..\..\..\Soft\Qt\Qt5.3.2\5.3\mingw482_32\include/QtCore/qvariant.h:466:12: error: declared here
inline QVariant(void *) Q_DECL_EQ_DELETE;
^
mingw32-make[1]: *** [debug/MainWindow.o] Error 1
mingw32-make: *** [debug] Error 2
11:50:00: Le processus "D:\Soft\Qt\Qt5.3.2\Tools\mingw482_32\bin\mingw32-make.exe" s'est terminé avec le code 2.
Erreur lors de la compilation/déploiement du projet TestElementWidget (kit : Desktop Qt 5.3 MinGW 32bit)
When executing step "Make"
11:50:00: Temps écoulé : 00:07.
Bon, je n'ai pas forcement que des erreurs de signal/slot mais, je ne m'en sors pas et c'est pour cela que je vous sollicite.

Merci d'avance.