Problems creating a slot for putting some text into QTextEdit - c++

I've done quite a thorough research as I've been struggling with a slot issue, but as the Google search results steadily grew more and more purple, I decided just to ask the SO pals =) Please mind that I am not using QtCreator nor any dynamic stuff. I need to:
declare some QStrings which are constant
get some QStrings out of QLineEdits
add 1 and 2
finally, put them into QTextEdit when a button is clicked.
For the step 1, I declare QStrings like this:
QString set_1 = "ООО «Хеллманн» (129343, г. Москва, ул. Уржумская, д. 4, стр. 14, ИНН 7722637955, ОГРН 1087746168476) доверяет забор груза - ";
QString set_2 = " - перегружаемого из контейнера ";
QString set_3 = ", в количестве ";
QString set_4 = " паллет, весом ";
QString set_5 = " кг, водителю ";
QString set_6 = ", паспорт ";
QString set_7 = " выдан ";
QString set_8 = ".";
QString set_9 = " На автотранспортном средстве марки ";
QString set_10 = " - ";
QString set_11 = ", прицеп: ";
Then, for the step 2, I make QStrings out of QLineEdits like this (e.g. line_b_b is the name of a QLineEdit):
QString a = line_b_b.text();
QString b = line_b_a.text();
QString c = line_b_c.text();
QString d = line_b_d.text();
QString e = line_a_b.text();
QString f = line_a_a.text();
QString g = line_a_c.text();
QString h = line_a_d.text();
QString i = line_c_b.text();
QString j = line_c_a.text();
QString k = line_c_c.text();
For the step 3, I add the QStrings from the step 1 with those from the step 2 into a variable named "doverka" (please don't mind this cyrillic stuff):
QString doverka = set_1+a+set_2+b+set_3+c+set_4+d+set_5+e+set_6+f+set_7+g+h+set_8+set_9+i+set_10+j+set_11+k+set_8;
Finally, in the step 4, I try to put the whole into QTextEdit when a button is pushed. And I guess the problem is here. I create a QTextEdit named "text":
QTextEdit text (&dw);
text.show();
And then I try to create a slot and I presume I am doing this in a totally wrong way as it simply doesn't work:
QPushButton btn_t ("Создать текст", &dw);
QObject::connect(
&btn_t,
SIGNAL(clicked()),
&text,
SLOT([dover](){return text.setText(doverka)}));
btn_t.show();
I am new to Qt as well as to C++ and that's why poor at slot creation. Here I've tried this with a lambda function but I am obviously doing something wrong. Maybe I should just put the lambda function somewhere else before SLOT? My slot is not recognized as such when the prog is being compiled, I get the "no such slot" notification. Or maybe the problem is somewhere earlier, e.g. in making QStrings out of QLineEdits (step2)?.. I'm pretty helpless and appreciate any useful tips greatly! Very many thanks.

You are trying to mix old style Qt signal/slot connection with new style which obviously does not work. lambdas can be used only with new style of connections. If you are using Qt 5 the connection could be like:
QObject::connect(
&btn_t,
&QPushButton::clicked,
[&text, &doverka](){
text.setText(doverka);
});
You should be careful that text and doverka objects should not be destroyed before the lambda is invoked, as they are captured by reference.
In case of using Qt 4.* you should use the old syntax. In your case just provide a slot in your class and connect the signal it:
QObject::connect(
&btn_t,
SIGNAL(clicked()),
this,
SLOT(onClicked()));
Your class should inherit from QObject containing a slot like:
public slots:
void onClicked() {
text.setText(doverka);
}
Also note that text and doverka should be members of the class.

Related

I want to get the names of my spinboxes in Qt

How can I pull the names of my spinBoxes? I tried looking at a lot of the documentation, however, I couldn't find anything that would show the names of each of the child spinBoxes. I've tried changing the result to a string. However, I just get a Hex or Long Int, of the address I’d imagine, returned instead.
QList<QSpinBox*> spinBoxes= findChildren<QSpinBox*>();
//create the QSignalMapper object
QSignalMapper* signalMapper= new QSignalMapper(this);
//loop through your spinboxes list
QSpinBox* spinBox;
foreach(spinBox, spinBoxes){
//setup mapping for each spin box
connect(spinBox, SIGNAL(valueChanged(int)), signalMapper, SLOT(map()));
signalMapper->setMapping(spinBox, spinBox);
}
//connect the unified mapped(QWidget*) signal to your spinboxWrite slot
connect(signalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(spinboxWrite(QWidget*)));
.
.
.
void GuiTest::SpinBoxChanged(QWidget* wSp){
QSpinBox* sp= (QSpinBox*)wSp; //now sp is a pointer to the QSpinBox that emitted the valueChanged signal
int value = sp->value(); //and value is its value after the change
//do whatever you want to do with them here. . .
qDebug() << value << "SpinBoxChanged";
}
void GuiTest::spinboxWrite(QWidget* e){
SpinBoxChanged(e);
QString* value = (QString*)e;
qDebug() << e << value << " SpinBoxWrite";
}
Please note qDebug() << e as this is where I'm having trouble getting some information about the spinboxes
The name you are trying to retrieve is the objectName property, which every QObject and QObject-derived class has. Call objectName() to retrieve this value.
You can also use this with the QObject::findChild() function.
This should get what you want:
void GuiTest::spinboxWrite(QWidget* e){
SpinBoxChanged(e);
qDebug() << e->objectName() << " SpinBoxWrite";
And will output:
"norm_spinBox_10" SpinBoxWrite
Note
This line is dangerous:
QSpinBox* sp= (QSpinBox*)wSp;
Use qobject_cast instead of C-style casts.
There is no direct way to get the name of a variable as a string.
However, you can use a QMap<QSpinBox*, QString> to map each spin-box to its name.
In the constructor you have to assign these manually:
map[ui->spinBox] = "spinBox";
map[ui->spinBoxWithStrangeName] = "spinBoxWithStrangeName";
Then you can simply get the strings using:
QString name = map[ui->spinBox];
Just give them names in the designer file and then use that name to retrieve them in the C++ code.
QSpinBox* mySpinner = findChild<QSpinBox*>("myGivenName");

Qt c++ Increasing integer with pushButton to label

I'm trying to make a simple "Cookie Clicker" game and I'm having trouble with this. When I press the button I want the label to print out "You have mined (VALUE) FSCoins" but the label won't update for some reason. Console shows no errors :(
Here's my code:
mainwindow.cpp
void MainWindow::on_pushButton_clicked(int num, int numplus)
{
num = numplus + 1;
QString qstr = QString::number(numplus);
ui->label->setText("You have mined " + qstr + " FSCoins");
}
Any help would be appreciated, I've only started working with Qt yesterday and I'm "Sort of" getting the hang of it.
num = numplus + 1;
What is the point of this line? num is a local variable that is never used. Did you mean to pass it by reference?
You need to connect a SIGNAL to a SLOT, but that function you wrote there does not seem like a SLOT. Somewhere in your code there shall be something like this in your header file:
class ...
{
// ...
private slots:
void onPushButtonClicked();
};
and in your source file:
// For example in the constructor.
connect( ui->PushButton, SIGNAL( clicked() ), this, SLOT( onPushButtonClicked() ) );
// The implementation of your SLOT.
Class::onPushButtonClicked()
{
// Your implementation.
updateLabel( /* Your arguments */ );
}
The SLOT function cannot have more arguments than the SIGNAL, so in this case your SLOT cannot have any.
And something else. I prefer this version of creating a QString:
QString( "You have mined %1 coins" ).arg( value );
I think it's more readable.
So the point is that that you need store that integers somewhere. Maybe in your class as a member variable.

Why QLineEdit with QCompleter for auto completion doesn't shows up?

I have two QLineEdits in the program being lineEdit and fileName_Edit. lineEdit holds path to a directory (taken from user). Then user enters the name of file in the fileName_Edit. I want to show suggestions to user when he is entering the file name in fileName_Edit. I tried to implement QCompleter like this:
(dirContents is a QStringList which holds the contents of the directory specified by user in lineEdit)
void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
QCompleter *fileEditCompleter = new QCompleter(dirContents, this);
fileEditCompleter->setCaseSensitivity(Qt::CaseInsensitive);
fileEditCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
ui->fileName_Edit->setCompleter(fileEditCompleter);
}
Program compiles successfully but, the completer doesn't shows up. Even if I try to connect textChanged signal to the function like following, it doesn't shows up.
QObject::connect(&MainWindow::ui->lineEdit, SIGNAL(&textChanged(QString)), this,SLOT(&MainWindow::on_lineEdit_editingFinished()));
EDIT: Adding above line gives an error saying:
Expected constructor, destructor or type-conversion before ( token
Any help will be greatly appreciated.
Try to do it simply first, if the code works, then everything is good and you can start improving it.
In constructor:
QDir dir("G:/2");//path here
QStringList dirContents = dir.entryList(QStringList(), QDir::Files);
qDebug() << dirContents;//make sure that you list isn't empty, or use isEmpty method
QCompleter *fileEditCompleter = new QCompleter(dirContents, this);
fileEditCompleter->setCaseSensitivity(Qt::CaseInsensitive);
fileEditCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
ui->lineEdit->setCompleter(fileEditCompleter);
If this will work on your computer then you can be sure that your system and project are good, and start improve it (change list etc). And try not to use global variables.
If you want do it dynamically, create a simple model and when you will set new QStringList to it, your completer always will display new data
QDir dir("G:/2");
QStringList dirContents = dir.entryList(QStringList(), QDir::Files);
mdl = new QStringListModel(dirContents,this);//QStringListModel *mdl in header
QCompleter *fileEditCompleter = new QCompleter(mdl, this);
fileEditCompleter->setCaseSensitivity(Qt::CaseInsensitive);
fileEditCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
ui->lineEdit->setCompleter(fileEditCompleter);
When you want change data when for example, user clicks button or something else, you can do:
QDir dir("G:/2/tmp");
mdl->setStringList(dir.entryList(QStringList(), QDir::Files));
Now your completer has new data.
Converting comment to an answer, as requested...
Try to set completer before providing QLineEdit to user. For example - in constructor of MainWindow. It is not correct to set it in textChanged slot.
MainWindow::MainWindow()
: QWidget(nullptr)
, ui( new ui_MainWindow() )
{
ui->setupUi(this);
//...
QCompleter *fileEditCompleter = new QCompleter(dirContents, this);
fileEditCompleter->setCaseSensitivity(Qt::CaseInsensitive);
fileEditCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
ui->fileName_Edit->setCompleter(fileEditCompleter);
}
void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
// Do nothing here
}

Qt pass additional argument to slot AND keep emitted signal data

I have searched the web on this issue and I've repeatedly got answers referring to the use of QSignalMapper. But my problem is pretty clear, QSignalMapper automatically gets rid of whatever is originally emitted and replaces it with basically nothing, plus the new data that is set via setMapping().
The problem here is simple.
I have a QNetworkAccessManager that parses html and updates a vector containing text data:
void DataManager::startHttpRequest(QString url, int index)
{
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
//QSignalMapper* signalMapper = new QSignalMapper(this);
//connect(manager,SIGNAL(finished(QNetworkReply*)), signalMapper,SLOT(map()));
//signalMapper->setMapping(manager, index);
//connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(insertUpdate(int)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishHttpRequest(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl(url)));
qDebug() << index;
}
and here is what happens when the request is finished, the normal way:
void DataManager::finishHttpRequest(QNetworkReply *reply)
{
QString html = QString(reply->readAll()).simplified();
QString info;
int start = html.indexOf("<span id=\"SalePrice\" >");
if(start != -1)
{
QString price = html.mid(start + 23, 30);
int end = price.indexOf("</span>");
info = price.mid(0, end - 1);
qWarning() << price.mid(0, end - 1);
}
else
{
info = "NA";
}
// Do more stuff
}
Using the normal way of signals and slots, I would not be able to know the index of the vector I am updating,
Or,
If I am using QSignalMapper, I know the index, but not the data that comes with it.
How do I get BOTH working (index + data)?
(something like mySlot(QNetworkReply *reply, int *index), but we all know that won't work)
Many thanks in advance.
While it's probably not the best,
sender()->setObjectName(const QString & name) allows the sender to name itself.
The sender's name can be accessed from the receiving slot via sender()->ObjectName()
As documented on http://qt-project.org/doc/qt-5/qobject.html#objectName-prop.

Qt Signals & Slots: How do I get the data which was changed?

I have a QStandardModel. I connect its itemChanged signal to my own slot.
m_model = new QStandardItemModel(this);
connect(m_model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(changed(QStandardItem*)));
The slot looks like this:
void Class::changed(QStandardItem * item) {
// ui->pushButton->setText("change");
QString name = item->parent()->data().toString();
ui->pushButton->setText(item->data().toString());
}
The pushButton text will change to "change", so my slot seems to work. However, item->data().toString() is always empty.
How do I do this right?
I think you should use QStandardItem::text() method. Like this: QString name = item->parent()->text();