PDA

View Full Version : QSlider & QLabel : setText after SIGNAL from QSlider not working



Faradn
28th November 2011, 20:42
Hi,

As the title states, I have some issues with a QSlider/QLabel connection.

I simply want to show the slider's position in a label as a text and update it every time the slider is changed (and all this in a QMessageBox).

Here's the failing code :



/* In the mainFrame constructor ... */

delete choiceBoxB.layout();
choiceBoxBLayout = new QVBoxLayout;
choiceBoxB.setLayout(choiceBoxBLayout);
sliderPosB = new QLabel("100%");
percentageSliderB = new QSlider(Qt::Horizontal);
percentageSliderB->setMinimum(0);
percentageSliderB->setMaximum(200);
percentageSliderB->setSliderPosition(100);
connect(percentageSliderB,SIGNAL(valueChanged(int) ),this,SLOT(updateSliderBPos(int)));
choiceBoxBLayout->addWidget(sliderPosB);
choiceBoxBLayout->addWidget(percentageSliderB);

/* ... */

void mainFrame::updateSliderBPos(int value){
sliderPosB->setText(QString("%1%").arg(value));
}


Every variable or object or class has been declared in the header file (no compiling issues).

For some reason I don't understand, it worked almost fine once but I couldn't find out what was not working, that wasn't enough.

The purpose of the slider and the label is to allow user to choose a percentage to change the brightness of an image (project in an image editor).

Thanks for your help,

Faradn

UPDATE :

I forgot to mention that the input text is perfectly fine (tested with std::cout) and that the signal works fine too. It is the setText that is not working properly.

ChrisW67
29th November 2011, 01:01
Works just fine here:

#include <QtGui>
#include <QDebug>

class Dialog: public QDialog {
Q_OBJECT

QVBoxLayout *choiceBoxBLayout;
QLabel *sliderPosB;
QSlider *percentageSliderB;

public:
Dialog(QWidget *p = 0): QDialog(p) {

choiceBoxBLayout = new QVBoxLayout;
setLayout(choiceBoxBLayout);

sliderPosB = new QLabel("100%");
percentageSliderB = new QSlider(Qt::Horizontal);
percentageSliderB->setMinimum(0);
percentageSliderB->setMaximum(200);
percentageSliderB->setSliderPosition(100);
connect(percentageSliderB,SIGNAL(valueChanged(int) ),this,SLOT(updateSliderBPos(int)));
choiceBoxBLayout->addWidget(sliderPosB);
choiceBoxBLayout->addWidget(percentageSliderB);
}
public slots:
void updateSliderBPos(int value){ sliderPosB->setText(QString("%1%").arg(value)); }
};

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

Dialog d;
d.show();
return app.exec();
}
#include "main.moc"


Why are you using a QMessageBox and not just your own QDialog subclass?

Faradn
29th November 2011, 10:14
Hi ChrisW67 and thank you for helping me out,

Why does it work with a QDialog and not a QMessageBox, I wonder ...

I used the QMessageBox class because I need the clickedButton() method in some other functions.

Now considering your code and mine, the only thing that changed is the QDialog/QMessageBox thing ... Why couldn't it work in a QMessageBox ?

Again, thanks for your help,


Faradn


UPDATE : whatever it is (QMessageBox or QDialog) the slider position Label remains unupdated.

ChrisW67
29th November 2011, 23:11
The code I posted compiles and works as-is. You can add your buttons to the QDialog and mimic the parts of the QMessageBox interface you need.

By using the QMessageBox and ripping the layout out of it you are leaving dangling sub-widgets, which you then overlay with another layout. It is ugly and the message box icon and message are lost, but still the slider works here:


