QDialog QPushButton响应键盘回车输入的问题

文章详细解释了QDialog中QPushButton的autoDefault属性、defaultButton的设置与响应,以及回车键如何触发默认按钮的点击过程。
摘要由CSDN通过智能技术生成

一、当按下回车键的时候:

如果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;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值