How to capture Tab Key in Qt widget - qt

I want to implement my own sequence for changing the focus of the active child widget using the Tab key. How to capture the Tab Key press event? I am using Qt5.2

If you want to change focus with Tab , you don't need to do those works, Qt has it as a feature.
First: set the desired widgets to be Qt::TabFocus or Qt::StrongFocus by QWidget::setFocusPolicy( Qt::FocusPolicy policy )
For example, if you want to rotate between 3 QLineEdit and 1 QCombobox, you have to assure that their focus policy have been set right. (Normally either Qt::TabFocus or Qt::StrongFocus will be set as default, but sometimes you might want to escape some widgets from being tabbed)
Second: go to designer mode and click "Edit Tab Order" to enter the tab-order editing mode
Third: After seeing the numbers, click on them until you got the desired sequence order.
(Picture from Qt official site)

Have a mouse press event or a event filter, get to the point where you have a QKeyEvent
Then only do something if tab was pressed
key_event->button() == Qt::Key_Tab

Related

With Electron, is there a way to distinguish between user clicking on the menu item and using the keyboard shortcut?

With Electron, is there a way to distinguish between user clicking on the menu item and using the keyboard shortcut?
I know that the expected behavior for both is generally the same, but I'd like to track the usage of shortcuts and menu clicks separately.
Unfortunately, you cannot do this directly. The event parameter of MenuItem's click handler doesn't have a property that indicates whether the action was invoked through mouse or keyboard.
Workaround
However, you can of course use a workaround, using the fact that if a menu function is triggered using the keyboard shortcut, the pressing of the key(s) can be simultaneously captured from the renderer process using the keydown event.
In its easiest form, you could track all calls to the menu function, i.e. disregarding whether they were invoked through mouse or keyboard. In parallel, you listen for the same shortcuts in your renderer. Whenever a shortcut is detected that is also an accelerator in your menu, you make a note of this.
Example
Assuming a scenario where you use the mouse to click the action, then use the shortcut, and then the mouse again, the tracked events would be:
# time event
1 t0 Menu item action (Using mouse)
2 t1 Menu item action (Using keyboard shortcut)
3 ~t1 Keyboard shortcut detected
4 t2 Menu item action (Using mouse)
If you have data like this, you can count the number of occurrences of "Menu item action" (here 3) and "Keyboard shortcut detected" (here 1). Then you know that 1 out of 3 times the menu action was invoked using the keyboard shortcut.
Downsides
The downsides of this workaround are:
Duplicated code for menu accelerators and key listener
Generation of two events in case of keyboard use
One could think of possible ways to remedy these downsides, depending on your particular use case.

How to control focus of QWidgetAction's child widgets?

