PDA

View Full Version : setFocus not setting focus on an item with ItemIsFocusable



Luc4
27th August 2011, 08:53
Hi! I'm working with QGraphicsItem and QGraphicsWidget in a QGraphicsScene. I use setFocus to give focus to my items. Now I'm trying to setFocus on an item, but for some reason it seems not to get focused. The item has ItemIsFocusable to true and the policy to StrongFocus. I tried to set the focus passing Qt::OtherFocusReason.
Do you know of any reason why the item could not get focused?
Thanks!

wysota
27th August 2011, 10:52
Please provide a minimal compilable example reproducing the problem.

Luc4
27th August 2011, 11:01
Well, I suppose this would be very difficult. I'm reusing classes multilple times, and other instances of the same class are working correctly. Now I suppose that creating a minimal example would result in something working. That is why I was asking for the possible reasons. It seems that the setFocus has no effect at all. The focusInEvent method is not invoked and the focus remains on the previous item. Any way I can understand where the problem is?

wysota
27th August 2011, 14:06
I think the possible reason is that your code is incorrect. Another possible reason is that you didn't provide any practical information regarding your problem.

Luc4
27th August 2011, 15:38
Yes, I suppose the problem is in my code already. It is quite difficult to give all the information. What I can provide is some code. What I do is I create a QGraphicsWidget with a QGraphicsWidget as a child which should represent a button:


FS_CallingDialog* dialog = new FS_CallingDialog(QString((const char*)identity), conv);
dialog->button->focusedPenColor = Qt::white;
dialog->button->notFocusedPenColor = Qt::black;
dialog->button->setNavigationFocus();

the constructor of the class calls the base class constructor which in turn invokes its own base class (QGraphicsWidget) constructor. What I do in the constructor of FS_CallingDialog is:


QGraphicsSimpleTextItem* title = new QGraphicsSimpleTextItem(this);
title->setText(tr("..."));
QGraphicsSimpleTextItem* targetDisplayLabel = new QGraphicsSimpleTextItem(this);
targetDisplayLabel->setText(targetDisplayName);

button = new LoginButton(this);
button->setText(tr("..."));
connect(button, SIGNAL(okKeyPressed()), this, SLOT(fadeOut()));
connect(button, SIGNAL(okKeyPressed()), this, SLOT(deleteLater()));

// Position the items.
centerHInParent(title);
centerHInParent(targetDisplayLabel);
centerHInParent(button);

title->setPos(title->pos().x(), 10);
targetDisplayLabel->setPos(targetDisplayLabel->pos().x(), boundingRect().height()/3);
button->setPos(button->pos().x(), boundingRect().height()*2/3);

this->conv = conv;

My problem is that the button never seems to get the focus. The constructor of the LoginButton is:


resize(40, 10);
setFocusPolicy(Qt::StrongFocus);
setFlag(ItemIsFocusable, true);

focusedPenColor = Qt::white;
notFocusedPenColor = Qt::white;

and the setNavigationFocus() method is implemented this way:


// Set the focus to the item.
setFocus();
update(boundingRect());

It seems that pressing the button, the keyPressEvent(...) method invoked is not that of the LoginButton, but that of the QGraphicsPixmapItem which was focused before it.

I use the same code in other parts of my project and seems to work there. Do you notice anything wrong in here? Of course the mistake might be somewhere else... :(
Thanks.

wysota
27th August 2011, 18:40
Did you reimplement any event handlers from the scene or from the button item? If so, which ones and what does the code look like?

Luc4
27th August 2011, 18:53
No, I didn't reimplement the event handlers for the scene. I did it for the QGraphicsView. This is the code:


// If there is a list currently shown then move the list, otherwise
// go on.
if (list) {
switch (event->key()) {
case Qt::Key_Left:
event->accept();
if (list->isKeyPressed) return;
list->isKeyPressed = true;
list->moveRight();
break;
case Qt::Key_Right:
event->accept();
if (list->isKeyPressed) return;
list->isKeyPressed = true;
list->moveLeft();
break;
case Qt::Key_Up:
event->accept();
if (exitButton) exitButton->setNavigationFocus();
default:
QGraphicsView::keyPressEvent(event);
}
return;
}
QGraphicsView::keyPressEvent(event);


// If there is a list currently shown then move the list.
if (list) {
switch (event->key()) {
case Qt::Key_Left:
case Qt::Key_Right:
if (event->isAutoRepeat()) return;
event->accept();
list->isKeyPressed = false;
list->startAnimationsRelease();
default:
QGraphicsView::keyReleaseEvent(event);
}
return;
}
QGraphicsView::keyReleaseEvent(event);

These are used to make the arrows control a list which is a QObject controlling items in the scene.
The LoginButton has this:


// Send signal according to key pressed.
switch (event->key()) {
case Qt::Key_Space:
case Qt::Key_Enter:
case Qt::Key_Return:
emit okKeyPressed(); break;
case Qt::Key_Escape:
emit backKeyPressed(); break;
case Qt::Key_Left:
emit leftArrowKeyPressed(); break;
case Qt::Key_Right:
emit rightArrowKeyPressed(); break;
case Qt::Key_Up:
emit upArrowKeyPressed(); break;
case Qt::Key_Down:
emit downArrowKeyPressed(); break;
default:
// Do nothing and do not accept.
return;
}
event->accept();

and some others like the paint(...) event and the focusInEvent, which looks like this:


Q_UNUSED(event);
update(boundingRect());

I use that to draw the button differently when it acquires the focus.

wysota
27th August 2011, 21:42
By reimplementing the view's keyPressEvent you effectively disable events for items when list != 0. Furthermore this:

// Do nothing and do not accept.
will not work as the event is accepted by default.

Remove code of the focusInEvent(), if the item is focusable and doesn't get repainted when you think it gains focus then it doesn't gain focus.

See if it all changes anything.

Luc4
28th August 2011, 23:37
Thank you for your help.
I tried removing the focusInEvent(...) and nothing changes at all. I guess it wasn't necessary to explicitly update. Anyway the problem remains.
What should I do to the keyPressEvent reimplementation? The current implementation seems to correctly invoke the method that creates the new LoginButton and sets the focus. What are you suggesting to do with my current reimplementations of the keyPressEvent(...) methods (yes, you're right, there's some mess there too)?
Thanks!

Luc4
29th August 2011, 14:03
It seems I solved the problem... I'm not quite understanding the problem completely, but it seems that changing something in the keyPressEvent(...) reimplementations and moving the setNavigationFocus() after the item was added to the scene fixed the issue. Unfortunately I'm not sure about how I fixed it and so I'm not fully understanding...

wysota
29th August 2011, 16:45
Well... trying to focus something that didn't exist in the scene was bound to fail.

Luc4
30th August 2011, 08:10
Now that you mention it, it seems quite obvious :-) Thanks!