📄 qabstractbutton.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qabstractbutton.h"#include "qbuttongroup.h"#include "qabstractbutton_p.h"#include "qevent.h"#include "qpainter.h"#include "qapplication.h"#include "qstyle.h"#include "qaction.h"#ifndef QT_NO_ACCESSIBILITY#include "qaccessible.h"#endif#define AUTO_REPEAT_DELAY 300#define AUTO_REPEAT_PERIOD 100/*!\class QAbstractButton qabstractbutton.h\brief The QAbstractButton class is the abstract base class ofbutton widgets, providing functionality common to buttons.\ingroup abstractwidgetsThis class implements an \e abstract button.Subclasses of this class handle user actions, and specify how the buttonis drawn.QAbstractButton provides support for both push buttons and checkable(toggle) buttons. Checkable buttons are implemented in the QRadioButtonand QCheckBox classes. Push buttons are implemented in theQPushButton and QToolButton classes; these also provide togglebehavior if required.Any button can display a label containing text and an icon. setText()sets the text; setIcon() sets the icon. If a button is disabled, its labelis changed to give the button a "disabled" appearance.If the button is a text button with a string containing an ampersand (\&),QAbstractButton creates an automatic shortcut key, called a mnemonic, that maychange based on the button translation. The following code createsa push button labelled "Ro\underline{c}k & Roll" (where the c is underlined):\code QPushButton *button = new QPushButton(tr("Ro&ck && Roll"), this);\endcodeIn this example, the shortcut \key Alt+C is assigned to the button, so that whenthe user presses \key Alt+C the button will call animateClick().You can also set a custom shortcut key using the setShortcut()function. This is useful mostly for buttons that do not have anytext, because they have no automatic shortcut.\code button->setIcon(QIcon(":/images/print.png")); button->setShortcut(tr("Alt+F7"));\endcodeAll of the buttons provided by Qt (QPushButton, QToolButton,QCheckBox, and QRadioButton) can display both \l text and \l{icon}{icons}.A button can be made the default button in a dialog are provided byQPushButton::setDefault() and QPushButton::setAutoDefault().QAbstractButton provides most of the states used for buttons:\list\i isDown() indicates whether the button is \e pressed down.\i isChecked() indicates whether the button is \e checked. Onlycheckable buttons can be checked and unchecked (see below).\i isEnabled() indicates whether the button can be pressed by theuser.\i setAutoRepeat() sets whether the button will auto-repeat if theuser holds it down.\i setCheckable() sets whether the button is a toggle button or not.\endlistThe difference between isDown() and isChecked() is as follows.When the user clicks a toggle button to check it, the button is first\e pressed then released into the \e checked state. When the userclicks it again (to uncheck it), the button moves first to the\e pressed state, then to the \e unchecked state (isChecked() andisDown() are both false).QAbstractButton provides five signals:\list 1\i pressed() is emitted when the left mouse button is pressed whilethe mouse cursor is inside the button.\i released() is emitted when the left mouse button is released.\i clicked() is emitted when the button is first pressed and thenreleased when the shortcut key is typed, or when animateClick()is called.\i toggled(bool) is emitted when the state of a toggle buttonchanges.\endlistTo subclass QAbstractButton, you must reimplement at leastpaintEvent() to draw the button's outline and its text or pixmap. Itis generally advisable to reimplement sizeHint() as well, andsometimes hitButton() (to determine whether a button press is withinthe button). For buttons with more than two states (like tri-statebuttons), you will also have to reimplement checkStateSet() andnextCheckState().\sa QButtonGroup*/QAbstractButtonPrivate::QAbstractButtonPrivate() :#ifndef QT_NO_SHORTCUT shortcutId(0),#endif checkable(false), checked(false), autoRepeat(false), autoExclusive(false), down(false), blockRefresh(false)#ifndef QT_NO_BUTTONGROUP , group(0)#endif{}#ifndef QT_NO_BUTTONGROUPclass QButtonGroupPrivate: public QObjectPrivate{ Q_DECLARE_PUBLIC(QButtonGroup)public: QButtonGroupPrivate():exclusive(true){} QList<QAbstractButton *> buttonList; QPointer<QAbstractButton> checkedButton; void notifyChecked(QAbstractButton *button); bool exclusive; QMap<QAbstractButton*, int> mapping;};QButtonGroup::QButtonGroup(QObject *parent) : QObject(*new QButtonGroupPrivate, parent){}QButtonGroup::~QButtonGroup(){ Q_D(QButtonGroup); for (int i = 0; i < d->buttonList.count(); ++i) d->buttonList.at(i)->d_func()->group = 0;}bool QButtonGroup::exclusive() const{ Q_D(const QButtonGroup); return d->exclusive;}void QButtonGroup::setExclusive(bool exclusive){ Q_D(QButtonGroup); d->exclusive = exclusive;}/*! Adds the given \a button to the end of the group's internal list of buttons. \sa removeButton()*/void QButtonGroup::addButton(QAbstractButton *button){ addButton(button, -1);}void QButtonGroup::addButton(QAbstractButton *button, int id){ Q_D(QButtonGroup); if (QButtonGroup *previous = button->d_func()->group) if (previous && previous != this) previous->removeButton(button); button->d_func()->group = this; d->buttonList.append(button); if (id != -1) d->mapping[button] = id; if (d->exclusive && button->isChecked()) button->d_func()->notifyChecked();}void QButtonGroup::removeButton(QAbstractButton *button){ Q_D(QButtonGroup); if (d->checkedButton == button) d->checkedButton = 0; if (button->d_func()->group == this) { button->d_func()->group = 0; d->buttonList.removeAll(button); }}QList<QAbstractButton*> QButtonGroup::buttons() const{ Q_D(const QButtonGroup); return d->buttonList;}QAbstractButton *QButtonGroup::checkedButton() const{ Q_D(const QButtonGroup); return d->checkedButton;}QAbstractButton *QButtonGroup::button(int id) const{ Q_D(const QButtonGroup); return d->mapping.key(id);}void QButtonGroup::setId(QAbstractButton *button, int id){ Q_D(QButtonGroup); if (button && id != -1) d->mapping[button] = id;}int QButtonGroup::id(QAbstractButton *button) const{ Q_D(const QButtonGroup); return d->mapping.value(button, -1);}int QButtonGroup::checkedId() const{ Q_D(const QButtonGroup); return d->mapping.value(d->checkedButton, -1);}#endif // QT_NO_BUTTONGROUPQList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const{#ifndef QT_NO_BUTTONGROUP if (group) return group->d_func()->buttonList;#endif Q_Q(const QAbstractButton); QList<QAbstractButton*>candidates; if (q->parentWidget() && autoExclusive) { candidates = qFindChildren<QAbstractButton *>(q->parentWidget()); for (int i = candidates.count() - 1; i >= 0; --i) { QAbstractButton *candidate = candidates.at(i); if (!candidate->autoExclusive()#ifndef QT_NO_BUTTONGROUP || candidate->group()#endif ) candidates.removeAt(i); } } return candidates;}QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const{#ifndef QT_NO_BUTTONGROUP if (group) return group->d_func()->checkedButton;#endif Q_Q(const QAbstractButton); QList<QAbstractButton *> buttonList = queryButtonList(); if (buttonList.count() == 1) // no group return 0; for (int i = 0; i < buttonList.count(); ++i) { QAbstractButton *b = buttonList.at(i); if (b->d_func()->checked && b != q) return b; } return checked ? const_cast<QAbstractButton *>(q) : 0;}void QAbstractButtonPrivate::notifyChecked(){#ifndef QT_NO_BUTTONGROUP Q_Q(QAbstractButton); if (group) { QAbstractButton *previous = group->d_func()->checkedButton; group->d_func()->checkedButton = q; if (group->d_func()->exclusive && previous && previous != q) previous->nextCheckState(); } else#endif if (autoExclusive) { if (QAbstractButton *b = queryCheckedButton()) b->setChecked(false); }}void QAbstractButtonPrivate::moveFocus(int key){ QList<QAbstractButton *> buttonList = queryButtonList();;#ifndef QT_NO_BUTTONGROUP bool exclusive = group ? group->d_func()->exclusive : autoExclusive;#else bool exclusive = autoExclusive;#endif QWidget *f = qApp->focusWidget(); QAbstractButton *fb = ::qobject_cast<QAbstractButton *>(f); if (!fb || !buttonList.contains(fb)) return; QAbstractButton *candidate = 0; int bestScore = -1; QRect fGeometry = f->geometry(); QPoint goal(f->mapToGlobal(fGeometry.center())); for (int i = 0; i < buttonList.count(); ++i) { QAbstractButton *button = buttonList.at(i); if (button != f && button->isEnabled()) { QRect buttonGeometry = button->geometry(); QPoint p(button->mapToGlobal(buttonGeometry.center())); int score = (p.y() - goal.y())*(p.y() - goal.y()) + (p.x() - goal.x())*(p.x() - goal.x()); bool betterScore = score < bestScore || !candidate; switch(key) { case Qt::Key_Up: if (p.y() < goal.y() && betterScore) { if (qAbs(p.x() - goal.x()) < qAbs(p.y() - goal.y())) { candidate = button; bestScore = score; } else if (buttonGeometry.x() == fGeometry.x()) { candidate = button; bestScore = score/2; } } break; case Qt::Key_Down: if (p.y() > goal.y() && betterScore) { if (qAbs(p.x() - goal.x()) < qAbs(p.y() - goal.y())) { candidate = button; bestScore = score; } else if (buttonGeometry.x() == fGeometry.x()) { candidate = button; bestScore = score/2; } } break; case Qt::Key_Left: if (p.x() < goal.x() && betterScore) { if (qAbs(p.y() - goal.y()) < qAbs(p.x() - goal.x())) { candidate = button; bestScore = score; } else if (buttonGeometry.y() == fGeometry.y()) { candidate = button; bestScore = score/2; } } break; case Qt::Key_Right: if (p.x() > goal.x() && betterScore) { if (qAbs(p.y() - goal.y()) < qAbs(p.x() - goal.x())) { candidate = button; bestScore = score; } else if (buttonGeometry.y() == fGeometry.y()) { candidate = button; bestScore = score/2; } } break; } } } if (exclusive#ifdef QT_KEYPAD_NAVIGATION && !QApplication::keypadNavigationEnabled()#endif && candidate && fb->d_func()->checked && candidate->d_func()->checkable) candidate->click(); if (candidate) { if (key == Qt::Key_Up || key == Qt::Key_Left) candidate->setFocus(Qt::BacktabFocusReason); else candidate->setFocus(Qt::TabFocusReason); }}void QAbstractButtonPrivate::fixFocusPolicy(){ Q_Q(QAbstractButton); QList<QAbstractButton *> buttonList = queryButtonList(); for (int i = 0; i < buttonList.count(); ++i) { QAbstractButton *b = buttonList.at(i); if (!b->isCheckable())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -