PDA

View Full Version : Disable default tab behaviour for a QGraphicsItem



nmather
12th April 2007, 21:06
I have a QGraphicsItem in a QGraphicsView as part of a MainWindow. I'd like to have a the QGraphicsItem have custom behaviour for a tab key press. However, the MainWindow seems to intercept the tab key and use it to move to the next widget after the QGraphicsView in the window.

There is a workaround for this to allow QWidgets to have tab key behaviour:

http://doc.trolltech.com/4.2/eventsandfilters.html

But this doesn't seem to work as QGraphicsItems don't naturally derive event behaviour from either QObject or QWidget.

I've also tried calling event->accept() in MyGraphicsWidget::keyPressEvent(), but it doesn't seem to get a chance to even accept it (for example, if ( event->key() == Qt::Key_Tab ) qDebug( "tab" ) produces no output ).

Is there a way to have custom tabkey behaviour for QGraphicsItems?

Thanks in advance, Neil.

wysota
13th April 2007, 11:42
First of all make sure the graphics view is the current widget (has focus). If you want to catch tab keys you have to reimplement event() - for either the main window (last resort) or the view widget. Then you'll be able to forward the event to the scene or simply make sure it's not handled by the default implementation of event(). If you have trouble doing that, you can always "eat up" the event and either call some method that does what you want directly or post another key event that will then be handled by the scene or one of the items.

nmather
21st April 2007, 21:42
Thanks Wysota, I got it to work by overriding QGraphicsView::event() :)

In case it helps others, here is what I did:



bool MyGraphicsView::event( QEvent *event )
{
switch (event->type()) {
case QEvent::KeyPress: {
QKeyEvent *k = (QKeyEvent *)event;
QGraphicsView::keyPressEvent(k);
if (k->key() == Qt::Key_Backtab
|| (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))
|| (k->key() == Qt::Key_Tab) ) {
event->accept();
}
return true;
}
default:
return QGraphicsView::event( event );
}
}


Don't know if it's necessarily the best way to do it, but it seems OK for now.

no_barth
13th December 2017, 10:30
Thanks. I managed to simulate selection using TAB thanks to this post solution.
Here is my code sample:



bool FacadeGraphicsView::event( QEvent *event )
{
switch (event->type())
{
case QEvent::KeyPress:
{
QKeyEvent *k = (QKeyEvent *)event;
QGraphicsView::keyPressEvent(k);
if (k->key() == Qt::Key_Backtab
|| (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))
|| (k->key() == Qt::Key_Tab) )
{
event->accept();
m_facadeScene()->manageTabSelection();
}
return true;
}
default:
return QGraphicsView::event( event );
}
}

CustomScene* FacadeGraphicsView::m_customScene()
{
auto pCustomScene = dynamic_cast<CustomScene*>(scene());
return pCustomScene;
}




void CustomScene::manageTabSelection()
{
if ((selectedItems().count() == 0) || (selectedItems().count() > 1))
{
foreach( QGraphicsItem *item, items() )
{
auto current = dynamic_cast<QGraphicsPolygonItem*>( item );
if( current)
{
current->setSelected(false);
}
}

foreach( QGraphicsItem *item, items() )
{
auto current = dynamic_cast<QGraphicsPolygonItem*>( item );
if( current)
{
current->setSelected(true);
break;
}
}
}
else
{
bool found = false;
// Find a selected item
foreach( QGraphicsItem *item, items() )
{
auto current = dynamic_cast<QGraphicsPolygonItem*>( item );
if( current)
{
if (current->isSelected())
{
current->setSelected(false);
found = true;
}
else
{
if (found)
{
current->setSelected(true);
break;
}
}
}
}

// if selected was the last item, ensure to select at least one item
if (selectedItems().count() == 0)
{
foreach( QGraphicsItem *item, items() )
{
auto current = dynamic_cast<QGraphicsPolygonItem*>( item );
if( current)
{
current->setSelected(true);
break;
}
}
}
}
}