valueChanged of doubleSpinBox not working - c++

//in my .h file i have:
void on_doubleSpinBox_test_valueChanged(double t);
//in my .cpp(mainwindow):
void MainWindow::on_doubleSpinBox_test_valueChanged(double t)
{
ui->lineEdit_test->setText(QString::number((double) t/2));
}
My problem is that when i set the value for lineEdit in SpinBox everything works, however in doubleSpinBox there is no message sent (changing value doesn't work).
What am i doing wrong? How to make this method to work?

The valueFromText and textFromValue methods might do what you want. They allow displaying the value of the spin box in a customized format, such as always displaying half the value of the spin box as in your code above.
http://doc.trolltech.com/4.7/qdoublespinbox.html#valueFromText
http://doc.trolltech.com/4.7/qdoublespinbox.html#textFromValue
A sample of how to use the methods is in the class QSpinBox and they are used the same in QDoubleSpinBox.
http://doc.trolltech.com/4.7/qspinbox.html#subclassing-qspinbox

Related

How to display a blinking cursor in QLineEdit during read-only

title pretty much says it all. I have a read-only text box on a form where users can edit the contents of this text box through buttons on the form. The form is basically a keypad. As users click the buttons, a digit will be added to the value in the text box.
Technically, the final application will be running on a machine with no keyboard but a touchscreen. Users interact with the application using the touchscreen and they should not be installing keyboards on the machine but in the event they do, I am making the text box read-only.
Now, how can I have the text box's cursor still blink even though it is read only?
I am wondering if I need to do something similar to this user's solution:
Hide QLineEdit blinking cursor
I have also tried using the setFocus method and I am looking into style sheets. However, nothing has panned out.
Other answers have given you technical solutions to your question. However, I think that you are going in a wrong direction. You want a QLineEdit that is read only, but with a cursor and still accepts input from a virtual keyboard... yeah, so it is not really read only... It is not smelling good.
And in general, arbitrarily and actively disabling standard functions is not a good idea. Especially, if it means hacking your way around standard widget behaviors an semantics to do it.
Let's think from the start. What is the issue of accepting input from a keyboard?
From your question I would dare to guess that you want to make sure that the QLineEdit only accepts digits, and forbid the user to input other characters.
If I am right what you want is a QValidator, either a QIntvalidator or a QRegExpValidator. Then you can let the users use a keyboard, but they will only be able to input digits, like they would with your virtual keyboard.
Create a class whiwh inherits from QLineEdit and ignore the key events (events triggered when the user press a key). It will make your line edit read only but without the look-and-feel:
class LineEdit: public QLineEdit
{
Q_OBJECT
public:
LineEdit(QWidget* parent=nullptr): QLineEdit(parent)
{
}
virtual void keyPressEvent(QKeyEvent* event)
{
event->ignore();
}
public slots:
void add(QString const& textToAdd)
{
setText(text() + textToAdd);
}
};
An usage example (the timer simulates the virtual keyboard):
LineEdit* line = new LineEdit;
line->show();
QTimer timer;
timer.setInterval(2000);
QObject::connect(&timer, &QTimer::timeout, [=]() { line->add("a"); });
timer.start();
Romha Korev's answer will appear to work, but it won't catch everything. It can still be possible to paste or drag&drop text into the line edit, or as a result of a locale dependent input-method keyboard event. I don't know all the various ways text can end up being entered into the line edit that way. You'd be hunting for holes to plug.
So I propose to abuse a QValidator for this. Do not set your line edit to read-only mode. Create your own validator that blocks all input unless you specifically disable it:
class InputBlockerValidator final: public QValidator
{
Q_OBJECT
public:
void enable()
{ is_active_ = true; }
void disable()
{ is_active_ = false; }
QValidator::State validate(QString& /*input*/, int& /*pos*/) const override
{
if (is_active_) {
return QValidator::Invalid;
}
return QValidator::Acceptable;
}
private:
bool is_active_ = true;
};
Now set an instance of this as the validator of your line edit:
// ...
private:
QLineEdit lineedit_;
InputBlockerValidator validator_;
// ...
lineedit_.setValidator(&validator_);
Then, whenever you insert text into the line edit, disable and re-enable the validator:
validator_.disable();
lineedit_.insert(text_to_be_inserted);
validator_.enable();
Do not ever call setText() on the line edit. For some reason, this permanently prevents the validator from blocking input. I don't know if this is intended or a Qt bug. Only use insert(). To simulate setText(), use clear() followed by insert().

Qt5 C++: Custom Spinbox accepting two values

I'm not really into qt but i would like to have spinbox accepting two values
i.e:
It should work like this: select value to change with mouse f.e second value click arrow button and change this value.
Is there any possibility to do that, not creating a new own custom widget?
Short answer is: no
Long answer is:
You should subclass QAbstractSpinBox and implement these two virtual methods:
virtual void stepBy(int steps) override;
virtual StepEnabled stepEnabled() const override;
Keep in mind that you will need to provide your own data store and data manipulation!
The first function determines what happens when the step in either direction is requested. The negative number for steps (that tells how many steps to go in either direction) means go down and positive means up (i.e. clicking on the arrows of the SpinBox). QSpinBox adds the value in steps to its value (so when negative it gets subtracted) for example. Here you can also catch what part of the SpiBox's string the user selected and increment that appropriately with use of
lineEdit()->selectionStart();
lineEdit()->selectedText();
and when you are done you set the correct text back with:
lineEdit()->setText(myModifedValueText); //note that your internally stored value does not need to be QString, you just need to create it from your value in this method to set it to the internal QLineEdit so it can be displayed
The second method is called when the SpinBox needs to know if it can go up or down. So basically here you check the boundaries (if there are any) and return the appropriate flags (QAbstractSpinBox::StepUpEnabled or QAbstractSpinBox::StepDownEnabled or both).
Optinally in the constructor of your SpinBox you can apply QValidator to its internal QLineEdit to accept only certain format of values when the user inputs them by hand, e.g.:
QRegExpValidator *validator = new QRegExpValidator(this);
validator->setRegExp(...); //create a RegExp for your value, you may use any Online regexp validator/creator for this to get the right one
lineEdit()->setValidator(validator);
Finally you can fine-tune your SpinBox to show a text when there is an invalid value or you can fix it yourself using QAbstractSpinBox::fixup and validate the input with the namesake QAbstractSpinBox::validate.
For really pimped out SpinBox you could also re-implement its context menu and actions where you first get the standard menu from QLineEdit:
QMenu *menu = lineEdit()->createStandardContextMenu();
in the QWidget::contextMenuEvent and add/modify it as you need before you show it with menu->exec(event->globalPos()) and then delete menu;.
However QAbstractSpinBox does most of the ground job for you so you really should be fine with implementing just the above two virtual methods.

Display the input of QLineEdit in a different window and or dialog?

I am writing a small QT gui application where there is a QLineEdit in my mainwindow.ui and I want to display the entered text in a separate dialog and or window when a button is pressed.
Now, I have stored the input in a variable, and I am also able to show this string on a label within this same mainwindow,
void MainWindow::on_GoButton_clicked()
{
QString mytext = ui->lineEdit_1->text();
ui->label_1->setText(mytext);
}
Now, I want to open a popup dialog (can be a window also), for example SecDialog;
SecDialog secdialog;
secdialog.setModal(true);
secdialog.exec();
and display the text of mainwindow->mytext string variable in a label of the SecDialog. How can I do that ??? I know it is a basic level question, but I think it will help clear lot of my doubts reagrding moving values of variables in between forms and classes.
Situation
So this is your situation:
From your code, the dialog is a modal dialog:
SecDialog secdialog;
//secdialog.setModal(true); // It's not needed since you already called exec(), and the
// dialog will be automatically set to be modal just like what
// document says in Chernobyl's answer
secdialog.exec();
Solution
To make the dialog display the text from the Window,
the concept is to pass the information(text) from the Window
to the dialog, and use a setter function from the dialog to display it.
Like Floris Velleman's answer, he passed the mytext string (by reference) to a customized dialog constructor and called the setter theStringInThisClass(myString) at once.
The implementation detail of this function is complemented by Chernobyl's answer (use the name setLabelText instead):
void SecDialog::setLabelText(QString str)
{
ui->label->setText(str); // this "ui" is the UI namespace of the dialog itself.
// If you create the dialog by designer, it's from dialog.ui
// Do not confuse with the ui from mainwindow.ui
}
Chernobyl suggested another way which calls the setter in the slot function and it bypasses the need of defining another constructor, but basically the concept is the same:
void MainWindow::on_GoButton_clicked()
{
QString mytext = ui->lineEdit_1->text();
ui->label_1->setText(mytext);
SecDialog secdialog;
secdialog.setLabelText(myText); // display the text in dialog
secdialog.exec();
}
Comment
I try to illustrate the concept as clear as possible, because from my previous experience on your question, you just "copy & paste" codes from answers and took them as your final solution, which is not right. So I hope this summary could help you understand the concept and then you may write your own code.
This task can be easy done with getter/setter method or with signal and slot, but setter is more suitable here. In SecDialog header:
public:
void setLabelText(QString str);
//in cpp
void SecDialog::setLabelText(QString str)
{
ui->label->setText(str);//it is label dialog
}
Usage:
secDialog.setLabelText(myText);
Also line where you set modal to true is not necessary because
This property holds whether show() should pop up the dialog as modal
or modeless. By default, this property is false and show() pops up the
dialog as modeless. Setting his property to true is equivalent to
setting QWidget::windowModality to Qt::ApplicationModal. exec()
ignores the value of this property and always pops up the dialog as
modal.
Assuming SecDialog is a custom class with an interface file as well you might want to pass it as a constructor argument or pass it by using another function.
So in the SecDialog constructor you could have something like:
SecDialog::SecDialog(QWidget* parent, const QString& myString)
: QDialog(parent),
theStringInThisClass(myString)
{}
And then you could call it like:
SecDialog secdialog(this, mytext);

QTreeView not showing header

I am displaying a TreeView with a custom sortfilterproxymodel (which takes another custom model as source) and a custom delegate (overwritten paint) to affect the display of each item.
However, I cannot get the header of the TreeView to show. I had a look at both the proxy and the normal model and both have their headerData() called and return the correct values. I do not explicitly hide the header. In fact, I explicitly show() the header of the TreeView and setHeaderHidden() to false.
What could cause the header not being shown?
Here is the paint() function of the delegate, as I suspect the mistake somewhere there:
//---------------------------------------------------------------------------------
void
MyDelegate::paint(QPainter* p_painter, const QStyleOptionViewItem& p_option, const QModelIndex& p_index) const
{
// Get a custom text
QString text = "";
// Code that changes the text variable, nothing fancy, no pre-mature return
// Left out for convenience
// Call painter methods for drawing
p_painter->save();
p_painter->setClipRect(p_option.rect);
drawBackground(p_painter, p_option, p_index);
drawDisplay(p_painter, p_option, p_option.rect, text);
drawFocus(p_painter, p_option, p_option.rect);
p_painter->restore();
}
If you wonder why I do all the painter stuff (save(), drawBackground, etc.) manually, it is because it seems to be the only way to change the displayed text inside the paint() function. At least the only one I could figure out. But I do not know if this has anything to do with the header not being shown in the view.
Edit: By now I tried to replace my own paint with the default one. The header is still not shown, so the paint() method seems to be innocent ;)
The problem was that I "forgot" to add the following to the beginning of the headerData() function:
if (role != Qt::DisplayRole)
return QVariant();
Though I have to say it is a bit weird that you have to have those lines in order to display anything at all. If they are required like that, why not do that check before headerData() is even called?
Anyway, I hope that may help some people with the same problem :)