#include <QtGui>
#include <QDebug>
class Widget: public QWidget {
Q_OBJECT
QMessageBox choiceBoxB;
QVBoxLayout *choiceBoxBLayout;
QLabel *sliderPosB;
QSlider *percentageSliderB;
public:
Widget(QWidget *p = 0):
QWidget(p),
choiceBoxB(QMessageBox::Question, "Deep title of significance", "Insightful question")
{
QTimer::singleShot(1000, this, SLOT(doit()));
}
public slots:
void doit() {
delete choiceBoxB.layout();
choiceBoxBLayout = new QVBoxLayout;
choiceBoxB.setLayout(choiceBoxBLayout);
sliderPosB = new QLabel("100%");
percentageSliderB = new QSlider(Qt::Horizontal);
percentageSliderB->setMinimum(0);
percentageSliderB->setMaximum(200);
percentageSliderB->setSliderPosition(100);
connect(percentageSliderB,SIGNAL(valueChanged(int) ),this,SLOT(updateSliderBPos(int)));
choiceBoxBLayout->addWidget(sliderPosB);
choiceBoxBLayout->addWidget(percentageSliderB);
choiceBoxB.show();
}
void updateSliderBPos(int value){ sliderPosB->setText(QString("%1%").arg(value)); }
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
#include "main.moc"


If you are not getting updated labels then you are probably doing something that blocks the program from returning to the event loop.

Faradn
1st December 2011, 19:53
Hi ChrisW67 and thanks a lot for all the solutions you are providing me.

It is true that using a QMessageBox and then delete its layout is quite ugly. I don't like that either but I need the addButton() and buttonClicked() methods.

Both your options work but I am having trouble finding out what my error is in my code and where it comes from. I'm really sorry, I feel quite bad not being able to use your perfectly suited and simple solutions to my simple issue ...

So please let me paste more code (the whole message box construction and when it is triggered) :


// Brightness parameters setup

delete choiceBoxB.layout();
choiceBoxBLayout = new QVBoxLayout;
choiceBoxB.setLayout(choiceBoxBLayout);
choiceBoxBMessage = new QLabel("Choisissez le pourcentage de luminosite souhaitee :");
sliderPosB = new QLabel("100%");
percentageSliderB = new QSlider(Qt::Horizontal);
bOkB = new QPushButton("&Ok");
bCancelB = new QPushButton("&Annuler");
percentageSliderB->setMinimum(0);
percentageSliderB->setMaximum(200);
percentageSliderB->setSliderPosition(100);
connect(percentageSliderB,SIGNAL(valueChanged(int) ),this,SLOT(updateSliderBPos(int)));
choiceBoxBLayout->addWidget(choiceBoxBMessage);
choiceBoxBLayout->addWidget(sliderPosB);
choiceBoxB.addButton(bOkB,QMessageBox::AcceptRole) ;
choiceBoxB.addButton(bCancelB,QMessageBox::RejectR ole);
choiceBoxBLayout->addWidget(percentageSliderB);
choiceBoxBLayout->addWidget(bOkB);
choiceBoxBLayout->addWidget(bCancelB);

and the slot that triggers choiceBoxB's execution (connected to a menu option, it works) :


void mainFrame::changeBrightness() {
if(currentImage.getBuffer() != NULL){
choiceBoxB.exec();
if(choiceBoxB.clickedButton()->text() == bOkB->text()){ // I know, this is even uglier ...

/* I am using quick and ugly solutions concerning the GUI because those are details in my project which is a duplicata of a GTK & C project. */

currentImage.changeBrightness(percentageSliderB->value());
displayImage(currentImage);
}
}
}

I have also discovered an interesting thing.

As you can see now my message box elements also contain a message.

I tried modifying the updateSliderBPos function from


void updateSliderBPos(int value) {
sliderPosB->setText(QString("%1%").arg(value));
}

to :


void updateSliderBPos(int value) {
sliderPosB->setText(QString("%1%").arg(value));
choiceBoxBMessage->setText(QString("%1%").arg(value));
}

The choiceBoxBMessage is updated with the correct position of the slider (plus the percentage symbol) whereas the sliderPosB isn't.

The sliderPosB label's purpose is only to show the slider position in that box. I do not see what differences there could be with the choiceBoxBMessage label ...


Again thanks for your help,

Faradn