How to make a QScrollBar with a fixed size handle?

I need to make a scrollbar with a fixed-size handle, as its background image becomes ugly when zoomed. I use the following stylesheet:

QScrollBar::handle:vertical { border-image:url(:/images/handle.png); min-height: 47px; max-height: 47px; height: 47px; width:10px; } 

but it seems that max-height is invalid. How to prevent scaling of handles?

+6
source share
2 answers

Little trick from Qt source code: myScrollbar.h

 class myScrollBar : public QScrollBar { Q_OBJECT public: myScrollBar(Qt::Orientation orientation, QWidget *parent = 0); void setSliderLength(int length); protected: void paintEvent(QPaintEvent *); private: QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, /*const*/ QWidget *widget); QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect); int sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown); private: int _sliderLength; }; 

myScrollbar.cpp

 myScrollBar::myScrollBar(Qt::Orientation orientation, QWidget *parent) : QScrollBar(orientation, parent), _sliderLength(100) { } void myScrollBar::paintEvent(QPaintEvent *e) { qDebug() << "scrollbar paintevent"; //Q_D(QScrollBar); QScrollBar::paintEvent(e); QPainter painter(this); QStyleOptionSlider opt; initStyleOption(&opt); opt.subControls = QStyle::SC_All; QWidget *widget = this; // if (d->pressedControl) { // opt.activeSubControls = (QStyle::SubControl)d->pressedControl; // if (!d->pointerOutsidePressedControl) // opt.state |= QStyle::State_Sunken; // } else { // opt.activeSubControls = (QStyle::SubControl)d->hoverControl; // } QPainter *p = &painter; //style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this); if (const QStyleOptionSlider *scrollbar = &opt) { // Make a copy here and reset it for each primitive. QStyleOptionSlider newScrollbar = *scrollbar; QStyle::State saveFlags = scrollbar->state; if (scrollbar->subControls & QStyle::SC_ScrollBarSubLine) { newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSubLine, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSubLine)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarSubLine, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarAddLine) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarAddLine, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarAddLine)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarAddLine, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarSubPage) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSubPage, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSubPage)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarSubPage, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarAddPage) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarAddPage, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarAddPage)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarAddPage, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarFirst) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarFirst, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarFirst)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarFirst, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarLast) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarLast, widget); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarLast)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarLast, &newScrollbar, p, widget); } } if (scrollbar->subControls & QStyle::SC_ScrollBarSlider) { newScrollbar.rect = scrollbar->rect; newScrollbar.state = saveFlags; QRect rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSlider, widget); newScrollbar.rect = QRect(rect.topLeft(), QSize(rect.width(), 100)); if (newScrollbar.rect.isValid()) { if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSlider)) newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver); style()->drawControl(QStyle::CE_ScrollBarSlider, &newScrollbar, p, widget); if (scrollbar->state & QStyle::State_HasFocus) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(newScrollbar); fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2, newScrollbar.rect.width() - 5, newScrollbar.rect.height() - 5); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget); } } } } } void myScrollBar::setSliderLength(int length) { _sliderLength = length; } QRect myScrollBar::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, /*const*/ QWidget *widget) { QRect ret; switch (cc) { case QStyle::CC_ScrollBar: if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { const QRect scrollBarRect = scrollbar->rect; int sbextent = 0; if (!style()->styleHint(QStyle::SH_ScrollBar_Transient, scrollbar, widget)) sbextent = style()->pixelMetric(QStyle::PM_ScrollBarExtent, scrollbar, widget); int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2); int sliderlen; // calculate slider length if (scrollbar->maximum != scrollbar->minimum) { uint range = scrollbar->maximum - scrollbar->minimum; sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); int slidermin = style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, scrollbar, widget); if (_sliderLength < slidermin || range > INT_MAX / 2) _sliderLength = slidermin; if (_sliderLength > maxlen) _sliderLength = maxlen; //length of the slider sliderlen = _sliderLength; } else { sliderlen = maxlen; } int sliderstart = sbextent + this->sliderPositionFromValue(scrollbar->minimum, scrollbar->maximum, scrollbar->sliderPosition, maxlen - sliderlen, scrollbar->upsideDown); switch (sc) { case QStyle::SC_ScrollBarSubLine: // top/left button if (scrollbar->orientation == Qt::Horizontal) { int buttonWidth = qMin(scrollBarRect.width() / 2, sbextent); ret.setRect(0, 0, buttonWidth, scrollBarRect.height()); } else { int buttonHeight = qMin(scrollBarRect.height() / 2, sbextent); ret.setRect(0, 0, scrollBarRect.width(), buttonHeight); } break; case QStyle::SC_ScrollBarAddLine: // bottom/right button if (scrollbar->orientation == Qt::Horizontal) { int buttonWidth = qMin(scrollBarRect.width()/2, sbextent); ret.setRect(scrollBarRect.width() - buttonWidth, 0, buttonWidth, scrollBarRect.height()); } else { int buttonHeight = qMin(scrollBarRect.height()/2, sbextent); ret.setRect(0, scrollBarRect.height() - buttonHeight, scrollBarRect.width(), buttonHeight); } break; case QStyle::SC_ScrollBarSubPage: // between top/left button and slider if (scrollbar->orientation == Qt::Horizontal) ret.setRect(sbextent, 0, sliderstart - sbextent, scrollBarRect.height()); else ret.setRect(0, sbextent, scrollBarRect.width(), sliderstart - sbextent); break; case QStyle::SC_ScrollBarAddPage: // between bottom/right button and slider if (scrollbar->orientation == Qt::Horizontal) ret.setRect(sliderstart + sliderlen, 0, maxlen - sliderstart - sliderlen + sbextent, scrollBarRect.height()); else ret.setRect(0, sliderstart + sliderlen, scrollBarRect.width(), maxlen - sliderstart - sliderlen + sbextent); break; case QStyle::SC_ScrollBarGroove: if (scrollbar->orientation == Qt::Horizontal) ret.setRect(sbextent, 0, scrollBarRect.width() - sbextent * 2, scrollBarRect.height()); else ret.setRect(0, sbextent, scrollBarRect.width(), scrollBarRect.height() - sbextent * 2); break; case QStyle::SC_ScrollBarSlider: if (scrollbar->orientation == Qt::Horizontal) ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height()); else ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen); break; default: break; } ret = visualRect(scrollbar->direction, scrollBarRect, ret); } return ret; } } QRect myScrollBar::visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect) { if (direction == Qt::LeftToRight) return logicalRect; QRect rect = logicalRect; rect.translate(2 * (boundingRect.right() - logicalRect.right()) + logicalRect.width() - boundingRect.width(), 0); return rect; } int myScrollBar::sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown) { if (span <= 0 || logicalValue < min || max <= min) return 0; if (logicalValue > max) return upsideDown ? span : min; uint range = max - min; uint p = upsideDown ? max - logicalValue : logicalValue - min; if (range > (uint)INT_MAX/4096) { double dpos = (double(p))/(double(range)/span); return int(dpos); } else if (range > (uint)span) { return (2 * p * span + range) / (2*range); } else { uint div = span / range; uint mod = span % range; return p * div + (2 * p * mod + range) / (2 * range); } // equiv. to (p * span) / range + 0.5 // no overflow because of this implicit assumption: // span <= 4096 } 

eg:

 myScrollBar *bar = new myScrollBar(Qt::Vertical, ui->treeWidget); ui->treeWidget->setVerticalScrollBar(bar); 
+1
source

Using this jquery plugin http://jscrollpane.kelvinluck.com/

-1
source

Source: https://habr.com/ru/post/898953/


All Articles