一、当按下回车键的时候:
如果QDialog中有default的QPushButton,触发该QPushButton的click。
二、QDialog中的按钮autoDefault属性
如果QDialog中的按钮没有设置过autoDefault属性,则该属性的返回值autoDefault()在QDialog下为开启。
( 如果QDialog已经显示,这时将default的按钮调用setDefault(false)设置为非default;
那么无论QDialog是否还有其他autoDefault的按钮,所有按钮都不会响应回车输入。)
class QPushButtonPrivate : public QAbstractButtonPrivate
{
Q_DECLARE_PUBLIC(QPushButton)
public:
enum AutoDefaultValue { Off = 0, On = 1, Auto = 2 };
QPushButtonPrivate()
: QAbstractButtonPrivate(QSizePolicy::PushButton), autoDefault(Auto),
defaultButton(false), flat(false), menuOpen(false), lastAutoDefault(false) {}
QPointer<QMenu> menu;
uint autoDefault : 2;
uint defaultButton : 1;
uint flat : 1;
uint menuOpen : 1;
mutable uint lastAutoDefault : 1;
};
void QPushButton::setAutoDefault(bool enable)
{
Q_D(QPushButton);
uint state = enable ? QPushButtonPrivate::On : QPushButtonPrivate::Off;
if (d->autoDefault != QPushButtonPrivate::Auto && d->autoDefault == state)
return;
d->autoDefault = state;
}
bool QPushButton::autoDefault() const
{
Q_D(const QPushButton);
if(d->autoDefault == QPushButtonPrivate::Auto)
return ( d->dialogParent() != 0 );
return d->autoDefault;
}
void QPushButton::setDefault(bool enable)
{
Q_D(QPushButton);
if (d->defaultButton == enable)
return;
d->defaultButton = enable;
if (d->defaultButton)
{
if (QDialog *dlg = d->dialogParent())
dlg->d_func()->setMainDefault(this);
}
}
/*!
dlg->d_func()->setMainDefault(this)
*/
void QDialogPrivate::setMainDefault(QPushButton *pushButton)
{
mainDef = 0;
setDefault(pushButton);
}
三、响应流程
1、QDialog在调用show()或者exec()时会调用QDialog::setVisible()函数,按照控件属性设置当前焦点;如果没有设置过default的QPushButton,QDialog将按照autoDefault属性设置一个default的QPushButton。
void QDialog::setVisible(bool visible)
{
Q_D(QDialog);
if (visible)
{
QWidget *fw = window()->focusWidget();
if (!fw)
fw = this;
if (d->mainDef && fw->focusPolicy() == Qt::NoFocus)
{
QWidget *first = fw;
while ((first = first->nextInFocusChain()) != fw &&
first->focusPolicy() == Qt::NoFocus)
;
if (first != d->mainDef && qobject_cast<QPushButton*>(first))
d->mainDef->setFocus();
}
if (!d->mainDef && isWindow())
{
QWidget *w = fw;
while ((w = w->nextInFocusChain()) != fw)
{
QPushButton *pb = qobject_cast<QPushButton *>(w);
if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus)
{
pb->setDefault(true);
break;
}
}
}
}
}
2、切换焦点时的按钮的default属性的处理。
(1)焦点切换到的按钮具有autoDefault属性,则将按钮自动设置为default。
(2)焦点移除按钮时,QDialog的default按钮不变。
void QPushButton::focusInEvent(QFocusEvent *e)
{
Q_D(QPushButton);
if (e->reason() != Qt::PopupFocusReason && autoDefault() && !d->defaultButton)
{
d->defaultButton = true;
QDialog *dlg = qobject_cast<QDialog*>(window());
if (dlg)
dlg->d_func()->setDefault(this);
}
QAbstractButton::focusInEvent(e);
}
void QPushButton::focusOutEvent(QFocusEvent *e)
{
Q_D(QPushButton);
if (e->reason() != Qt::PopupFocusReason && autoDefault() && d->defaultButton)
{
QDialog *dlg = qobject_cast<QDialog*>(window());
if (dlg)
dlg->d_func()->setDefault(0);
else
d->defaultButton = false;
}
QAbstractButton::focusOutEvent(e);
}
/*!
dlg->d_func()->setDefault(0)
*/
void QDialogPrivate::setDefault(QPushButton *pushButton)
{
Q_Q(QDialog);
bool hasMain = false;
QList<QPushButton*> list = qFindChildren<QPushButton*>(q);
for (int i=0; i<list.size(); ++i)
{
QPushButton *pb = list.at(i);
if (pb->window() == q)
{
if (pb == mainDef)
hasMain = true;
if (pb != pushButton)
pb->setDefault(false);
}
}
if (!pushButton && hasMain)
mainDef->setDefault(true);
if (!hasMain)
mainDef = pushButton;
}
3、响应回车。 触发QDialog中default按钮的click。
void QDialog::keyPressEvent(QKeyEvent *e)
{
switch (e->key())
{
case Qt::Key_Return:
{
QList<QPushButton*> list = qFindChildren<QPushButton*>(this);
for (int i=0; i<list.size(); ++i)
{
QPushButton *pb = list.at(i);
if (pb->isDefault() && pb->isVisible())
{
if (pb->isEnabled())
pb->click();
return;
}
}
}
break;
}
}