Преглед изворни кода

gradient controls more smooth

Nicolas Winkler пре 5 година
родитељ
комит
a0ef843376
2 измењених фајлова са 81 додато и 7 уклоњено
  1. 61 2
      GradientWidget.cpp
  2. 20 5
      GradientWidget.h

+ 61 - 2
GradientWidget.cpp

@@ -153,7 +153,7 @@ void GradientWidget::paintEvent(QPaintEvent* e)
     int index = 0;
     for (auto& [point, color] : points) {
         QRect r = getHandleRect(index);
-        QStyleOptionButton so;
+        /*QStyleOptionButton so;
         so.init(this);
         so.rect = r;
         if (dragging && selectedHandle == index)
@@ -168,7 +168,15 @@ void GradientWidget::paintEvent(QPaintEvent* e)
             so.state &= ~QStyle::State_MouseOver;
         
         so.palette.setColor(QPalette::ColorRole::Button, color);
-        style()->drawControl(QStyle::ControlElement::CE_PushButton, &so, &painter, this);
+        style()->drawControl(QStyle::ControlElement::CE_PushButton, &so, &painter, this);*/
+        int hs = HandleState::HANDLE_NORMAL;
+        if (dragging && selectedHandle == index)
+            hs |= HANDLE_DOWN;
+        if (mouseOver == index)
+            hs |= HANDLE_MOUSEOVER;
+        if (selectedHandle == index)
+            hs |= HANDLE_SELECTED;
+        paintHandle(painter, r, color, hs);
         index++;
     }
     /*for (auto&[point, color] : points) {
@@ -198,6 +206,39 @@ void GradientWidget::paintEvent(QPaintEvent* e)
 }
 
 
+void GradientWidget::paintHandle(QPainter& painter, const QRectF& pos,
+                                 QColor c, int handleState)
+{
+    const float lineWidth = 2;
+    QPainterPath qpp = createSlideHandle(pos.width() - lineWidth, pos.height() - lineWidth);
+    qpp.translate(pos.x() + lineWidth / 2, pos.y() + lineWidth / 2);
+    if (handleState & HANDLE_SELECTED) {
+        QColor absLighter;
+        absLighter.setHsvF(c.hueF(), c.saturationF(), c.valueF() > 0.3 ? c.valueF() : 0.3);
+        painter.setPen(QPen(QBrush(absLighter.lighter(130)), lineWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+    } else
+        painter.setPen(QPen(QBrush(c.darker(200)), lineWidth / 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+
+    painter.setRenderHint(QPainter::Antialiasing);
+    QLinearGradient bevel{ 0, pos.top(), 0, pos.bottom() }; // top down linear gradient
+
+    if (handleState & HANDLE_DOWN) {
+        bevel.setColorAt(0, c.darker(120));
+        bevel.setColorAt(1, c.lighter(120));
+    }
+    else if (handleState & HANDLE_MOUSEOVER) {
+        bevel.setColorAt(0, c.lighter(130));
+        bevel.setColorAt(1, c.darker(110));
+    }
+    else {
+        bevel.setColorAt(0, c.lighter(120));
+        bevel.setColorAt(1, c.darker(120));
+    }
+    painter.fillPath(qpp, QBrush(bevel));
+    painter.drawPath(qpp);
+}
+
+
 void GradientWidget::mousePressEvent(QMouseEvent* e)
 {
     int handle = handleAtPos(e->pos());
@@ -375,3 +416,21 @@ float GradientWidget::gradValToHandleY(float v) const
     return area.top() + v * area.height();
 }
 
+
+QPainterPath GradientWidget::createSlideHandle(float w, float h)
+{
+    const float rounding = 4;
+    QPainterPath qpp;
+    QPolygonF qpf;
+    qpf << QPointF{ 0, 0.5 * h }
+        << QPointF{ 0.3 * w, h };
+    qpp.moveTo(0, 0.5 * h);
+    qpp.lineTo(0.3 * w, h);
+    qpp.arcTo(w - rounding, h - rounding, rounding, rounding, -90, 90);
+    qpp.arcTo(w - rounding, 0, rounding, rounding, 0, 90);
+    qpp.lineTo(0.3 * w, 0);
+    qpp.lineTo(0, 0.5 * h);
+
+    return qpp;
+}
+

+ 20 - 5
GradientWidget.h

@@ -3,6 +3,7 @@
 
 #include <QWidget>
 #include <QLinearGradient>
+#include <QPainterPath>
 #include <QVector>
 #include <QPair>
 
@@ -21,6 +22,16 @@ class GradientWidget :
     int handleWidth = 40;
     int handleHeight = 24;
 public:
+
+    enum HandleState
+    {
+        HANDLE_NORMAL = 0x00,
+        HANDLE_MOUSEOVER = 0x01,
+        HANDLE_DOWN = 0x02,
+        HANDLE_SELECTED = 0x04
+    };
+
+
     explicit GradientWidget(QWidget *parent = nullptr);
 
     const QVector<QPair<float, QColor>>& getGradient(void) const;
@@ -28,12 +39,13 @@ public:
 
     QColor colorAtY(float y);
 
-    void paintEvent(QPaintEvent* e) override;
+    virtual void paintEvent(QPaintEvent* e) override;
+    virtual void paintHandle(QPainter& painter, const QRectF &pos, QColor c, int handleState);
 
-    void mousePressEvent(QMouseEvent* e) override;
-    void mouseReleaseEvent(QMouseEvent* e) override;
-    void mouseMoveEvent(QMouseEvent* e) override;
-    void mouseDoubleClickEvent(QMouseEvent* e) override;
+    virtual void mousePressEvent(QMouseEvent* e) override;
+    virtual void mouseReleaseEvent(QMouseEvent* e) override;
+    virtual void mouseMoveEvent(QMouseEvent* e) override;
+    virtual void mouseDoubleClickEvent(QMouseEvent* e) override;
 
     QSize minimumSizeHint(void) const override;
     QSize sizeHint(void) const override;
@@ -53,6 +65,9 @@ protected:
 
     float handleYToGradVal(float y) const;
     float gradValToHandleY(float v) const;
+
+private:
+    static QPainterPath createSlideHandle(float w, float h);
 signals:
 
 };