QSlider setvalue() not updating slider position in GUI - qt

I have multiple slider widget in my main window, added using QT creater, I am trying to set the slider position in my program, the slider value is set based on color (HSV) picked from a color picker dialog.
I have a color button, upon clicking color button,it invokes the color picker dialogue, after picking the color it calls updateSlider() to set slider position.
void MainWindow::on_Color_clicked()
{
QColor color = QColorDialog::getColor(Qt::white);
int h,s,v;
color.getHsv(&h,&s,&v);
h = h/2;
ccfg.mHueL = h;
ccfg.mHueH = h;
ccfg.mSatL = s;
ccfg.mSatH = s;
ccfg.mValueL = v;
ccfg.mValueH = v;
updateSlider();
}
void MainWindow::updateSlider()
{
ui->hueL->setValue(ccfg.mHueL);
ui->hueH->setValue(ccfg.mHueH);
ui->satL->setValue(ccfg.mSatL);
ui->satH->setValue(ccfg.mSatH);
ui->valL->setValue(ccfg.mValueL);
ui->valH->setValue(ccfg.mValueH);
ui->thrED->setValue(ccfg.mThrEd);
ui->thrCD->setValue(ccfg.mThrCd);
ui->minR->setValue(ccfg.mMinR);
}
After selecting the color only first sliders is getting updated, why the other sliders positions are not updated?
If I select the same color again the second slider position in UI gets updated to new value and if I select 9 times all sliders position gets set appropriately .
I tried calling repaint() of main window and widget, and also tried calling processEvents() nothing worked. Is there any way to force UI to update slider widget after setValue()?

Make sure that you are not updating ccfg.mxxx values in the valueChanged slot function.

Related

Changing fluently brightness of QPushButton icon

I found a function to make QImage brighter and used in my Qt application.
I want to show simple "animation" of making button step by step brighter and than again step by step back to initial state after user click it.
Here my code:
void Widget::on_stopButton_clicked(){
player.stop();
for(int i = 0; i <= 50; ++i){
QImage* image = new QImage(":/Graphics/Graphics/StopButton.png");
changeBrightness(*image, i);
QPixmap* pixmap = new QPixmap(QPixmap::fromImage(*image));
ui->stopButton->setIcon(QIcon(*pixmap));
QThread::msleep(50);
}
}
It doesn't work as I expected...
I see only the final effect, so the last call:
changeBrightness(*image, 50);
It seems that user can see changes on form only after function ends, is it right?
Is there other way to make such "animation"?
You do not give Qt any time to redraw the widget after you update the button's image, because you are stuck in the loop. Only after you finished updating the image, Qt will be able to redraw your widget, which is why you only see the final result.
Look into QTimer. You can set its timeout to 50 milliseconds via QTimer::setInterval. Then connect a slot that changes the color of the button's image to QTimer::timeout. This slot will be much like your code, but without the loop. E.g. each call of the slot is a single iteration of your loop. Finally, to start or stop the animation, you call QTimer::start or QTimer::stop.

How to change highlight color on QTreewidgetItem

I have wrote an app using QTreeWidget. Currently when selecting an item using the mouse, this item is highlighted in blue as probably default palette.
How can I change the property to modify the highlight color when a QTreeWidgetItem is selected using the mouse. For example, the color is no more blue but the one I want.
My TreeWidget is defined as below:
setSortingEnabled(true);
setColumnWidth(0, 400);
setExpandsOnDoubleClick(true);
setAlternatingRowColors(true);
QPalette p = palette();
p.setColor( QPalette::AlternateBase, QColor(0xef, 0xef, 0xef) );
setPalette(p);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
I have also subclass the QTreeWidgetItem but it's mostly to add parameter and change the font by default
MyTreeWidgetItem::MyTreeWidgetItem()
{
isFolder = false;
filename = NULL;
QFont ItemFont = QFont(FONT_TYPE);
ItemFont.setPointSize(FONT_SIZE_MEDIUM);
setFont(0,ItemFont);
}
Any idea ?
Thanks

hide QLabel based on text-size

