PDA

View Full Version : Unable to get signals from QSignalMapper



rawfool
28th March 2014, 12:26
I'm trying to create a custom tab control - A widget with QToolButtons laid in QVBoxLayout and an QStackedLayout placed adjacently. Here my QToolButtons are in contained in QList.
I've written a function called addTab(...) which adds buttons to the vertical layout dynamically and also the widget to be show to stacked layout.

My Question:
Signal mapper object's connect statement is written even before the mapping is done. So is this the reason the button click is not emitting signal ?

// ctabwidget.cpp
#include "ctabwidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
#include <QStackedLayout>
#include <QDebug>
#include <QSignalMapper>

CTabWidget::CTabWidget(QWidget *parent) :
QWidget(parent)
{
mainLayout = new QHBoxLayout;
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
this->setLayout(mainLayout);

buttonLayout = new QVBoxLayout;
buttonLayout->setSpacing(0);

stackLayout = new QStackedLayout;
stackLayout->setContentsMargins(0, 0, 0, 0);
stackLayout->setSpacing(0);

mainLayout->addLayout(buttonLayout);
mainLayout->addLayout(stackLayout);

signalMapper = new QSignalMapper;
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(selectTab(int)));
}

CTabWidget::~CTabWidget()
{
qDeleteAll(tabButtons);
}

// This will be called after the constructor is executed
// Is this the reason why signals aren't emitted on button click ??
void CTabWidget::addTab(const QString & normalIcon, const QString & hoverIcon, const QString & selectIcon, QWidget * tabWidget)
{
tabButtons.append(new CTabButton());
CTabButton * tabButton = tabButtons.last();
tabButton->setFixedSize(196, 54);
tabButton->setCheckable(true);
tabButton->setFocusPolicy(Qt::NoFocus);
tabButton->setStyleSheet("QToolButton { border-image: url(" + normalIcon + "); border: none; border-top-left-radius: 2px; border-bottom-left-radius: 2px; background-color: transparent; }"
"QToolButton:hover { border-image: url(" + hoverIcon + "); border: none; }"
"QToolButton:checked { border-image: url(" + selectIcon + "); border: none; }");
buttonLayout->addWidget(tabButton);
stackLayout->addWidget(tabWidget);
connect(tabButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
int buttonId = tabButtons.size();
signalMapper->setMapping(tabButton, buttonId);
qDebug() << buttonId;
}

void CTabWidget::doneAddingTabs(void)
{
buttonLayout->addStretch();
}

// slot
void CTabWidget::selectTab(int tabId)
{
tabId = tabId - 1;
qDebug() << "Tab Id - " << tabId;
if(tabId < 0)
return;

stackLayout->setCurrentIndex(tabId);
}


// main.cpp
#include "ctabwidget.h"
#include <QApplication>
#include <QLabel>
#include <QList>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QList<QLabel *> labels;

for(int i = 0; i < 4; i++)
{
labels.append(new QLabel(QString::number(i+1)));
}

CTabWidget w;
w.addTab(":/tabIcons/idbak.png", ":/tabIcons/idbak_sel.png", ":/tabIcons/idbak_sel.png", labels.at(0));
w.addTab(":/tabIcons/idrst.png", ":/tabIcons/idrst_sel.png", ":/tabIcons/idrst_sel.png", labels.at(1));
w.addTab(":/tabIcons/idsch.png", ":/tabIcons/idsch_sel.png", ":/tabIcons/idsch_sel.png", labels.at(2));
w.addTab(":/tabIcons/idlog.png", ":/tabIcons/idlog_sel.png", ":/tabIcons/idlog_sel.png", labels.at(3));
w.doneAddingTabs();
w.show();

return a.exec();
}

Thank you.

anda_skoa
30th March 2014, 12:04
Signal mapper object's connect statement is written even before the mapping is done. So is this the reason the button click is not emitting signal ?


No. As long as the connection is set up before the button is clicked that should be fine.

Have you verified that both connect statements worked? I.e. is their return value true?

Why not use a zero based button id and connect the signal mapper directly to the stacked layout's setCurrentIndex() slot?

Cheers,
_

rawfool
1st April 2014, 10:26
Have you verified that both connect statements worked? I.e. is their return value true?Yeah, it's true.


Why not use a zero based button id and connect the signal mapper directly to the stacked layout's setCurrentIndex() slot?Ok. I did that.

connect(signalMapper, SIGNAL(mapped(int)), stackLayout, SLOT(setCurrentIndex(int)));



void CTabWidget::addTab(const QString & normalIcon, const QString & hoverIcon, const QString & selectIcon, QWidget * tabWidget)
{
...
...
int buttonId = tabButtons.size() - 1;
...
...
}

But still I'm not able to switch between pages in the QStackedLayout on button click.

anda_skoa
1st April 2014, 11:19
Do the buttons emit their signal?

I.e. if you connect a slot to the buttons' clicked() signals, does it get invoked? Something like


void CTabWidget::onButtonClicked()
{
qDebug() << Q_FUNC_INFO << QObject::sender();
}

If not, try connecting to the toggled() signal

Cheers,
_

rawfool
1st April 2014, 11:50
Thank you very much for helping me to check for button click signals. The problem was that! My custom button was not emitting the signal due to a small mistake in void mousePressEvent(QMouseEvent * event).


void mousePressEvent(QMouseEvent * event)
{
if(event->button() == Qt::RightButton)
{
return;
}
else if(event->button() == Qt::MiddleButton)
{
return;
}
else // I forgot to add the else case and return the necessary event
{
QToolButton::mousePressEvent(event);
}
}
Thank you.