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

QDial pointer start position(value - 0) at top



  • Hello All,

    I want a qdial pointer with the start value(0 or 360) at the top. By default it appears at the bottom.
    6701ea17-6735-4368-b3eb-92b699cdba02-image.png
    So the pointer of the dial with value 0 should be at the green mark .
    Is there any flag to do so, or-else, I have do manual calculation with +/- 180 .

    Any suggestion is appreciated.

    Regards,
    Sayan


  • Moderators

    @sayan275
    here ya go:

    //.h
    #ifndef JHDIAL_H
    #define JHDIAL_H
    
    #include <QDial>
    
    class JhDial : public QDial
    {
        Q_OBJECT
        Q_PROPERTY(int adjustedValue READ adjustedValue WRITE setAdjustedValue NOTIFY adjustedValueChanged)
    public:
        explicit JhDial(QWidget *parent = nullptr);
    
        inline int adjustedValue() const { return m_adjustedValue; }
    
    signals:
        void adjustedValueChanged(int adjustedValue);
    
    public slots:
        void setAdjustedValue(int adjustedValue);
    
    private:
        int mapValueToRange(int y, int y_min, int y_max, int x_min, int x_max);
        void adjustValue(int value);
        int m_adjustedValue = -1;
    };
    
    #endif // JHDIAL_H
    
    
    //.cpp
    #include "jhdial.h"
    
    JhDial::JhDial(QWidget *parent) : QDial(parent)
    {
        connect(this, &QDial::valueChanged, this, &JhDial::adjustValue);
    
        setWrapping(true);
        setRange(0,360);
        setAdjustedValue(0);
    }
    
    void JhDial::setAdjustedValue(int adjustedValue)
    {
        if (m_adjustedValue == adjustedValue)
            return;
    
        if(adjustedValue < 180)
            setValue(mapValueToRange(adjustedValue,0,179,180,360));
        else
            setValue(mapValueToRange(adjustedValue,180,360, 0, 180));
    
    }
    
    int JhDial::mapValueToRange(int y, int y_min, int y_max, int x_min, int x_max)
    {
        return qRound((y-y_min)/static_cast<double>(y_max-y_min)*(x_max-x_min)+x_min);
    }
    
    void JhDial::adjustValue(int value)
    {
        if(value < 180)
            m_adjustedValue = mapValueToRange(value,0, 179, 180, 360);
        else
            m_adjustedValue = mapValueToRange(value,180, 360, 0, 180);
    
        emit adjustedValueChanged(m_adjustedValue);
    }
    
    

    You may have to adjust the borders for the mapping, so that they don't overlap, I mad this in a rush ;)
    you had to, cleaned it up a bit.


  • Lifetime Qt Champion

    Hi
    Did you try with
    alt text

    If that is not working with Dial then you have to do it manually.



  • This post is deleted!

  • Lifetime Qt Champion

    @sayan275
    Hi
    Ok you must have something that block images then.
    Anyway, it show the property
    "inverted appearance "
    that normally flips a slider to be reversed.
    But sadly it didn't work with 0-360 as the zero is still in the bottom.

    http://imagizer.imageshack.com/img922/2451/awXZvi.png



  • @mrjj sorry I got your posted image..its the property.
    dbfebf2e-5bc1-4907-89ed-a71b586dfc3d-image.png
    Yes it didn't work...I tried all possible combinations with the flags available.
    Can we rotated a widget? .. can't remember any api.
    Meanwhile I got the expected output by calculating with +/- 180

    //    if(value > 180)
    //        value -= 180;
    //    else if(value <= 180)
    //        value += 180;
    

    I didn't want to update the value in this manner.

    @mrjj Anyways thanks for your reply.


  • Lifetime Qt Champion

    @sayan275
    well we cant rotate a widget as such
    but we could subclass it and then flip the painter.
    If that works in terms of navigation, im not sure.

    void QDial::paintEvent(QPaintEvent *)
    {
        QStylePainter p(this);
        QStyleOptionSlider option;
        initStyleOption(&option);
        p.drawComplexControl(QStyle::CC_Dial, option);
    }
    
    

    use p and
    https://doc.qt.io/qt-5/qtwidgets-painting-transformations-example.html
    to flip it and see :)



  • @mrjj Thanks for the suggestion.
    I'll try out the overriding the paintEvent()



  • @sayan275 just in case, do you really need the dial to wrap?


  • Lifetime Qt Champion

    Hi
    Just as a note.

    void MyDial::paintEvent(QPaintEvent *event)
    {
        QStylePainter p(this);
        QStyleOptionSlider option;
        initStyleOption(&option);
        p.translate(0, height());
        p.scale(1.0, -1.0);
        p.drawComplexControl(QStyle::CC_Dial, option);
    }
    

    Did draw as we wanted and using keys (left , right ) moves it ok
    but click and drag with the mouse it jumps back to the old zero.

    So sadly was not a solution as navigation did went banans.



  • @Pablo-J-Rogina yes...we need to wrap...so that the starting and endpoints are similar.


  • Moderators

    @sayan275
    here ya go:

    //.h
    #ifndef JHDIAL_H
    #define JHDIAL_H
    
    #include <QDial>
    
    class JhDial : public QDial
    {
        Q_OBJECT
        Q_PROPERTY(int adjustedValue READ adjustedValue WRITE setAdjustedValue NOTIFY adjustedValueChanged)
    public:
        explicit JhDial(QWidget *parent = nullptr);
    
        inline int adjustedValue() const { return m_adjustedValue; }
    
    signals:
        void adjustedValueChanged(int adjustedValue);
    
    public slots:
        void setAdjustedValue(int adjustedValue);
    
    private:
        int mapValueToRange(int y, int y_min, int y_max, int x_min, int x_max);
        void adjustValue(int value);
        int m_adjustedValue = -1;
    };
    
    #endif // JHDIAL_H
    
    
    //.cpp
    #include "jhdial.h"
    
    JhDial::JhDial(QWidget *parent) : QDial(parent)
    {
        connect(this, &QDial::valueChanged, this, &JhDial::adjustValue);
    
        setWrapping(true);
        setRange(0,360);
        setAdjustedValue(0);
    }
    
    void JhDial::setAdjustedValue(int adjustedValue)
    {
        if (m_adjustedValue == adjustedValue)
            return;
    
        if(adjustedValue < 180)
            setValue(mapValueToRange(adjustedValue,0,179,180,360));
        else
            setValue(mapValueToRange(adjustedValue,180,360, 0, 180));
    
    }
    
    int JhDial::mapValueToRange(int y, int y_min, int y_max, int x_min, int x_max)
    {
        return qRound((y-y_min)/static_cast<double>(y_max-y_min)*(x_max-x_min)+x_min);
    }
    
    void JhDial::adjustValue(int value)
    {
        if(value < 180)
            m_adjustedValue = mapValueToRange(value,0, 179, 180, 360);
        else
            m_adjustedValue = mapValueToRange(value,180, 360, 0, 180);
    
        emit adjustedValueChanged(m_adjustedValue);
    }
    
    

    You may have to adjust the borders for the mapping, so that they don't overlap, I mad this in a rush ;)
    you had to, cleaned it up a bit.



  • @J-Hilk Thanks ...I tried this.


Log in to reply