Solved Issue with programming a function template to list the QWidgets in a QDialog with a specific type
-
In the creator function of my Qdialog class, I got that code to work find :
QList<QComboBox *> CombList2; QString QCBName; for(int i=1;; i++ ) { QCBName = "comboBox_" + QString::number(i); if( ui->gridLayoutWidget->findChild<QComboBox *>( QCBName ) != NULL ) { CombList2.append(ui->gridLayoutWidget->findChild<QComboBox *>( QCBName ) ); } else { break; } }
It constructs an ordered Qlist with QComboBox that are in my UI. The name of the QComboBox in the ui are comboBox_1, comboBox_2 ... and the comboBox numbers have been set to match the ordered fashion in which they appear in the UI.
This actually replaces this :
QComboBox *l_TheComboBoxs[NUMofKNOBS_BCR2000] = { ui->comboBox_1, ui->comboBox_2, ui->comboBox_3, ui->comboBox_4, ui->comboBox_5, ui->comboBox_6, ui->comboBox_7, ui->comboBox_8, ui->comboBox_9, ui->comboBox_10, ui->comboBox_11, ui->comboBox_12, ui->comboBox_13, ui->comboBox_14, ui->comboBox_15, ui->comboBox_16, ui->comboBox_17, ui->comboBox_18, ui->comboBox_19, ui->comboBox_20, ui->comboBox_21, ui->comboBox_22, ui->comboBox_23, ui->comboBox_24, ui->comboBox_25, ui->comboBox_26, ui->comboBox_27, ui->comboBox_28, ui->comboBox_29, ui->comboBox_30, ui->comboBox_31, ui->comboBox_32 };
I wanted to build a function that would do the same for deferent widgets QComboBox, QLabel, QDial, QSlidder ..
I tried with this :
template <class T> void fillQWidgetList(QList<T> *QWidgetList, QWidget *gridLayoutWidget, Q_Widget_Type qwidgettype, QRegExp *QWidgetName) { QString QCBName; for(int i=1;; i++ ) { //QCBName = &QWidgetName + QString::number(i); if( qwidgettype == Q_Combo_Box || gridLayoutWidget->findChild<T *>( QCBName ) != NULL ) { QWidgetList->append( gridLayoutWidget->findChild<T *>( QCBName ) ); } else { break; } } }
but compiler issue an error when I call the function for QDialogBox
fillQWidgetList<QComboBox>( &CombList2, ui->gridLayoutWidget, Q_Combo_Box, &Exp);
error : no matching function for call to 'BCR2000::fillQWidgetList(QList<QComboBox*>, QWidget&, Q_Widget_Type, QRegExp*)'
fillQWidgetList<QComboBox>( &CombList2, ui->gridLayoutWidget, Q_Combo_Box, &Exp);
^
I not sure what this means "QWidget*&". Anybody has experience with function template an this kind of issue -
Hi!
@PALYGAP said in Issue with programming a function template to list the QWidgets in a QDialog with a specific type:template <class T>
void fillQWidgetList(QList<T> *QWidgetList, QWidget *gridLayoutWidget, Q_Widget_Type qwidgettype, QRegExp *QWidgetName)First thing: Don't give your own parameters / variables etc names starting with a "q" or "Q". In the context of a Qt based program that's highly misleading. E.g. you have a parameter named QWidgetList. Everyone would think that this is a Qt class (it looks similar to QListWidget).
Second thing: Don't pass arguments by raw pointer unless you have a reason to do so. So, instead of
QList<T> *widgetList
better use a reference:QList<T> &widgetList
.Third thing:
You have a typo:void fillQWidgetList(QList<T>
... has to bevoid fillQWidgetList(QList<T*>
. -
Thanks @Wieland for the advices.
I've cleaned up the code and use references in the function call, and got a version of the code that compiles :
****FUNCTION CALL**** QString widgetName = "comboBox_"; QList<QComboBox *> CombList; fillWidgetList<QComboBox>( &CombList, &ui->gridLayoutWidget, &widgetName); ****FUNCTION**** template <class T> void MIDIControllerGenericDialog::fillWidgetList( QList<T *> *dialogWidgetList, QWidget **gridLayoutWidget, QString *widgetName ) { QString QCBName; for(int i=1;; i++ ) { QCBName = *widgetName + QString::number(i); if( (*gridLayoutWidget)->findChild<T *>( QCBName ) != NULL ) { dialogWidgetList->append( (*gridLayoutWidget)->findChild<T *>( QCBName ) ); } else { break; } } }
but there is a linking issue " error : undefined reference to `void MIDIControllerGenericDialog::fillWidgetList<QComboBox>(QList<QComboBox*>, QWidget**, Widget_Type, QString)'
The calling calling function is in the constructor of my BCR2000 class and the BCR2000 class inherit from the MIDIControllerGenericDialog class where the fillWidgetList is defined :
class MIDIControllerGenericDialog : public QDialog { Q_OBJECT public: explicit MIDIControllerGenericDialog(QWidget *parent = 0); ~MIDIControllerGenericDialog(); void storeGeom(void); template <class T> void fillWidgetList( QList<T *> *dialogWidgetList, QWidget **gridLayoutWidget, Widget_Type widgetType, QString *widgetName );
Putting the function in the BCR2000 class solves the linking issue. Weird and problematic since I want to move functions from the BCR2000 class to the MIDIControllerGenericDialog class.
-
Solved the linking problem. Template function definition has to be in the header file (.h) so that the linker works properly. Seems a fairly common issue : see THIS for the explanation.
Thanks again @Wieland for the help.
-
One thing I am wondering now : wouldn't it be better to use a single function that takes a QList of QObject :
void MIDIControllerGenericDialog::fillWidgetList( QList<QObject *> *dialogWidgetList, QWidget **gridLayoutWidget, QString *widgetName )
since the important function used in the fillWidgetListfunction is QObject::findchild() (and it works on QObjects)
and feed it with casted reference (or pointer ) like so :QString widgetName = "comboBox_"; QList<QComboBox *> CombList; fillWidgetList( (QObject>) &CombList, &ui->gridLayoutWidget, &widgetName);
Not sure if that would work. Anybody tried that ?
-
@PALYGAP Did you try it?
It will not compile because QList<QObject *> is not the same as QList<QComboBox *>. -
No I haven't.
ctually if the both the function call and the function definition uses QObject instead of QComboBox it should compile, shouldn't it ?