QT 中的 QSlider 在新的 MacOS Monterey (v12.0.1) 中行为不端。任何解决方法?

Posted

技术标签:

【中文标题】QT 中的 QSlider 在新的 MacOS Monterey (v12.0.1) 中行为不端。任何解决方法?【英文标题】:QSlider in QT misbehaves in new MacOS Monterey (v12.0.1) . Any workaround? 【发布时间】:2021-12-21 16:40:56 【问题描述】:

据报道 (https://bugreports.qt.io/browse/QTBUG-98093),QT 中的 QSlider 组件在新的 MacOS 更新中无法正常运行。

如果我在同一个窗口中添加两个或多个水平滑块,拖动一个滑块中的夹点会影响其他滑块。这可能会导致他们一起移动,或者可能让下一个跳到一个意想不到的位置。

以下代码可以重现问题:

#include <QApplication>
#include <QDialog>
#include <QVBoxLayout>
#include <QSlider>

class Dialog: public QDialog

    QSlider* brokenSlider;
public:
    explicit Dialog(QWidget *parent = nullptr):QDialog(parent)
        auto mainLayout = new QVBoxLayout;
        brokenSlider = new QSlider(Qt::Horizontal, this);
        mainLayout->addWidget(brokenSlider);
        connect(brokenSlider, &QSlider::valueChanged, [&]()this->update(););

        mainLayout->addWidget(new QSlider(Qt::Horizontal, this));
        mainLayout->addWidget(new QSlider(Qt::Horizontal, this));
        setLayout(mainLayout);
    
;


int main(int argc, char *argv[])

    QApplication app(argc, argv);
    Dialog g;
    g.exec();

我正在寻找解决此 Apple/QT 错误的方法。

【问题讨论】:

【参考方案1】:

我能够解决将自定义样式表应用于滑块的问题。但是,这样做也会导致未显示的刻度出现问题。 我找到的解决方案是扩展 QSlider 并手动绘制:

myslider.h:

#pragma once

#include <QStylePainter>
#include <QStyleOptionSlider>
#include <QStyleOptionComplex>
#include <QSlider>
#include <QColor>
#include "math.h"

class MySlider:public QSlider

public:
    explicit MySlider(Qt::Orientation orientation, QWidget *parent = nullptr):QSlider(orientation, parent);
    explicit MySlider(QWidget *parent = nullptr):QSlider(parent)
        this->setStyleSheet("\
                            QSlider::groove:horizontal \
                                height: 8px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */ \
                                background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);\
                                margin: 2px 0;\
                            \
                            \
                            QSlider::handle:horizontal \
                                background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);\
                                border: 1px solid #5c5c5c;\
                                width: 18px;\
                                margin: -2px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */ \
                                border-radius: 3px;\
                            \
                        ");
    ;
protected:
    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 = std::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);
                
            
        

        QSlider::paintEvent(ev);
    
;

在QT Creator中,如果使用forms,需要将上面的文件添加到提升的widgets列表中,然后每个QSlider都需要提升才能使用这个类。

部分归功于:https://***.com/a/27535264/6050364

更新(2021 年 12 月):QT 在 QT 6.2.3 中修复了这个问题

【讨论】:

以上是关于QT 中的 QSlider 在新的 MacOS Monterey (v12.0.1) 中行为不端。任何解决方法?的主要内容,如果未能解决你的问题,请参考以下文章

sh 在新的macOS上设置/安装的事情

QT软件开发之基础控件--2.4.9 QSlider滑块

Debian系列-在新的GNOME下无法启动Qt

Debian系列-在新的GNOME下无法启动Qt

QSlider 和 QSpinBox 之间的 Qt 模型视图架构

GUI 编程 —— QT 的 QSlider 鼠标点击定位问题