Would you like to react to this message? Create an account in a few clicks or log in to continue.

You are not connected. Please login or register

Rotary encoder

2 posters

Go down  Message [Page 1 of 1]

1Rotary encoder  Empty Rotary encoder Thu Aug 04, 2022 9:56 pm

feri



I would like the QDial of the rotary encoder not to move when clicked with the mouse but only when it is dragged.
There is a way to get this into a QDial.
Greetings

2Rotary encoder  Empty Re: Rotary encoder Fri Aug 05, 2022 3:06 pm

arcachofo

arcachofo

Maybe installing an event filter to catch the MousePressEvent and ignore it.

3Rotary encoder  Empty Re: Rotary encoder Sat Aug 06, 2022 11:29 pm

feri



I tried like this:

Code:

bool KY040::eventFilter(QObject *object, QEvent *event)
{
    bool ret = false;
    if ( object == m_dial &&  ( event->type() == QEvent::MouseButtonPress )  ) {
        QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event);
        if(mouseEvent->buttons() == Qt::LeftButton) {
           //QStyleOptionSlider *opt = new QStyleOptionSlider;
           QStyleOptionComplex *opt = new QStyleOptionComplex;
           opt->initFrom(m_dial);
           QRect sr = m_dial->style()->subControlRect(QStyle::CC_Dial, opt, QStyle::SC_DialHandle, m_dial);
           qDebug() << sr;
           if (!sr.contains(mouseEvent->pos())){
              event->ignore();
              ret = true;
              qDebug() << "LEFT";
           }
        }
    }
    return ret;
}

The filter works but the rectangle of the indicator circle is empty, the method I copied from the code found on the internet for QSlider and QScrollBar.

Code:

    QStyleOptionSlider *opt = new QStyleOptionSlider;
    opt->initFrom(scrollBar1);
    
    QRect r = scrollBar1->style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSubLine);

I tried to fit it to QDial but it gives an empty rectangle and I get this message:
"QCommonStyle::subControlRect: Case 6 not handled"

Greetings

4Rotary encoder  Empty Re: Rotary encoder Sun Aug 07, 2022 12:54 am

arcachofo

arcachofo

Ignoring the press events is simple:
Code:
bool KY040::eventFilter( QObject *object, QEvent *event )
{
    bool ret = true;
    if( object == m_dial && event->type() == QEvent::MouseButtonPress )
    {
        QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event);
        if(mouseEvent->buttons() == Qt::LeftButton) ret = false;
    }
    return ret;
}
But this does not avoid the dial to move to mouse position (even ignoring the release event also).

The only solution I can think is reimplementing QDial and find out how to do by looking at QDial source code.
Maybe filtering Mouse move event and implementing something there could work as well.

5Rotary encoder  Empty Re: Rotary encoder Thu Sep 01, 2022 5:05 pm

feri



I was unable to reimplement QDial but I did this:

Code:

bool KY040::eventFilter(QObject *object, QEvent *event)
{
    bool ret = false;
    int sliderpos = m_dial->sliderPosition();
    if (sliderpos == maximum) sliderpos = 0;
    if ( object == m_dial &&  ( event->type() == QEvent::MouseButtonPress )  ) {
        QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event);
        int frompoint = valueFromPoint(mouseEvent->pos());
        if (frompoint == maximum) frompoint = 0;
        if(mouseEvent->buttons() == Qt::LeftButton) {
          // qDebug() << valueFromPoint(mouseEvent->pos()) << m_dial->sliderPosition();
          if (sliderpos != frompoint) {
              event->ignore();
              ret = true;
          }
          else event->accept();
        }
    }
    return ret;
}

int KY040::valueFromPoint(const QPoint &p)
{
    double yy = m_dial->height()/2.0 - p.y();
    double xx = p.x() - m_dial->width()/2.0;
    double a = (xx || yy) ? std::atan2(yy, xx) : 0;
    if (a < (Q_PI / -2))
        a = a + Q_PI * 2;
    int dist = 0;
    int minv = minimum, maxv = maximum;
    if (minimum < 0) {
        dist = -minimum;
        minv = 0;
        maxv = maximum + dist;
    }
    int r = maxv - minv;
    int v;
    if (wrapping)
        v =  (int)(0.5 + minv + r * (Q_PI * 3 / 2 - a) / (2 * Q_PI));
    else
        v =  (int)(0.5 + minv + r* (Q_PI * 4 / 3 - a) / (Q_PI * 10 / 6));
    if (dist > 0)
        v -= dist;
    return !invertedAppearance ? bound(v) : maximum - bound(v);
}

int KY040::bound(int val)
{
    if (wrapping) {
        if ((val >= minimum) && (val <= maximum))
            return val;
        val = minimum + ((val - minimum) % (maximum - minimum));
        if (val < minimum)
            val += maximum - minimum;
        return val;
    } else {
        return qMax(minimum, qMin(maximum, val));
    }
}

Greetings

6Rotary encoder  Empty Re: Rotary encoder Thu Sep 01, 2022 7:06 pm

arcachofo

arcachofo

I was unable to reimplement QDial but I did this:
Nice, I will try it.

Sponsored content



Back to top  Message [Page 1 of 1]

Permissions in this forum:
You cannot reply to topics in this forum