Qt-interest Archive, May 2008
Problem with SIGNAL currentCellChanged(int, int, int, int) in QTableWidget
Message 1 in thread
Hi,
I came across this peculiar problem with SIGNAL currentCellChanged(int,
int, int, int) in QTableWidget.
I am using QTableWidget class for the application that I am developing
and have made the following settings with it.
tablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
There is a pushbutton next to the table which calls a function to remove
a selected row on receiving a click.
Now, for example, if there are 8 rows in the tableWidget, and I select
row 4 and click on remove button. Row 4 will be removed and the
selection will jump up to row 3. SIGNAL currentCellChanged will also
emit the new row as row 3. This behaviour is fine. The problem comes
when row 0 (THE FIRST ROW) is the one that is selected and removed. Now
since there is no place to jump 'up', the next automatic selection
jumps 'down' to row 1 SIGNAL currentCellChanged emits that row 1 is the
new row............. BUT row 1 is now new row 0 (since row 0 was
removed) . This means that SIGNAL currentCellChanged emits wrong row
number as the new row. It emits row 1 instead of row 0. *All this
assumes that we manually (by clicking with mouse or by keyboard tab
button) don't intervene in the selection process.*
Now if we click on the remove button to remove the currently selected
row 0, then the row 0 *does not get deleted (removed)* rather the one
down below gets removed.
I hope I have been able to explain the problem. I have written a small
example to demonstrate it.
#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QPushButton>
#include <QRect>
class TableTest : public QTableWidget {
Q_OBJECT
public:
TableTest(QWidget *parent);
private slots:
void removeRow();
void updateSelection(int row);
private:
QPushButton *button;
QTableWidget *tw;
int selectedRow;
};
TableTest::TableTest(QWidget *parent) : QTableWidget(parent) {
tw = new QTableWidget (5, 1, parent);
tw->setGeometry(QRect(30, 30, 291, 201));
tw->resizeRowsToContents();
tw->setSelectionBehavior(QAbstractItemView::SelectRows);
tw->setSelectionMode(QAbstractItemView::SingleSelection);
for (int i=0; i<6; i++){
tw->setItem(i, 0, new QTableWidgetItem("This is row
"+QString::number(i+1)));
}
button = new QPushButton(parent);
button->setGeometry(QRect(110, 250, 83, 28));
button->setText("Remove Row");
connect(tw, SIGNAL(currentCellChanged(int, int, int, int)), this,
SLOT(updateSelection(int)));
connect(button, SIGNAL(clicked()), this, SLOT(removeRow()));
tw->setCurrentCell(0,0);
}
void TableTest::updateSelection(int row){
selectedRow=row;
}
void TableTest::removeRow(){
tw->removeRow(selectedRow);
}
#include "main.moc"
int main(int argc, char *argv[] ){
QApplication app(argc, argv);
QWidget *w = new QWidget();
w->resize(346, 289);
TableTest tt(w);
w->show();
return app.exec();
}
Start the program and click on 'Remove Row' button. On clicking the
button, 'This is row 1' gets deleted (removed) from the table and the
selection automatically goes to 'This is row 2'. Now *without clicking
anywhere else* in the table, click on the 'Remove Row' button again.
Logically, 'This is row 2' should get removed because that is the one
with the selection. But, instead 'This is row 3' will get deleted
(removed). That is because the SIGNAL currentCellChanged is emitting the
wrong current row number.
Is this a bug or am I doing something wrong?
Rajen.
--
[ signature omitted ]
Message 2 in thread
I think QT emit signal currentCellChanged before deleting the row.
So, if you have selected row > 0, QT select 'row - 1' (emit signal whit
newRow = row - 1) and later will be deleted oldRow.
And, if you have selected row 0, QT select row 1 (emit signal whit
newRow = 1) and later will be deleted row 0. So, the signal is correct,
newRow is row 1.
Well, if you want assuring you could create new slot whit four params,
and connect this slot whit the signal currentCellChanged, then you are
going to be assured by printing the params (current column/row and
previous column/row).
I hope it will be useful for you.
Salu2.
Sorry for my (bad)English.
Rajen M. Parekh escribió:
> Hi,
>
> I came across this peculiar problem with SIGNAL
> currentCellChanged(int, int, int, int) in QTableWidget.
>
> I am using QTableWidget class for the application that I am developing
> and have made the following settings with it.
>
> tablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
> tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
>
> There is a pushbutton next to the table which calls a function to
> remove a selected row on receiving a click.
>
> Now, for example, if there are 8 rows in the tableWidget, and I select
> row 4 and click on remove button. Row 4 will be removed and the
> selection will jump up to row 3. SIGNAL currentCellChanged will also
> emit the new row as row 3. This behaviour is fine. The problem comes
> when row 0 (THE FIRST ROW) is the one that is selected and removed.
> Now since there is no place to jump 'up', the next automatic
> selection jumps 'down' to row 1 SIGNAL currentCellChanged emits that
> row 1 is the new row............. BUT row 1 is now new row 0 (since
> row 0 was removed) . This means that SIGNAL currentCellChanged emits
> wrong row number as the new row. It emits row 1 instead of row 0. *All
> this assumes that we manually (by clicking with mouse or by keyboard
> tab button) don't intervene in the selection process.*
>
> Now if we click on the remove button to remove the currently selected
> row 0, then the row 0 *does not get deleted (removed)* rather the one
> down below gets removed.
>
> I hope I have been able to explain the problem. I have written a
> small example to demonstrate it.
>
>
> #include <QApplication>
> #include <QTableWidget>
> #include <QTableWidgetItem>
> #include <QPushButton>
> #include <QRect>
>
> class TableTest : public QTableWidget {
>
> Q_OBJECT
>
> public:
> TableTest(QWidget *parent);
>
> private slots:
> void removeRow();
> void updateSelection(int row);
>
> private:
> QPushButton *button;
> QTableWidget *tw;
> int selectedRow;
> };
>
> TableTest::TableTest(QWidget *parent) : QTableWidget(parent) {
> tw = new QTableWidget (5, 1, parent);
> tw->setGeometry(QRect(30, 30, 291, 201));
> tw->resizeRowsToContents();
> tw->setSelectionBehavior(QAbstractItemView::SelectRows);
> tw->setSelectionMode(QAbstractItemView::SingleSelection);
> for (int i=0; i<6; i++){
> tw->setItem(i, 0, new QTableWidgetItem("This is row
> "+QString::number(i+1)));
> }
> button = new QPushButton(parent);
> button->setGeometry(QRect(110, 250, 83, 28));
> button->setText("Remove Row");
> connect(tw, SIGNAL(currentCellChanged(int, int, int, int)), this,
> SLOT(updateSelection(int)));
> connect(button, SIGNAL(clicked()), this, SLOT(removeRow()));
> tw->setCurrentCell(0,0);
> }
>
> void TableTest::updateSelection(int row){
> selectedRow=row;
> }
>
> void TableTest::removeRow(){
> tw->removeRow(selectedRow);
> }
>
> #include "main.moc"
>
> int main(int argc, char *argv[] ){
> QApplication app(argc, argv);
> QWidget *w = new QWidget();
> w->resize(346, 289);
> TableTest tt(w);
> w->show();
> return app.exec();
> }
>
>
> Start the program and click on 'Remove Row' button. On clicking the
> button, 'This is row 1' gets deleted (removed) from the table and the
> selection automatically goes to 'This is row 2'. Now *without clicking
> anywhere else* in the table, click on the 'Remove Row' button again.
> Logically, 'This is row 2' should get removed because that is the one
> with the selection. But, instead 'This is row 3' will get deleted
> (removed). That is because the SIGNAL currentCellChanged is emitting
> the wrong current row number.
>
> Is this a bug or am I doing something wrong?
>
> Rajen.
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>
--
[ signature omitted ]
Message 3 in thread
> I came across this peculiar problem with SIGNAL
> currentCellChanged(int, int, int, int) in QTableWidget.
While it could be argued that the signal is wrong (you should send a
mail to qt-bugs or use the form
http://trolltech.com/developer/bugreport-form), why do you store the
"selectedRow" at all?
Instead use tw->currentRow() or tw->selectionModel()->selectedRows().
Cheers,
Peter
--
[ signature omitted ]
Message 4 in thread
Please reply to the list, not to me in private.
Rajen M. Parekh wrote:
> Peter Prade wrote:
> >> I came across this peculiar problem with SIGNAL
> >> currentCellChanged(int, int, int, int) in QTableWidget.
> >
> > While it could be argued that the signal is wrong (you should send a
> > mail to qt-bugs or use the form
> > http://trolltech.com/developer/bugreport-form), why do you store the
> > "selectedRow" at all?
> >
> > Instead use tw->currentRow() or
> tw->selectionModel()->selectedRows().
>
> Even currentRow() gives wrong row number of the row which is
> selected.
> What I mean is that the selection lies on first row (row 0) but the
> currentRow() function gives result as 1 (row 1), when
> actually it should
> be 0 (row 0).
>
> Same is the case with tw->selectionModel()->selectedRows().
>
> Rajen.
I've just modified your example code, change the removeRow slot to:
void TableTest::removeRow(){
tw->removeRow(tw->currentRow());
}
Works for me, using Qt 4.3.3!
Cheers,
Peter
--
[ signature omitted ]
Message 5 in thread
Miguel Ángel Orenes Fernández wrote:
>> The signal is correct *before* the removal, because it emits before
>> the row is removed. But that is wrong. The signal should be emitted
>> *after* the row is removed, thereby giving the correct selected row
>> number.
> Why?
> QT emits this signal when the new row is selected (not when the row is
> deleted),
Correct.
> then if the new row is selected *before* deleting the old row,
> will emits signal *before* deleting.
> I think QT emits the signal correctly.
The signal is wrong in the sense that it should emit *after* the row is
removed. Then it would probably emit the correct row number where the
selection lies. I am trying to explain again below.
When the current selection lies on row 0 (the first row) currentRow()
function will give result 0 (meaning row 0). When you remove this row
the selection goes on row 1 (the second row). At this point the signal
gets emitted saying that current cell of the second row (row 1). But
since we have removed the first row (row 0), the second row has now
become the first row (row 0 ). This means that the signal which emitted
row 1 as current row is wrong. It becomes wrong because it was called
*before* the row was removed, if it was called *after* the row was
removed then I think it would emit the correct row number with the
selection.
I sincerely hope that I have been able to explain my view.
Rajen.
--
[ signature omitted ]