Qt 的 `QScrollBar` 滑塊大小會隨內容長度自動變化:內容少→滑塊長;內容多→滑塊短。需求:像 `QSlider` 那樣固定滑塊大小。
Qt 無屬性/樣式表直接設置滑塊固定大小,必須重寫繪製邏輯。
class FixedHandleScrollBar : public QScrollBar {
Q_OBJECT
public:
FixedHandleScrollBar(Qt::Orientation orientation, QWidget* parent = nullptr)
: QScrollBar(orientation, parent), m_fixedHandleLength(30) {}
void setFixedHandleLength(int len) { m_fixedHandleLength = len; update(); }
protected:
void paintEvent(QPaintEvent* event) override {
QStyleOptionSlider opt;
initStyleOption(&opt);
// 關鍵:手動計算固定大小的 handle 矩形
QRect handleRect = style()->subControlRect(QStyle::CC_ScrollBar, &opt,
QStyle::SC_ScrollBarSlider, this);
if (orientation() == Qt::Vertical) {
int centerY = handleRect.center().y();
handleRect.setTop(centerY - m_fixedHandleLength / 2);
handleRect.setBottom(centerY + m_fixedHandleLength / 2);
} else {
int centerX = handleRect.center().x();
handleRect.setLeft(centerX - m_fixedHandleLength / 2);
handleRect.setRight(centerX + m_fixedHandleLength / 2);
}
// 臨時修改 opt 用於繪製固定大小 handle
QStyleOptionSlider fixedOpt = opt;
fixedOpt.rect = handleRect;
QPainter painter(this);
style()->drawComplexControl(QStyle::CC_ScrollBar, &fixedOpt, &painter, this);
}
private:
int m_fixedHandleLength;
};
// 僅能設置最小高度,無法完全固定
scrollBar->setStyleSheet(
"QScrollBar:vertical {"
" width: 12px;"
"}"
"QScrollBar::handle:vertical {"
" min-height: 30px;" // 最小高度
" max-height: 30px;" // 嘗試限制最大高度(可能無效)
" background: #888;"
" border-radius: 6px;"
"}"
);
⚠️ `max-height` 在某些樣式/平台上會被 Qt 內部邏輯覆蓋,不可靠。
scrollBar->installEventFilter(this);
// ...
bool MyWidget::eventFilter(QObject* obj, QEvent* ev) {
if (obj == scrollBar && ev->type() == QEvent::Resize) {
// 強制調整 handle 幾何 - 會與 Qt 內部邏輯衝突,閃爍
}
return false;
}
Qt 設計哲學:標準控件行為固定,深度定制請繼承重寫。