Strategies for dealing with focus in qwidget project with custom input device
-
I'm tasked with implementing a GUI for a custom hardware. Our earlier software has been SDL-based with custom widgets. We want to switch to Qt but are at the moment stuck on Qt4.8.
The hardware consists of a screen with four buttons beneath whose actions are mapped to: Qt::Key_Enter, Qt::Key_Up, Qt::Key_Down and Qt::Key_Escape. Those four buttons are the only available input methods for the user.
The GUI should consist of multiple screens; there should be a menu for selecting among the screens; and support for showing pop-up dialogues.
My problem is that I have to manually keep track of focus for each widget. If they don't have focus, then they won't receive keyboard events and the application gets stuck. Right now I'm littering the code with explicit calls to setFocus() for different widgets.
void MyWidget::showEvent(QShowEvent *event) { subWidget->setFocus(); // ... } void MyWidget::keyboardEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: menuWidget->setFocus(); break; case Qt::Key_Enter: someWidget->setFocus(); break; // ... } }
This approach won't scale as the program grows; if I get one of those single setFocus() calls wrong, then the program can no longer be controlled from the buttons.
QUESTIONS
- How should I design a program that only has esc, up, down, and enter available as input means?
- Can I somehow use the tab order for specifying how focus should change between widgets?
- Does anyone have examples of a QWidget based program that runs on a hardware with limited input devices?
- Would anything be significantly easier if I had access to a newer Qt version?
- Does QML give me any advantages here?
-
Hi and welcome to devnet,
Do you have any example screenshot of what your application should look like ? Or are you still in the design phase ?
It's possible to write a Qt application with reduced input. I remember doing such an application but it was a decade ago so the details are a bit blurry.
-
@SGaist The application is still in an early prototype phase. The plan is to use regular QWidgets and style them with css. There will be some sort of vertical list of icons in the left margin that will serve as sub-screen selectors.
When experimenting I've started with a MainWindow containing:
MainWidget::MainWidget(...) { menuList = new QListWidget(this); setFocusProxy(menuList); screenStack = new QStackedWidget(this); // Add widgets to layout // Fill menuList with icons and fix layout details // ... }
I've thought about create a common base class for the screens which calls setFocus() in the constructor. I've also considered implementing some sort of stack data structure for keeping track of the latest visited widgets; when escape is pressed, the widgets from the stack would be popped one by one and if the popped widgets is visible, I would call setFocus() on it.
The popups will most likely be stacked; the user should be able to have say 5 pending popup messages. I've done them with a QStackedWidget as well.
The whole solution feels hacky and fragile. I'd very much appreciate alternative architectural design suggestion.
-
The Keyboard Focus in Widgets chapter from Qt's documentation already give some hints on how to handle that.
If you build your focus chain properly you can then use nextInFocusChain and previousInFocusChain to avoid hardcoding stuff.