c++ 刻度线在已设置样式的QSlider上消失

r8uurelv  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(609)

我正在使用Qt5.3并尝试样式化一个QSlider。然而,当我应用我的样式表时,刻度线消失了。有人知道如何保持样式而不影响刻度线吗?
下面是样式表:

QSlider::groove:horizontal
{
    border: 1px inset #B0B0B0;
    background-color: #EAEAEA;
    height: 2px;
}

QSlider::Handle
{   
    border: 1px solid black;
    background: #B0B0B0;                        
    background-image: url(:/metal_background_small);    
    width: 12px;
    margin: -8px 0;
}

QSlider::Handle:Hover
{   
    border: 1px solid black;
    background: #707070;                        
    background-image: url(:/metal_background_small);    
}

QSlider::sub-page
{
/*  margin: 7px 1px 7px 0px;*/
    height: 2px;
    background: #05bcfe;
}
eqqqjvef

eqqqjvef1#

Qt样式表和刻度线不能很好地配合使用。最简单的解决方案是子类化QSlider并重新实现paint_event。

virtual void paintEvent(QPaintEvent *ev)
{

    QStylePainter p(this);
    QStyleOptionSlider opt;
    initStyleOption(&opt);

    QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);

    // draw tick marks
    // do this manually because they are very badly behaved with style sheets
    int interval = tickInterval();
    if (interval == 0)
    {
        interval = pageStep();
    }

    if (tickPosition() != NoTicks)
    {
        for (int i = minimum(); i <= maximum(); i += interval)
        {
            int x = round((double)((double)((double)(i - this->minimum()) / (double)(this->maximum() - this->minimum())) * (double)(this->width() - handle.width()) + (double)(handle.width() / 2.0))) - 1;
            int h = 4;
            p.setPen(QColor("#a5a294"));
            if (tickPosition() == TicksBothSides || tickPosition() == TicksAbove)
            {
                int y = this->rect().top();
                p.drawLine(x, y, x, y + h);
            }
            if (tickPosition() == TicksBothSides || tickPosition() == TicksBelow)
            {
                int y = this->rect().bottom();
                p.drawLine(x, y, x, y - h);
            }

        }
    }

    // draw the slider (this is basically copy/pasted from QSlider::paintEvent)
    opt.subControls = QStyle::SC_SliderGroove;
    p.drawComplexControl(QStyle::CC_Slider, opt);

    // draw the slider handle
    opt.subControls = QStyle::SC_SliderHandle;
    p.drawComplexControl(QStyle::CC_Slider, opt);
}
cnh2zyt3

cnh2zyt32#

我不得不修改前面的答案来解释Qt的CSS margin属性(只有当句柄的margin为0时,这个答案才有效),我还需要在绘制滑块和句柄 * 之后 * 绘制刻度,可能是因为它被绘制在刻度的顶部。
绘制刻度时,仅在平移手柄的边距和手柄宽度的一半后才开始绘制。最后一个刻度也必须与滑块右侧保持类似的距离。请参阅:drawing area image .

virtual void paintEvent(QPaintEvent *event)
{
    QStylePainter p(this);
    QStyleOptionSlider styleOptions;
    initStyleOption(&styleOptions);

    // Rectangle representing the slider's handle (position and size).
    const QRect handleRectangle =
    style()->subControlRect(QStyle::CC_Slider, &styleOptions, QStyle::SC_SliderHandle, this);

    // Draw the slider (this is basically copy/pasted from QSlider::paintEvent).
    styleOptions.subControls = QStyle::SC_SliderGroove;
    p.drawComplexControl(QStyle::CC_Slider, styleOptions);

    // Draw the slider handle.
    styleOptions.subControls = QStyle::SC_SliderHandle;
    p.drawComplexControl(QStyle::CC_Slider, styleOptions);

    // Draw tick marks.
    // Do this manually because they are very badly behaved with style sheets.
    int interval = tickInterval();
    if (interval == 0)
    {
        interval = pageStep();
    }

    if (tickPosition() != NoTicks)
    {
        // This is the horizontal margin of the slider's *handle*, as defined in the stylesheet.
        constexpr float margin = 25;

        const float handleWidth = static_cast<float>(handleRectangle.width());
        const float handleHalfWidth = handleWidth / 2.0f;
        const float sliderValueRange = static_cast<float>(this->maximum() - this->minimum());
        // Drawing range = control's width, minus twice the handle half width (one on each side), minus twice the margin (one on each side).
        const float drawingRange = static_cast<float>(this->width()) - handleWidth - 2.0f * margin;
        const float factor = drawingRange / sliderValueRange;
    
        for (int i = minimum(); i <= maximum(); i += interval)
        {
            // Height of the ticks' bars to draw.
            constexpr int tickHeight = 5;

            const int offsetValueSpace = i - minimum(); // How far from the slider's minimum value we are.
            const float offsetDrawingSpace = factor * static_cast<float>(offsetValueSpace) + handleHalfWidth + margin; // Where to draw in the horizontal range.
            const int x = static_cast<int>(offsetDrawingSpace);

            p.setPen(QColor{255, 255, 255, 255});
            if (tickPosition() == TicksBothSides || tickPosition() == TicksAbove)
            {
                const int y = this->rect().top();
                p.drawLine(x, y, x, y + tickHeight);
            }
            if (tickPosition() == TicksBothSides || tickPosition() == TicksBelow)
            {
                const int y = this->rect().bottom();
                p.drawLine(x, y, x, y - tickHeight);
            }
        }
    }
}

使用Qt的CSS中定义的边距:

MySlider::handle:horizontal {
    margin: -5px 25px; /* Match the 'margin' constexpr in the paint event. */
    ...
}

相关问题