📄 qabstractspinbox.cpp
字号:
/*! Virtual function that determines whether stepping up and down is legal at any given time. The up arrow will be painted as disabled unless (stepEnabled() & StepUpEnabled) != 0. The default implementation will return (StepUpEnabled| StepDownEnabled) if wrapping is turned on. Else it will return StepDownEnabled if value is > minimum() or'ed with StepUpEnabled if value < maximum(). If you subclass QAbstractSpinBox you will need to reimplement this function. \sa QSpinBox::minimum(), QSpinBox::maximum(), wrapping()*/QAbstractSpinBox::StepEnabled QAbstractSpinBox::stepEnabled() const{ Q_D(const QAbstractSpinBox); if (d->readOnly || d->type == QVariant::Invalid) return StepNone; if (d->wrapping) return StepEnabled(StepUpEnabled | StepDownEnabled); StepEnabled ret = StepNone; if (d->variantCompare(d->value, d->maximum) < 0) { ret |= StepUpEnabled; } if (d->variantCompare(d->value, d->minimum) > 0) { ret |= StepDownEnabled; } return ret;}/*! This virtual function is called by the QAbstractSpinBox to determine whether \a input is valid. The \a pos parameter indicates the position in the string. Reimplemented in the various subclasses.*/QValidator::State QAbstractSpinBox::validate(QString & /* input */, int & /* pos */) const{ return QValidator::Acceptable;}/*! This virtual function is called by the QAbstractSpinBox if the \a input is not validated to QValidator::Acceptable when Return is pressed or interpretText() is called. It will try to change the text so it is valid. Reimplemented in the various subclasses.*/void QAbstractSpinBox::fixup(QString & /* input */) const{}/*! Steps up by one linestep Calling this slot is analogous to calling stepBy(1); \sa stepBy(), stepDown()*/void QAbstractSpinBox::stepUp(){ stepBy(1);}/*! Steps down by one linestep Calling this slot is analogous to calling stepBy(-1); \sa stepBy(), stepUp()*/void QAbstractSpinBox::stepDown(){ stepBy(-1);}/*! Virtual function that is called whenever the user triggers a step. The \a steps parameter indicates how many steps were taken, e.g. Pressing Qt::Key_Down will trigger a call to stepBy(-1), whereas pressing Qt::Key_Prior will trigger a call to stepBy(10). If you subclass QAbstractSpinBox you must reimplement this function. Note that this function is called even if the resulting value will be outside the bounds of minimum and maximum. It's this function's job to handle these situations.*/void QAbstractSpinBox::stepBy(int steps){ Q_D(QAbstractSpinBox); const QVariant old = d->value; QString tmp = d->edit->displayText(); int cursorPos = d->edit->cursorPosition(); bool dontstep = false; EmitPolicy e = EmitIfChanged; if (d->pendingEmit) { dontstep = validate(tmp, cursorPos) != QValidator::Acceptable; d->interpret(NeverEmit); if (d->value != old) e = AlwaysEmit; } if (!dontstep) { d->setValue(d->bound(d->value + (d->singleStep * steps), old, steps), e); } else if (e == AlwaysEmit) { d->emitSignals(e, old); } selectAll();}/*! This function returns a pointer to the line edit of the spin box.*/QLineEdit *QAbstractSpinBox::lineEdit() const{ Q_D(const QAbstractSpinBox); return d->edit;}/*! \fn void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit) Sets the line edit of the spinbox to be \a lineEdit instead of the current line edit widget. \a lineEdit can not be 0. QAbstractSpinBox takes ownership of the new lineEdit If QLineEdit::validator() for the \a lineEdit returns 0, the internal validator of the spinbox will be set on the line edit.*/void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit){ Q_D(QAbstractSpinBox); if (!lineEdit) { Q_ASSERT(lineEdit); return; } delete d->edit; d->edit = lineEdit; if (!d->edit->validator()) d->edit->setValidator(d->validator); if (d->edit->parent() != this) d->edit->setParent(this); d->edit->setFrame(false); d->edit->setAttribute(Qt::WA_InputMethodEnabled, false); d->edit->setFocusProxy(this); d->edit->setAcceptDrops(false); if (d->type != QVariant::Invalid) { connect(d->edit, SIGNAL(textChanged(QString)), this, SLOT(_q_editorTextChanged(QString))); connect(d->edit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(_q_editorCursorPositionChanged(int,int))); } d->updateEditFieldGeometry(); d->edit->setContextMenuPolicy(Qt::NoContextMenu); if (isVisible()) d->edit->show(); if (isVisible()) d->updateEdit();}/*! This function interprets the text of the spin box. If the value has changed since last interpretation it will emit signals.*/void QAbstractSpinBox::interpretText(){ Q_D(QAbstractSpinBox); d->interpret(EmitIfChanged);}/*! \reimp*/bool QAbstractSpinBox::event(QEvent *event){ Q_D(QAbstractSpinBox); switch (event->type()) { case QEvent::ApplicationLayoutDirectionChange: case QEvent::LayoutDirectionChange: d->updateEditFieldGeometry(); break; case QEvent::HoverEnter: case QEvent::HoverLeave: case QEvent::HoverMove: if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) d->updateHoverControl(he->pos()); break; case QEvent::ShortcutOverride: if (d->edit->event(event)) return true; break;#ifdef QT_KEYPAD_NAVIGATION case QEvent::EnterEditFocus: case QEvent::LeaveEditFocus: if (QApplication::keypadNavigationEnabled()) { const bool b = d->edit->event(event); d->edit->setSelection(d->edit->displayText().size() - d->suffix.size(),0); if (b) return true; } break;#endif default: break; } return QWidget::event(event);}/*! \reimp*/void QAbstractSpinBox::showEvent(QShowEvent *){ Q_D(QAbstractSpinBox); d->reset(); d->updateEdit();}/*! \reimp*/void QAbstractSpinBox::changeEvent(QEvent *event){ Q_D(QAbstractSpinBox); switch (event->type()) { case QEvent::StyleChange: d->spinClickTimerInterval = style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, 0, this); d->spinClickThresholdTimerInterval = thresholdTime; d->reset(); d->updateEditFieldGeometry(); break; case QEvent::EnabledChange: if (!isEnabled()) { d->reset(); } break; case QEvent::ActivationChange: if (!isActiveWindow()){ d->reset(); if (d->pendingEmit) // pendingEmit can be true even if it hasn't changed. d->interpret(EmitIfChanged); // E.g. 10 to 10.0 } break; default: break; } QWidget::changeEvent(event);}/*! \reimp*/void QAbstractSpinBox::resizeEvent(QResizeEvent *event){ Q_D(QAbstractSpinBox); QWidget::resizeEvent(event); d->updateEditFieldGeometry(); update();}/*! \reimp*/QSize QAbstractSpinBox::sizeHint() const{ Q_D(const QAbstractSpinBox); ensurePolished(); const QFontMetrics fm(fontMetrics()); int h = d->edit->sizeHint().height(); int w = 0; QString s; s = d->prefix + d->textFromValue(d->minimum) + d->suffix + QLatin1Char(' '); s.truncate(18); w = qMax(w, fm.width(s)); s = d->prefix + d->textFromValue(d->maximum) + d->suffix + QLatin1Char(' '); s.truncate(18); w = qMax(w, fm.width(s)); if (d->specialValueText.size()) { s = d->specialValueText; w = qMax(w, fm.width(s)); } w += 2; // cursor blinking space QStyleOptionSpinBox opt; initStyleOption(&opt); QSize hint(w, h); QSize extra(35, 6); opt.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this).size(); // get closer to final result by repeating the calculation opt.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this).size(); hint += extra; opt.rect = rect(); return style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this) .expandedTo(QApplication::globalStrut());}/*! \reimp*/QSize QAbstractSpinBox::minimumSizeHint() const{ Q_D(const QAbstractSpinBox); ensurePolished(); const QFontMetrics fm(fontMetrics()); int h = d->edit->minimumSizeHint().height(); int w = fm.width(QLatin1String("1000")); w += 2; // cursor blinking space QStyleOptionSpinBox opt; initStyleOption(&opt); QSize hint(w, h); QSize extra(35, 6); opt.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this).size(); // get closer to final result by repeating the calculation opt.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this).size(); hint += extra; opt.rect = rect(); return style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this) .expandedTo(QApplication::globalStrut());}/*! \reimp*/void QAbstractSpinBox::paintEvent(QPaintEvent *){ QStyleOptionSpinBox opt; initStyleOption(&opt); QStylePainter p(this); p.drawComplexControl(QStyle::CC_SpinBox, opt);}/*! \reimp This function handles keyboard input. The following keys are handled specifically: \table \row \i Enter/Return \i This will reinterpret the text and emit a signal even if the value has not changed since last time a signal was emitted. \row \i Up \i This will invoke stepBy(1) \row \i Down \i This will invoke stepBy(-1) \row \i Page up \i This will invoke stepBy(10) \row \i Page down \i This will invoke stepBy(-10) \endtable*/void QAbstractSpinBox::keyPressEvent(QKeyEvent *event){ Q_D(QAbstractSpinBox); if (!event->text().isEmpty() && d->edit->cursorPosition() < d->prefix.size()) d->edit->setCursorPosition(d->prefix.size()); int steps = 1; switch (event->key()) { case Qt::Key_PageUp: case Qt::Key_PageDown: steps *= 10; case Qt::Key_Up: case Qt::Key_Down: {#ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled()) { // Reserve up/down for nav - use left/right for edit. if (!hasEditFocus() && (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)) { event->ignore(); return; } }#endif event->accept(); const bool up = (event->key() == Qt::Key_PageUp || event->key() == Qt::Key_Up); if (!(stepEnabled() & (up ? StepUpEnabled : StepDownEnabled))) return; if (!up) steps *= -1; if (style()->styleHint(QStyle::SH_SpinBox_AnimateButton, 0, this)) { d->buttonState = (Keyboard | (up ? Up : Down)); } stepBy(steps); return; }#ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Left: case Qt::Key_Right: if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); return; } break; case Qt::Key_Back: if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); return; } break;#endif case Qt::Key_Enter: case Qt::Key_Return: d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged); selectAll(); event->ignore(); emit editingFinished(); return;#ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: if (QApplication::keypadNavigationEnabled()) { // Toggles between left/right moving cursor and inc/dec. setEditFocus(!hasEditFocus()); } return;#endif#ifdef Q_WS_X11 // only X11 case Qt::Key_U: if (event->modifiers() & Qt::ControlModifier) { event->accept(); if (!isReadOnly()) clear(); return; } break;#endif case Qt::Key_End: case Qt::Key_Home: if (event->modifiers() & Qt::ShiftModifier) { int currentPos = d->edit->cursorPosition(); const QString text = d->edit->displayText(); if (event->key() == Qt::Key_End) { if ((currentPos == 0 && !d->prefix.isEmpty()) || text.size() - d->suffix.size() <= currentPos) { break; // let lineedit handle this } else { d->edit->setSelection(currentPos, text.size() - d->suffix.size() - currentPos); } } else { if ((currentPos == text.size() && !d->suffix.isEmpty()) || currentPos <= d->prefix.size()) { break; // let lineedit handle this } else { d->edit->setSelection(currentPos, d->prefix.size() - currentPos); } } event->accept(); return; } break; default:#ifndef QT_NO_SHORTCUT if (event == QKeySequence::SelectAll) { selectAll(); event->accept(); return; }#endif break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -