QTableWidget + setCellWidget - controlling tab order
I've been trying for some time now to make QTableWidget behave the way I want it.
I have a few MyTableWidgets (which inherit from QTableWidget) on the one tab. I modified QTableWidget so it would display in the first (and as for now only) row QLineEdits (to be precise it displays my class inheriting from QLineEdit) using QTableWidget::setCellWidget().
Now I would like to traverse through all MyTableWidgets on this tab.
If I have only a one column (so it's also the only cell in MyTableWidget) when I press Tab it goes to the next MyTableWidget (and I've reimplemented focusInEvent so the first cell in this MyTableWidget gets the focus). When I press Tab again and again it loops through all cells in the only row in this MyTableWidget, but never leaves MyTableWidget and I don't know where to change this behavior.
So my question is how to change QTableWidget so that after pressing Tab in the last cell it will go to the next widget not first cell (and shift+tab in the first cell to go to the previous widget)?
From all I read it appears I should do something by reimplementing focusNextPrevChild( bool), but I just can't get it to work properly.
edit:
I think I found the solution:
Code:
bool MyTableWidget::focusNextPrevChild( bool next )
{
std::cout << "focusNextPrev " << qPrintable(objectName()) << std::endl;
if( next )
{
if( currentColumn() == m_model->columnCount() - 1 )
return QWidget::focusNextPrevChild(next
);
return false;
}
else
{
if( currentColumn() == 0 )
return QWidget::focusNextPrevChild(next
);
return false;
}
}
{
switch( e->reason() )
{
case Qt::BacktabFocusReason:
cellWidget(0, m_model->columns().count()-1)->setFocus();
break;
case Qt::TabFocusReason:
default:
cellWidget(0,0)->setFocus();
break;
}
}
As far as I checked it does work, though I'm not sure it's entirely correct.
Re: QTableWidget + setCellWidget - controlling tab order
So after some playing around it appears it doesn't work as it should.
I have:
main.cpp
Code:
#include <QGroupBox>
#include <QApplication>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <MyTable.h>
int main(int argc, char *argv[])
{
{
sublay->addWidget( new MyTable(box));
box->setLayout(sublay);
layout->addWidget(box);
}
{ /* same as above */
sublay->addWidget( new MyTable(box));
box->setLayout(sublay);
layout->addWidget(box);
}
{ /* same as above */
sublay->addWidget( new MyTable(box));
box->setLayout(sublay);
layout->addWidget(box);
}
window->setLayout(layout);
window->show();
return app.exec();
}
MyTable.h
Code:
#include <QTableWidget>
#include <QFocusEvent>
#include <QEvent>
#include <QLineEdit>
#include <iostream>
{
Q_OBJECT
public:
{
setColumnCount(7);
setRowCount(1);
for(unsigned int i = 0; i < columnCount(); ++i)
{
}
}
bool focusNextPrevChild( bool next )
{
}
};
The code above is compilable.
To compile:
Code:
moc MyTable.h -o MyTable.cpp
g++ MyTable.cpp main.cpp `pkg-config QtGui --cflags --libs` -I . -o table
First question: shouldn't this work like this: when I press tab it goes to the next MyTable widget?
Because I thought that if I call directly QWidget::focusNextPrevChild(bool) it will treat MyTable as any other QWidget which can have focus, so it should navigate through all three MyTables not going into cells.
Re: QTableWidget + setCellWidget - controlling tab order
Another attempt:
MyTable.h:
Code:
#include <QTableWidget>
#include <QFocusEvent>
#include <QEvent>
#include <QLineEdit>
#include <iostream>
{
Q_OBJECT
public:
{
setColumnCount(7);
setRowCount(1);
for(unsigned int i = 0; i < columnCount(); ++i)
{
setCellWidget(0, i, e);
e->setFocusPolicy( Qt::ClickFocus );
}
}
{
switch( e->type() )
{
e->accept();
bool res = true;
switch( ke->key() )
{
case Qt::Key_Backtab:
res = focusNextPrevChild(false);
break;
case Qt::Key_Tab:
res = focusNextPrevChild(true);
break;
}
return res;
}
}
{
switch( e->reason() )
{
case Qt::BacktabFocusReason:
setCurrentCell(0, columnCount()-1);
break;
case Qt::TabFocusReason:
default:
setCurrentCell(0,0);
break;
}
}
bool focusNextPrevChild( bool next )
{
if( next )
{
if( currentColumn() < columnCount() - 1 )
{
setCurrentCell( 0, currentColumn() + 1);
return true;
}
}
else if( currentColumn() > 0 )
{
setCurrentCell( 0, currentColumn() - 1);
return true;
}
return false;
}
};
I don't know why this works only one way: when pressing tab it loops as it should. But when I press Shift+Tab ( = Key_Backtab) it loops inside one MyTable. Why does it behave like that?
Re: QTableWidget + setCellWidget - controlling tab order
ANd why do you need QTableWidget? If you want to place several QLineEdits in a row use QHBoxLayout. In more than one row use QGridLayout.
Re: QTableWidget + setCellWidget - controlling tab order
Quote:
Originally Posted by
faldżip
ANd why do you need QTableWidget? If you want to place several QLineEdits in a row use QHBoxLayout. In more than one row use QGridLayout.
1. I would like it to look like a grid ( possibly with vertical header, but horizontal header is a must) and user has to have the ability to resize columns when "grabbing" in between two header cells.
2. I would like to know what's going on and how to control tab traversal order (as I can't find anything in the docs and I can't google anything useful).
Re: QTableWidget + setCellWidget - controlling tab order
QLabels with QSplitters and QLineEdits could be your header and a whole view. You can even make it in Designer when you can easily set the tab order
Re: QTableWidget + setCellWidget - controlling tab order
Quote:
Originally Posted by
faldżip
QLabels with QSplitters and QLineEdits could be your header and a whole view. You can even make it in Designer when you can easily set the tab order
Hm... QSpliters. Haven't noticed that. I think I will go with that idea, but still I would like to know how the heck can I control tab traversal order.
Re: QTableWidget + setCellWidget - controlling tab order
Quote:
Originally Posted by
elmo
still I would like to know how the heck can I control tab traversal order.
Bump. Really noone has a clue on how to control tab order with QTableWidget/View?