How to issue signal each time a row is edited in QListWidget?

class genericTaskList : public QListWidget
{
Q_OBJECT
public:
QListWidgetItem *defaultText;
genericTaskList (QWidget *parentWidget)
{
setParent (parentWidget);
setFixedSize (445, 445);
defaultText = new QListWidgetItem ("Double click here to compose the task");
defaultText->setFlags (defaultText->flags () | Qt :: ItemIsEditable);
insertItem (0, defaultText);
QObject :: connect (this, SIGNAL (currentRowChanged (int)), this, SLOT (addDefaultText (int)));
}
public slots:
void addDefaultText (int rr)
{
std::cout << "\ndsklfjsdklfhsdklhfkjsdf\n";
insertItem (++rr, defaultText);
}
};
This code is supposed to issue a signal each time the row gets edited.
After I call "insertItem" in the constructor, the signal is issued.
But, that's it. It never gets issued after that - no matter how many times I edit the row.
What am I missing?
At first it seems like QListWidget::itemChanged is the way to go, but soon you run into a problem: the signal is sent for everything - inserts, removes, changing colors, checking boxes, etc! So then you end up trying to put in flags and filter everywhere by intercepting various signals to find out if editing was the actual event. It gets very messy.
There is also QAbstractItemModel::dataChanged , which would seem like a good solution. It even has a parameter "const QVector& lstRoles" so you could scan for Qt::EditRole and see if it was really edited. Alas, there's a catch - it gets called for everything just like QListWidget::itemChanged and unfortunately, for QListWidget anyway, the roles parameter is always empty when it's called (I tried it). So much for that idea...
Fortunately, there's still hope... This solution does the trick! :
http://falsinsoft.blogspot.com/2013/11/qlistwidget-and-item-edit-event.html
He uses QAbstractItemDelegate::closeEditor, but I prefer using QAbstractItemDelegate::commitData.
So make a connect like so...
connect(ui.pLstItems->itemDelegate(), &QAbstractItemDelegate::commitData, this, &MyWidget::OnLstItemsCommitData);
Then implement the slot like this...
void MyWidget::OnLstItemsCommitData(QWidget* pLineEdit)
{
QString strNewText = reinterpret_cast<QLineEdit*>(pLineEdit)->text();
int nRow = ui.pLstItems->currentRow();
// do whatever you need here....
}
Now you have a slot that gets called only when the list item's text has been edited!
currentRowChanged indicates the row selection has changed, not the content of the row. Perhaps you want to use currentTextChanged or itemChanged instead.
The reuse of the word current and changed in the QT docs is quite confusing.
Warning: A QListWidgetItem can only be added to a QListWidget once. Adding the same QListWidgetItem multiple times to a QListWidget will result in undefined behavior.
So even if it will emit the signal I think you should better to add newly created Item.
And when do you want the new row to be inserted ? -
as soon as item is double clicked or finishing edit - they differ.