for my application I'm trying to put login control into a QMenu and am struggling with controlling the focus policy.
This is my custom login widget:
class LoginWidget(QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
mainLayout = QVBoxLayout()
layoutH = QHBoxLayout()
nameField = QLineEdit()
pwdField = QLineEdit()
pwdField.setEchoMode(QLineEdit.EchoMode(2))
btnSubmit = QPushButton('log in')
btnSubmit.setIcon(IconCache.getIcon('login'))
for w in (nameField, pwdField):
layoutH.addWidget(w)
mainLayout.addLayout(layoutH)
mainLayout.addWidget(btnSubmit)
self.setLayout(mainLayout)
I then add the above widget to my menu like this:
app = QApplication([])
menu = QMenu()
settingsAction = QAction('settings', menu)
loginAction = QWidgetAction(menu)
loginAction.setDefaultWidget(LoginWidget())
menu.addAction(settingsAction)
menu.addAction(loginAction)
btn = QToolButton()
btn.setText('menu button')
btn.setMenu(menu)
btn.setPopupMode(QToolButton.InstantPopup)
btn.show()
sys.exit(app.exec_())
The problem is that when you open the menu, click into the name field to fill in the user name, then hit the tab key, focus jumps to the "settings" action rather than to the password widget inside the LoginWidget.
I tried setFocusPolicy(Qt.StrongFocus) on the LoginWidget as well as it's pwdField but to no avail.
Can this be done?
Thanks in advance,
frank
The QMenu has special handling for Tab / Backtab, which effectively converts them into Up / Down arrow key presses.
However, the real source of the problematic behaviour is the focusNextPrevChild method, which keeps forcing the focus back to the menu. Fortunately, this method is virtual, so it can be overridden in a subclass, like so:
class Menu(QtGui.QMenu):
def focusNextPrevChild(self, next):
return QtGui.QWidget.focusNextPrevChild(self, next)
This will restore normal tabbing between child widgets.
To also enable keyboard navigation from child widgets back to normal menu items, make sure the LoginWidget has a focus proxy, like so:
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
...
self.setFocusPolicy(QtCore.Qt.TabFocus)
self.setFocusProxy(nameField)
http://qt-project.org/doc/qt-4.8/qwidget.html#setTabOrder
http://qt-project.org/doc/qt-4.8/focus.html#tab-or-shift-tab
Tab or Shift+Tab
Pressing Tab is by far the most common way to move focus using the keyboard. (Sometimes in data-entry applications Enter does the same as Tab; this can easily be achieved in Qt by implementing an event filter.)
Pressing Tab, in all window systems in common use today, moves the keyboard focus to the next widget in a circular per-window list. Tab moves focus along the circular list in one direction, Shift+Tab in the other. The order in which Tab presses move from widget to widget is called the tab order.
You can customize the tab order using QWidget::setTabOrder(). (If you don't, Tab generally moves focus in the order of widget construction.) Qt Designer provides a means of visually changing the tab order.
Since pressing Tab is so common, most widgets that can have focus should support tab focus. The major exception is widgets that are rarely used, and where there is some keyboard accelerator or error handler that moves the focus.
For example, in a data entry dialog, there might be a field that is only necessary in one per cent of all cases. In such a dialog, Tab could skip this field, and the dialog could use one of these mechanisms:
If the program can determine whether the field is needed, it can move focus there when the user finishes entry and presses OK, or when the user presses Enter after finishing the other fields. Alternately, include the field in the tab order but disable it. Enable it if it becomes appropriate in view of what the user has set in the other fields.
The label for the field can include a keyboard shortcut that moves focus to this field.
Another exception to Tab support is text-entry widgets that must support the insertion of tabs; almost all text editors fall into this class. Qt treats Ctrl+Tab as Tab and Ctrl+Shift+Tab as Shift+Tab, and such widgets can reimplement QWidget::event() and handle Tab before calling QWidget::event() to get normal processing of all other keys. However, since some systems use Ctrl+Tab for other purposes, and many users aren't aware of Ctrl+Tab anyway, this isn't a complete solution.
So you probably will want to use:
QWidget.setTabOrder( nameField, pwdField )
QWidget.setTabOrder( pwdField, btnSubmit )
or something similar.
Hope that helps.

Does Qt have combo boxes like Word?

In Microsoft Word, if you want to use Bullets you have a combo box (If we can call it a combo box) to select the shape of the bullet (by clicking the little triangle) or you can just apply the default one by clicking the combo box's button.
Actually the combo box in Word has two parts. For an example let's consider a situation where I want to have a combo box in Qt that has these items as menu items:
"Restart", "Shutdown" and "Log off". User needs to choose one of them but he also can apply previously selected item by clicking its button exactly like Windows shutdown menu in start. You can click Shut down or select another option.
How can we achieve this in Qt?
If you are pursuing after a menu that looks like in the second picture, you can use QToolButton to achieve your goal. Use a QToolButton with popupMode set to MenuButtonPopup. It will render a control something similar to following.
Then you can style the look & feel further more using Qt Style Sheets. Read this example on how to style a QToolButton.
Create a QMenu dynamically, so you can attach it to the QToolButton at run-time in such a way that all items will be included in the menu except for the default item. Default action has to be assigned to the QToolButton itself.
You can use void QToolButton::setMenu (QMenu * menu) to assign a QMenu to your QToolButton at run-time.
If you are trying to design a control that is in your 1st screenshot, you will have to create a custom Qt control I guess. There is no default control available, which can yield that look & feel out of the box.

Keyboard control of GUI dialogs - Should default button change with focus?

In GUI dialogs, most applications provide for keyboard control as follows:
Enter key - presses the default button. (Default is usually indicated with a bold button border.)
Esc key - presses the Cancel or close button.
Space key - presses widget that currently has keyboard focus.
Tab key - advances focus to next widget.
Question is, when keyboard focus is on a widget that is a button, should the default button be changed to be the one with focus?
I see some issues with this behavior:
The display noise of redrawing buttons to unbold the outline of original default button and rebold the button under focus as being new default.
The Space key is now somewhat redundant with Enter key.
There is no keyboard accelerator to get the normal default button now (Usually the OK button).
However, it seems the trend has been in this direction to change the default button with focus change to another button. What is the rationale for this departure from the early GUIs? It would seem to provide less functionality given there is no way to press the original default button. Did people find that the original model was too complicated for users to understand? I would think keyboard control of dialogs would be a task for advanced users who would have no trouble understanding the model and prefer to have accelerator for current button (Space) and original default button (Enter) at all times.
Note that Qt for one is supporting the change: QPushButton's autoDefault property is responsible for the behavior of changing the default button. By default its value is true. Therefore, you must take extra action to set it to false for all buttons, to prevent them from becoming the default button when focused.
This is not a "departure from the early GUIs", at least not if by "early GUIs", you mean Windows 1.0. The behavior that you describe has been this way since the beginning.
The focused button is always "pushed" when the Enter key is pressed. The default button is only triggered in the following two situations:
The default button has the focus (which it does by default), or
The focus is on a control that does not process Enter key presses (such as a static control, or a single-line textbox that does not have the ES_WANTRETURN style flag set).
The famous Win32 blogger Raymond Chen has a post explaining this behavior (focus specifically on the last two quoted paragraphs):
A dialog box maintains the concept of a "default button" (which is always a pushbutton). The default button is typically drawn with a distinctive look (a heavy outline or a different color) and indicates what action the dialog box will take when you hit Enter. Note that this is not the same as the control that has the focus.
For example, open the Run dialog from the Start menu. Observe that the OK button is the default button; it has a different look from the other buttons. But focus is on the edit control. Your typing goes to the edit control, until you hit Enter; the Enter activates the default button, which is OK.
As you tab through the dialog, observe what happens to the default button. When the dialog box moves focus to a pushbutton, that pushbutton becomes the new default button. But when the dialog box moves focus to something that isn't a pushbutton at all, the OK button resumes its position as the default button.
The dialog manager remebers which control was the default button when the dialog was initially created, and when it moves focus to something that isn't a button, it restores that original button as the default button.
The behavior that I would expect is:
If I press enter when the window just pop up, it should press the default button
If I press tab, I start navigating through the widgets. In this case there are two options:
2.1 I press enter - this event should be delivered to the focused widget. There's no need to change the default button - simply hand the event to the focused widget.
2.2 I press escape. In this case, everything should go back to the state after the window is created.
Notes:
I come from a mixed background - I don't know if I learned this in windows, linux or Mobile OSes! This is just how I expect things to work out.
I don't use the space key (didn't know it's functionality)

What is the proper name for a multibutton?

I'm trying to design a UI in Qt and I can't find anywhere in the designer a button which can be "droped down" like combobox. What I mean by that is that I would like to have this button with his "default" option choosen so if I like it I would have to just click on it but if I would like to choose different option I would be able to clik the little arrow on the right side of this button and then pick option suitable for me at that moment.
You're looking for a QToolButton that has a set of actions or a menu set on it. From the documentation, the QToolButton::ToolButtonPopupMode...
Describes how a menu should be popped up for tool buttons that has a menu set or contains a list of actions.
Of it's values, the two that I see most frequently are DelayedPopup:
After pressing and holding the tool button down for a certain amount of time (the timeout is style dependant, see QStyle::SH_ToolButton_PopupDelay), the menu is displayed. A typical application example is the "back" button in some web browsers's tool bars. If the user clicks it, the browser simply browses back to the previous page. If the user presses and holds the button down for a while, the tool button shows a menu containing the current history list
And MenuButtonPopup:
In this mode the tool button displays a special arrow to indicate that a menu is present. The menu is displayed when the arrow part of the button is pressed.

Resources