Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Custom drawn QSlider



  • I'm working on porting an app from MFC to Qt. One of the main controls in our app is a custom drawn CSliderCtrl. It has a bunch of custom functionality that the standard slider can not duplicate, but we use slider as the base class because at it's core it's just a thumb that slides back and forth along a track.

    Does anyone know of any examples or tutorials for creating custom controls in Qt? This is the slider I need to recreate...

    7baed6b9-9fcd-470d-8514-637d9cf0a90c-image.png

    As you can see it has a multi color track, a custom thumb and special markers that can be added along the rack. (these are not ticks and can be anywhere along the track)


  • Moderators

    I can't offer any ready made tutorial but there's not much to it really.
    Depending on how low level you need to go subclass either QSlider or the base QAbstractSlider.
    Paint your custom markers in the overriden paintEvent using QPainter.
    Handle adding, moving and removing custom markers in mouse related event overrides: mousePressEvent, mouseReleaseEvent and mouseMoveEvent.



  • Hi, for a project a needed a QSlider that looked like a slider on a musician's mixer table, here's the code I used:

    void  MainWindow::customizeSlider(QWidget* pSlider, QColor c, int nWidthInPixels, int nHeightInPixels)
    {
        static int nnBorderWidth  = 1;
        static int nnBorderRadius = 7;  // for nice rounded corners
        static QColor ccBorder("grey");
        static int nnLineWidth    = 2;
        static int nnMidLineWidth = 0;
    
    // will the real QSlider* please stand up (use a safe downcast)
        QSlider* pRealSlider = dynamic_cast<QSlider*>(pSlider);
        if (nullptr == pRealSlider)
            return; // no QSlider* present, so skip this
    
    // construct and set the style sheet (2 parts, one for the groove and one for the handle)
        pRealSlider->setStyleSheet(QString(
            ".QSlider::groove { background: transparent; height: %1px; } "
            ".QSlider::handle { background: %2; border-radius: %3px; border: %4px solid %5; width: %6px;}")
            .arg(nHeightInPixels).arg(c.name()).arg(nnBorderRadius).arg(nnBorderWidth).arg(ccBorder.name()).arg(nWidthInPixels));
    
    // need to recreate the QSlider's groove? (the original is now invisible due to the stylesheet applied above)
        QString sFrameObjectName = pRealSlider->objectName() + "Frame";  // we'll be using a QFrame
        if (nullptr == pRealSlider->parentWidget()->findChild<QFrame*>(sFrameObjectName))
        {
        // yes, so wire up a new QFrame to act as a surrogate groove, use the same parent and geometry as the slider
            QFrame* pFrame = new QFrame(pRealSlider->parentWidget());
            pFrame->setGeometry(pRealSlider->geometry());
            pFrame->setObjectName(sFrameObjectName);
            pFrame->setFrameStyle(((Qt::Horizontal == pRealSlider->orientation()) ? QFrame::HLine : QFrame::VLine) | QFrame::Sunken);
            pFrame->setLineWidth(nnLineWidth);
            pFrame->setMidLineWidth(nnMidLineWidth);
    
        // finally, change the z-order so that our custom groove is drawn under the handle (just like the real groove)
            pFrame->stackUnder(pRealSlider);
        }
    }
    

    This code might help you create the custom thumb and the special markers, and even the multiple colors, you can try applying them where I create the groove above. Good luck!



  • Forgot, here's a screenshot:
    CustomSliders.png


Log in to reply