I would like to write a custom QLabel subclass with some more features for responsive design. In thisexample, I want to write a QLabel which scales the text based on the useable space. This is quite easy but also has some problems because of Qt-intern stuff. (I have to scale the text to 0.9 of the useable space, otherwise resizing the window / widget gets buggy)
Now I wan't to add a way to hide the label completely when the font size is bellow a specific threshold. However, this seems to be quite a complex task.
Here is what I have sofar in the classes resizeEvent(QResizeEvent *event) function.
Right now, my function only sets the text to "" when the size would be bellow the threshold.
void CustomLabel::resizeEvent (QResizeEvent * event ) {
if(autoFontResize) {
this->setSilentText(labelText); // just the normal setText function, I overwrote it for the subclass
QFont f = this->font();
int flags = Qt::TextDontClip|Qt::TextWordWrap;
QRect fontBoundRect = this->fontMetrics().boundingRect(this->rect(), flags, this->text());
float xFactor = (float)event->size().width() / (float)fontBoundRect.width();
float yFactor = (float)event->size().height() / (float)fontBoundRect.height();
float factor = xFactor < yFactor ? xFactor : yFactor;
f.setPointSizeF(f.pointSize()*factor*0.9); //
if(minimumFontSize != 0) { // 0 = no minimum Size for the font
if(f.pointSize() < minimumFontSize) {
if(hideFontOnMinimum) { // either Hide or set to the limit size
this->setSilentText(""); //replace text
} else {
f.setPointSizeF(minimumFontSize);
}
}
}
this->setFont(f);
}
QLabel::resizeEvent(event);
}
By the way, some parts of the code are found on stackoverflow, not mine. ;)
What I would like to do is to completely hide() the label. However the label doesn't know when It can show() again since the resizeEvent doesn't seem to be called after that.
Any ideas?
Thanks!
As you've noticed, if you call hide() on the widget it fails to receive a resize event. Since you're customising the class anyway, rather than calling hide(), you could just set a class variable to note that it's hidden and overload the paintEvent function, not to draw the widget if the variable is set: -
void CustomLabel::paintEvent(QPaintEvent * event)
{
if(m_hideOnMinimum)
return;
QLabel::paintEvent(event);
}
Note that by not painting the label, it will be hidden, but the user may still be able to interact with it, so you will need to disable it or overload keyboard / mouse events too.

qradiobutton issue

i have a problem with radio button.
I've created a groupbox with two radio buttons and set it exclusive so when one is checked the other one is unchecked.
when i check one it connects to a slot that as a function so it does an action, more specifically change the scale and transform the value from a Slider.
the problem is when i clicked by mistake the already checked button, because even if it already checked it still connects to the function and the value of the slider is changed again, which i don't want.
here's the code from them:
//Conect change from MM or PIXEL, making the change in the scale
connect(ui->radioButton, SIGNAL(pressed())), this, SLOT(mm()));
connect(ui->radioButton_2, SIGNAL(pressed()), this, SLOT(pixel()));
is there a way to block it when it has been already checked before?
I'll post here the mm() and pixel() functions:
// Function to transform the slider scale from pixel to mm
void planevolume::mm()
{
// Set the sliders ranges and connections
// X Slider
double xvaluem=ui->Slider->value();
ui->Slider->setRange(xmin, xmax/(256.0/3.0), 1.0/(256.0/3.0));
ui->Slider->setValue(xvaluem/(256.0/3.0));
ui->Slider->setScale(xmin, (xmax+1.0)/(256.0/3.0), ((xmax+1.0)/16.0)/(256.0/3.0));
connect(ui->Slider, SIGNAL(valueChanged(double)), ui->lcdNumber, SLOT(display(double)));
// Y Slider
double yvaluem=ui->Slider_2->value();
ui->Slider_2->setRange(ymin, ymax/(512.0), 1.0/(512.0));
ui->Slider_2->setValue(yvaluem/(512.0));
ui->Slider_2->setScale(ymin, (ymax+1.0)/512.0, (((ymax+1.0)/16.0)/512.0));
connect(ui->Slider_2, SIGNAL(valueChanged(double)), ui->lcdNumber_2, SLOT(display(double)));
// Z Slider
double zvaluem=ui->Slider_3->value();
ui->Slider_3->setRange(zmin, zmax/(64.0/3.0), 1.0/(64.0/3.0));
ui->Slider_3->setValue(zvaluem/(64.0/3.0));
ui->Slider_3->setScale(zmin, (zmax+1.0)/(64.0/3.0),(((zmax+1.0)/16.0)/(64.0/3.0)));
connect(ui->Slider_3, SIGNAL(valueChanged(double)), ui->lcdNumber_3, SLOT(display(double)));
}
// Function to transform the slider scale from mm to pixel
void planevolume::pixel()
{
// Set the sliders ranges and connections
// X Slider
double xvaluep=ui->Slider->value();
ui->Slider->setRange(xmin, xmax, 1.0);
ui->Slider->setValue(xvaluep*(256.0/3.0));
ui->Slider->setScale(xmin, xmax+1.0, (xmax+1.0)/16.0);
connect(ui->Slider, SIGNAL(valueChanged(double)), ui->lcdNumber, SLOT(display(double)));
// Y Slider
double yvaluep=ui->Slider_2->value();
ui->Slider_2->setRange(ymin, ymax, 1.0);
ui->Slider_2->setValue(yvaluep*(512.0));
ui->Slider_2->setScale(ymin, ymax+1.0, (ymax+1.0)/16.0);
connect(ui->Slider_2, SIGNAL(valueChanged(double)), ui->lcdNumber_2, SLOT(display(double)));
// Z Slider
double zvaluep=ui->Slider_3->value();
ui->Slider_3->setRange(zmin, zmax, 1.0);
ui->Slider_3->setValue(zvaluep*(64.0/3.0));
ui->Slider_3->setScale(zmin, zmax+1.0, (zmax+1.0)/16.0);
connect(ui->Slider_3, SIGNAL(valueChanged(double)), ui->lcdNumber_3, SLOT(display(double)));
}
Instead of using the pressed() signal you might try to use the toggled(bool) signal. This signal is only emitted if the button changes state. Take a look at: http://doc.qt.io/qt-4.8/qabstractbutton.html#toggled
EDIT: If both buttons are connected to toggled(bool), then checking one will uncheck the other and also trigger the signal. But note that the signal has a bool that gives the new state of the button. Your slots must also have this bool parameter, i.e., in your case you need to rewrite your slots as void planevolume::mm(bool on) and void planevolume::pixel(bool on).
Once you have done this, you can simply check the value of the parameter. If it is false it means that the button was checked and now has just been unchecked. Then, the first line of both your functions can be as simple as
if (!on) return;
meaning, that if the radio button has just been unchecked, do not do anything, just go away.
I think the best option is to store a int value related to which option box is selected. Each time you click on an option box, check if it is already selected by using the variable, and then decide.
Regards,

