How do I get the value of the slider's position in Qt Eclipse? - c++

I have about 5 push buttons and one slider. Every time I click the push button, the function for the particular push button gets called.
However, I also want the slider to do the same. So, instead of pressing the push button, you can drag the slider to the 5 different positions and it will do the same. However, I dont really know how I can connect 5 different positions of the sliders to each push button. Any help would be appreciated.
Thanks

I don't even know what to say... it's kinda easy:
slider->setRange(0, 4);
connect(slider, SIGNAL(valueChanged(int)), SLOT(onSliderValueChanged(int)));
...
void Widget::onSliderValueChanged(int value)
{
switch (value)
{
case 0:
return onPushButton0Clicked();
...
}
}
void Widget::onPushButton0Clicked()
{
// do stuff
slider->blockSignals(true);
slider->setValue(0);
slider->blockSignals(false);
}
...

Related

Closing Popup and setting button label

I'm writing a C++ wxWidgets calculator application. I want to compress trigonometric function buttons into a single one to save on space, using what's basically a split button. If you left click on it, the current option is used. If you right click, a popup menu is opened, which contains all the buttons; when you click on one of them, it is used and the big button changes.
I've been suggested to use wxComboBox and other stuff for this job, but I preferred using wxPopupTransientWindow because this way I can display the buttons in a grid, making everything - in my opinion - neater.
Problem is, when I choose an option from the menu, the main button's ID changes (because when I reopen the menu the previously clicked button is light up as its ID and the big button's ID match), but the label does not. Furthermore, the popup is supposed to close itself when you left click on one of the buttons, but it does not.
This is the code for the custom button in the popup which is supposed to do all that stuff:
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetParent()->GetParent();
mBtn->SetLabel(this->GetLabel());
mBtn->SetId(this->GetId());
this->GetParent()->Close(true);
}
}
This is the code for the custom button in the main frame which opens up the popup (temporary setup just to test if the whole thing is working):
void ikeButton::rightClick(wxMouseEvent& evt) // CREA PANNELLO ESTENSIONE
{
if (flags & EXPANDABLE)
{
std::vector<expandMenuInfo> buttons;
buttons.push_back(expandMenuInfo(L"sin", 3001));
buttons.push_back(expandMenuInfo(L"cos", 3002));
buttons.push_back(expandMenuInfo(L"tan", 3003));
buttons.push_back(expandMenuInfo(L"arcsin", 3004));
buttons.push_back(expandMenuInfo(L"arccos", 3005));
buttons.push_back(expandMenuInfo(L"arctan", 3006));
wxPoint p = this->GetScreenPosition();
size_t sz = this->GetSize().GetHeight() / 1.15;
expandMenu* menu = new expandMenu(this, buttons, sz, wxPoint(
p.x, p.y + this->GetSize().GetHeight() + 2));
menu->SetPosition(wxPoint(
menu->GetPosition().x - ((menu->GetSize().GetWidth() - this->GetSize().GetWidth()) / 2),
menu->GetPosition().y));
menu->Popup();
}
}
Let me know if I need to show more code.
This is probably a terrible way of doing this, but this is basically the first "serious" application I'm creating using the wxWidgets framework. Any help is appreciated.
when I choose an option from the menu, the main button's ID changes
(because when I reopen the menu the previously clicked button is light
up as its ID and the big button's ID match), but the label does not.
If you're creating the popup menu like in your previous post, you had a popup window with a panel as its child and the buttons were then children of the panel layed out with a sizer.
If that's still the case, this->GetParent() and should be the panel, this->GetParent()->GetParent() should be the popup. So this->GetParent()->GetParent()->GetParent() should be the trig function button (assuming you created the popup with the trig function button as the parent).
So I think the line wxWindow* mBtn = this->GetParent()->GetParent(); should be changed to wxWindow* mBtn = this->GetParent()->GetParent()->GetParent();.
Or slightly shorter wxWindow* mBtn = this->GetGrandParent()->GetParent();;
the popup is supposed to close itself when you left click on one of
the buttons, but it does not.
It looks like wxPopupTransientWindow has a special Dismiss method that is supposed to be used to close it.
So I think the line this->GetParent()->Close(true); should be changed to this->GetGrandParent()->Dismiss(); (Assuming as above that the buttons in the popup are children pf a panel).
Alternately, if you want a solution that will work regardless of the parentage of the controls in the popup window, you could have a utility function to find the popup ancestor which would look something like this:
wxPopupTransientWindow* FindPopup(wxWindow* w)
{
wxPopupTransientWindow* popup = NULL;
while ( w != NULL )
{
popup = wxDynamicCast(w, wxPopupTransientWindow);
if ( popup )
{
break;
}
w = w->GetParent();
}
return popup;
}
This uses the wxDynamicCast function which is slightly different from the c++ dynamic_cast expression. wxDynamicCast uses wxWidgets' RTTI system to check if the given pointer can be converted to the given type.
Then the mouseReleased method could use this utility function something like this:
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxPopupTransientWindow* popup = FindPopup(this);
if (popup ) {
wxWindow* mBtn = popup->GetParent();
mBtn->SetLabel(this->GetLabel());
mBtn->SetId(this->GetId());
mBtn->Refresh();
popup->Dismiss();
}
}
}
I'm not sure why you're setting trig function button to have a new id, but I assume you have a reason.
To make the SetLabel method work in your custom button class, I think the easist thing is to call the SetLabel() method in the button's constructor. This will store the string passed to the constructor in the button's internal label member.
Based on other questions, I think the ikeButton constructor looks something like this:
ikeButton::ikeButton(wxFrame* parent, wxWindowID id, wxString text,...
{
...
this->text = text;
To store the label, you would need to change the line this->text = text; to
SetLabel(text);
And when you draw the button, I think the method you use looks like this:
void ikeButton::render(wxDC& dc)
{
...
dc.DrawText(text, ...);
}
You would need to change, the line dc.DrawText(text, ...); to
dc.DrawText(GetLabel(), ...);
Likewise, any other references to the button's text member should be changed to GetLabel() instead.
Finally, when you set the label in the expandButton::mouseReleased method, it might be a good idea to call button's Refresh() method to force the button to redraw itself. I added that my suggestion for the mouseReleased method above.

Qt, offset when restore geometry

With Qt 5.11, I have this code to save end restore geometry of a QDialog subclass :
class HlgRunoffEditorDialog:public QDialog
{
some code
}
void HlgRunoffEditorDialog::show()
{
if (isVisible())
return;
ReosSettings settings;
restoreGeometry(settings.value(QStringLiteral("RunoffEditorDialog/geometry")).toByteArray());
ui->splitter->restoreState(settings.value(QStringLiteral("RunoffEditorDialog/splitter/geometry")).toByteArray());
QDialog::show();
}
void HlgRunoffEditorDialog::closeEvent(QCloseEvent *event)
{
updateSettings();
QDialog::closeEvent(event);
}
void HlgRunoffEditorDialog::updateSettings()
{
ReosSettings settings;
settings.setValue(QStringLiteral("RunoffEditorDialog/geometry"),saveGeometry());
settings.setValue(QStringLiteral("RunoffEditorDialog/splitter/geometry"),ui->splitter->saveState());
}
The problem is when the show() method is called, the windows has an offset with the position before the close event. A picture is more explicit than text :
The red line is the position before the close event.
It seems like the new position is set the top left point of the widget excluding the windows frame before close event is set on the the top left point of the widget including the windows frame after show() method id called.
Any idea ?
Edit 1
This offset above is on Windows. When I run on Linux KDE, it seems like the offset is in the other direction ....
Edit 2 :
This offset appear anly when the QDialog is close with the cross on the top right. When the QDialog is closed with the close button (connect to the close() slot), the offset is not here ...
For correct resoring visibility states of widgets (as windows) you must follow this call order:
// 1) show the widget
widget->show();
// 2) set status bar visibility (if exists)
//widget->statusBar->setVisible(booleanValueFromSettings);
// 3) set margins (if use it)
//widget->setContentsMargins(a, b, c, d);
// 4) geometry
widget->restoreGeometry(byteArrayFromSettings);
// 5) state (can be use it and for you splitter)
widget->restoreState(byteArrayFromSettings);
I remember a project where I had to calculate a bit, something like this:
QRect ng = w->normalGeometry();
QRect frame = w->frameGeometry();
ng.adjust(-frame.x(), -frame.y(), -frame.x(), -frame.y());
and saving the latter values

Qt QDialog moves location slightly each time it is closed and showed again

I have a QDialog and it pops up as a top level window in the center of my main window the first time it is opened(great, exactly what I want). However, each time I hit the "X" to close the window, when I trigger an event to cause the QDialog to pop up again(I use show() function for this)...the widget has slightly moved down and to the right(maybe 10 pixels each way, each time). Does anyone know what is causing this behavior/have a solution? Ideally I would like it to always pop up in the center of my main window(like it does the first time it opens).
Thanks in advance.
commandTimeWindow = new QDialog();
commandTimeWindow->resize(390, 180);
commandTimeWindow->setWindowTitle("Command In Progress");
commandTimeWindow->setStyleSheet("background-color: white;");
commandTimeWindow->setWindowFlags(Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
commandTimeWindow->setWindowIcon(QIcon(""));
commandTimeWindow->installEventFilter(this);
commandTimeWindow->close();
commandTimeWindow->show();
Also the standard "X" button closes the window...but I didnt write any code on this end.
You can use the widget's move(x, y) method or replace resize with setGeometry.
I was able to solve my issue using the code below:
void MyMainWindow::moveEvent(QMoveEvent* event)
{
const QPoint global = this->mapToGlobal(rect().center());
waitDialog->move(global.x() - waitDialog->width() / 2, global.y() - waitDialog->height() / 2);
}

How to remove focus from QLineEdit

I am developing a cpp/Qt tool.When I click on a QLineEdit field, its frame turns to a different color and the cursor starts blinking.When I type on Return in the field, I want its cursor to stop blinking and its frame color to default back to normal.I can intercept the Return Pressed, but when I then start the clearFocus() command, the keyboard input does not come anymore to the QLineEdit field (which is the behaviour I am expecting), but its frame doesn't go back to the default color and the cursor continues blinking. How to really remove focus from the field (i.e.: No cursor blinking anymore and frame back to default color) ?
=== EDIT ===
Here is the code:
void myQLineEditClass::keyPressEvent(QKeyEvent *e)
{
if(e->text().length()>0)
{
int asciiVal = e->text().at(0).toAscii();
if (asciiVal==3||asciiVal==13)
{
MGlobal::displayInfo(MQtUtil::toMString(QString().sprintf("Focus cleared"))); // -> this is properly displayed
clearFocus();
}
}
QLineEdit::keyPressEvent(e);
}
Thanks.

osgWidget label within frame won't trigger the callback

Here's my problem
I'm new to osg and I'm trying to create something like a dropdown list by adding osgWidget::Labels to a osgWidget::Box and then setting this same box as a osgWidget::Frame's window and all this works fine until the part where my callback "labelClicked" is never actually triggered once I click the label.
I tried adding this callback to other widgets such as an input and even the actual frame where I keep the box with the labels, and both worked fine.
Here's the functions that I use to add labels to my dropdown list:
osgWidget::Label* DropdownInput::createLabel(const std::string& l, unsigned int size) {
osgWidget::Label* label = new osgWidget::Label("", "");
label->setFont("fonts/Vera.ttf");
label->setFontSize(size);
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label->setLabel(l);
return label;
}
void DropdownInput::addLabel(string text){
osg::ref_ptr<osgWidget::Label> label1 = createLabel(text,15);
label1->setName(text);
label1->setPadding(2.0f);
label1->setColor(1,1,1, 1);
label1->setSize(300.0f, 40);
label1->setImage( "img.png" );
label1->addCallback( new osgWidget::Callback(&DropdownInput::labelClicked, this, osgWidget::EVENT_MOUSE_PUSH) );
dropdownContent.push_back(label1); //list where I store the labels for flitering purposes
this->dropdownBox->addWidget(label1);
}
and the callback:
bool DropdownInput::labelClicked(osgWidget::Event& ev) {
cout<<"label clicked!"<<endl;
return true;
}
Already tried to place the labels inside a box inside a frame and adding the callback to this frame instead, and then adding it to the main box but not only did it not resize correctly but also caused lag when filtering the labels which is not an option.
Also tried with other types of events like mouse over and such and still no answer from the label.
I was asked to avoid using other UI libraries, so if possible I would prefer osgWidget based solutions.
So, now I'm a bit lost, any help would be greatly appreciated.
If you didn't find my explanation to be comprehensible enough don't hesitate telling me since it's my first time posting here :)
For labels you should first add the push event to the label event mask:
label->addEventMask(osgWidget::EVENT_MOUSE_PUSH);
Otherwise label->canMousePush() will return false and the callback will never be called.