Emit signal if all children widgets lose focus
I have a QStackedWidget
which holds several pages full of various QLineEdit
and QComboBox
children. I want to emit a signal whenever the QStackedWidget
no longer has any child with focus (given that a child had focus to begin with). So moving from child to child will not emit 开发者_如何学Pythona signal, but once a widget is selected outside of the QStackedWidget
, a signal is emitted. Any advice on how to implement this? I've looked at InstallEventFilter
and QSignalMapper
, but neither of those appear to fit my needs. Any advice would be appreciated.
You can connect to the QApplication::focusChanged signal in order to evaluate the focus widgets within a corresponding slot. The clean way to do this is to derive from QStackedWidget:
class StackedFocusWidget : public QStackedWidget {
Q_OBJECT
public:
StackedFocusWidget(QWidget *parent = 0) : QStackedWidget(parent) {
connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(onFocusChanged(QWidget *, QWidget *)));
}
private slots:
void onFocusChanged(QWidget *old, QWidget *now) {
bool focusOld = old != 0 && isAncestorOf(old);
bool focusNow = now != 0 && isAncestorOf(now);
if (!focusOld && focusNow) {
emit gotFocus();
} else if (focusOld && !focusNow) {
emit lostFocus();
}
}
signals:
void gotFocus();
void lostFocus();
};
The signals StackedFocusWidget::gotFocus and StackedFocusWidget::lostFocus will be emitted whenever the stacked widget or any of its childs receives or loses focus.
This is a bit tricky. Even when cycling from child to child, there is a brief period after a child loses focus and before another child gains focus where no child of the stacked widget has focus. Although this state is extremely short lived, it's a matter of fact.
The only option I can see is to decide how long a period between a child widget losing focus and no child widget gaining focus you would consider to be long enough to declare that indeed, no child widget has focus anymore. This would be a mechanism similar to what is used to distinguish two single mouse clicks from one double-click.
This could be achieved using a timer and an event filter in the parent registered with each child, that looks for focus in and out events. Set the timer for some interval (100 ms?) and start it whenever a focus out event is received. If you receive a focus in event while the timer is still running, stop the timer. If the timer completes you can fire a signal of your own to indicate that no child widget has focus.
精彩评论