How to display a tooltip only if the mouse cursor is within certain coordinates?

Within my component, I'm drawing some rectangles as below:
var objGraphics:Graphics=graphics;
objGraphics.drawRect(start, end, total, 5);
objGraphics.endFill();
I need to display a custom tooltip for each rectange when the mouse cursor is hovering over it.
How can I do this? I'm using the MouseMove event to track when the cursor moves over these coordinates (that part is working), but when I change the tooltip text it's not refreshing.
private function this_MOUSE_MOVE(event:MouseEvent):void
{
//...some code to check the coordinates to find out which rectangle the cursor
//is over
//current tooltip is "Rectangle A";
ToolTipManager.destroyToolTip(_myToolTip);
var localPoint:Point=new Point(event.localX, event.localY);
var globalPoint:Point=new Point(localToGlobal(localPoint).x,
localToGlobal(localPoint).y);
//cursor is over Rectangle B, so changing the tooltip;
_myToolTip=ToolTipManager.createToolTip("Rectangle B",
globalPoint.x, globalPoint.y) as ToolTip;
callLater(addChild, [_myToolTip]);
}
Thanks for your help.
EDIT: The problem seems to be with the following line:
ToolTipManager.destroyToolTip(_myToolTip);
If I comment out the preceding line, it will display the new tooltip, but it will keep creating new ones and the old ones never get removed. But if I add that line, it doesn't add any tooltips! Is the code not being executed sequentially, i.e., is the code to remove the tooltip somehow getting executed after the code to add the tooltip?
Assuming what you're adding to the stage, is called "myShape", you could do something like this:
// in your class...
private var var tooltip:Tooltip; // Or whatever your tooltip is
myShape.addEventListener(MouseEvent.MOUSE_OVER, handleOver);
myShape.addEventListener(MouseEvent.MOUSE_OUT, handleOut);
private function handleOver(evt:MouseEvent):void
{
// Show here
// OR
// tooltip = new Tooltip();
// addChild(tooltip);
}
private function handleOut(evt:MouseEvent):void
{
// Hide here
// OR
// removeChild(tooltip);
}
Hope this helps.

Resources