This question already has answers here:
Passing an argument to a slot
(6 answers)
Closed 6 years ago.
I started working on a project that requires the using of the TableView. My table has 3 columns and the last column has a comboBox. Using the Delegate I managed to set the comboBox and to retrieve a signal when the index status of the comboBox changes. The problem is I can not identify from witch comboBox the signal is emited from.
If I signal to the mainWindow the QString of the comboBox this seems to be very bad. I was thinking at a solution to insert into the comboBox from each line the index of the row. Something like row + name.
I initiate the connection using the advice from another post, such like:
signals:
void boxDataChanged(const int & str);
In create editor:
QComboBox * editor = new QComboBox(parent);
editor->addItem("This");
editor->addItem("is");
editor->addItem("nice");
connect(editor, SIGNAL(currentIndexChanged(int)), this, SIGNAL(boxDataChanged(int)));
return editor;
And called like:
connect(mydelegate, &Delegate::boxDataChanged, [=](const int & str)
{
qDebug() << str;
});
This is working nice but I also need to know from witch row this is comming.
The problem is I can not identify from witch comboBox the signal is
emited from.
You can use QObject::sender to get the sender of the signal.
It will return a QObject that you can cast into the desired type.
Related
This question already has answers here:
Passing an argument to a slot
(6 answers)
Closed 6 years ago.
I'm new in Qt... I'm creating N buttons based on a JSON file. And I need to run a function/slot when a button is clicked and I need to know which buttton was pressed.
I tried:
QObject::connect(button, &QToolButton::clicked, this, &base::show_brands(json, type));
show_brands(json, type) is a function/slot...
but I can't send args like this...
How can I sent args to my function/slot? Or how can I run a function when a button is clicked?
You want to use QSignalMapper;
http://doc.qt.io/qt-5/qsignalmapper.html#details
This lets you send signals from a collection of objects to a single method which can identify the source object.
This question already has an answer here:
Qt, no such slot
(1 answer)
Closed 7 years ago.
I'm creating my first GUI App in QT, I'm newbie at it.
This application is supposed to count calories for me with little more options than webapps offer me.
In my program I got 4 lineedits :
lineEdit_Carbs
lineEdit_Fats
lineEdit_Protein
lineEdit_Calories
I want to do like "Realtime counter", if user provides value to any of the 3 cells, carbs,fats,proteins it shows how many calories is it already.
I tried to do this
connect(ui->lineEdit_Carbs,SIGNAL(textChanged(QString)),ui->lineEdit_Calories,SLOT(setText(CALORIE_COUNT(ui->lineEdit_Carbs->text(),ui->lineEdit_Fats->text(),ui->lineEdit_Proteins->text()))))
CALORIE_COUNT function takes 3 arguments, 3 QStrings, returns calculated QString containing the calories.
I would have to do this connection 3 times, for each lineEdit containing macronutrient.
But this seem to not work because
QObject::connect: No such slot QLineEdit::setText(CALORIE_COUNT(ui->lineEdit_Carbs->text(),ui->lineEdit_Fats->text(),ui->lineEdit_Proteins->text())) in ..\CalcProto\mainwindow.cpp:22
It says there is no such slot.
How should I create slot to make it work?
connect(ui->lineEdit_Carbs,
SIGNAL(textChanged(QString)),
this,
SLOT(intermediateSlot()));//SLOT can ignore incoming arguments
private Q_SLOTS:
intermediateSlot()
{
QString calorie = CALORIE_COUNT(ui->lineEdit_Carbs->text(),
ui->lineEdit_Fats->text(),
ui->lineEdit_Proteins->text());
ui->lineEdit.setText(calorie);// you can emit a new signal here
// carring calorie and connect it to
// ui->lineEdit, which is more Qt-ish
}
You maybe can subclass QLineEdit and reimplement the setText() method, but I am not sure you can, since it not seems to be declared as virtual
What about connecting all the QLineEdit textChanged(QString) to the the same slot and do all the work in it ?
Something like
connect(ui->lineEdit_Carbs,SIGNAL(textChanged(QString)), UpdateCalc);
connect(ui->lineEdit_Calories,SIGNAL(textChanged(QString)), UpdateCalc);
connect(ui->lineEdit_Fats,SIGNAL(textChanged(QString)), UpdateCalc);
connect(ui->lineEdit_Proteins,SIGNAL(textChanged(QString)), UpdateCalc);
where the UpdateCalc slot do all the calculations ?
Eventually you can add a timer to add a little delay to the execution so if you insert something with more than one char, you don't fire the event every time.
My program has 2 classes. One of them is MainWindow and another is Calc.
In main window I use automatic generated function on_PushButton_clicked. This function should send two values: double & char to function in Calc.
first:
void MainWindow::on_OneButton_clicked(){
QObject::connect(ui->ZeroButton , SIGNAL(clicked()), this, SLOT(...)) );
ui->TextEdit->insertPlainText("1");
}
second :
void Calc::Add(double val, char oper){
//compute something
}
It's my first app with Qt and I do not know how can I connect them. I've searched similar question on this forum, but can't found.
Sorry if i'm wrong.
First of all, you have to well understand what signal/slot mecanism is, and what you are doing.
Signal/slot mecanism is a Qt concept to link a function (signal) to another function (slot). To "make a link" between a signal and a slot, you have to connect them using QObject::connect(...).
When you use automatic generated function on_PushButton_Clicked() with Qt designer, you, in fact, "make a link" between the signal clicked() emitted when the pushButton is clicked, with a slot on_PushButton_Clicked(). However, the connection between this signal and this slot doesn't appear in your code so it may be confusing and that's why I'm pointing it out.
When you write this:
void MainWindow::on_OneButton_clicked(){
QObject::connect(ui->ZeroButton , SIGNAL(clicked()), this, SLOT(...)) );
ui->TextEdit->insertPlainText("1");
}
You create a connection with zeroButton when clicked and a slot, each time you clic on your button. As a connection is valid till an object is destructed, if you clic again on your pushButton, you'll have a second connection between zeroButton when clicked and your slot.
A better way to create connection is to use connect(...) function when you create your object (mainWindow in your case).
To make it simple for your calculator, you can create 9 buttons for digits, 4 buttons for operators, and 1 button to compute everything.
In your mainwindow constructor, you could have something like:
connect(ui->pushButton1, SIGNAL(clicked()), this, SLOT(onPushButton1Clicked()));
.... // Every other signal for each button
connect(ui->pushButtonEqual, SIGNAL(clicked(), this, SLOT(onPushButtonEqualClicked());
And in your body
void MainWindow::onPushButton1Clicked()
{
// concatenate current value + 1
ui->textEdit->insertPlainText(ui->textEdit->toPlainText() + "1");
}
void MainWindow::onPushButtonEqualClicked()
{
// check textedit content (need a digit + operator + digit)
...
// compute result
...
// write result in TextEdit
...
}
I hope it will help a little bit ;)
I need to create application which will work with database and I need to connect QCombobox with lineEdits(1,2,3). I have QComboBox with two items(1,2) and I want to hide lineEdits(2,3) when I change to item 2. And when I change back to item 1 I want to show lineEdits(2,3) and hide lineEdit 1. Can somebody help me? :-) Thanks
You simply connect the currentIndexChanged(int index) signal of your QComboxBox to a slot in your class and hide/show the QLineEdit's depending on the the value of index.
QObject::connect(myComboxBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(onComboxBoxCurrentIndexChanged(int)));
The slot can be implemented as follows:
MyClass::onComboxBoxCurrentIndexChanged(int index)
{
if(index == 0){
lineEdit1->setVisible(false);
lineEdit2->setVisible(true);
lineEdit3->setVisible(true);
}
else{
lineEdit1->setVisible(true);
lineEdit2->setVisible(false);
lineEdit3->setVisible(false);
}
}
Note that your class must be a subclass of QObject for the slot to work. If you don't know how signal and slots work I would recommend reading a tutorial first.
See http://qt-project.org/doc/qt-4.8/signalsandslots.html
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.