首页 > 解决方案 > 如何在两条线之间画圆弧

问题描述

我当前的代码实现类似于所附图像。如何在垂直线(法线)和相交线(折射线和入射线)之间绘制弧线?我不知道该怎么做。弧必须更新以及折射线和入射线移动。这里的例子

void SnellsLawWidget::paintEvent(QPaintEvent* event)
{

    QPainter painter(this);

    painter.drawText(QPoint(width - 100, height / 2 + 20), "Interface");
    painter.drawText(QPoint(width / 2 + 10, 20), "Normal");


    painter.drawText(QPoint(100, height / 2 - 20), "n1");
    painter.drawText(QPoint(100, height / 2 + 30), "n2");

    painter.setPen(QPen(Qt::black, Qt::SolidLine));
    painter.drawLine(0, height / 2, width, height / 2);

    painter.setPen(QPen(Qt::green, Qt::DashLine));
    painter.drawLine(width / 2, 0, width / 2, height);

    QLineF incidenceLine;
    painter.setPen(QPen(Qt::red, Qt::SolidLine));
    incidenceLine.setP1(QPoint(width / 2, height / 2));
    incidenceLine.setAngle(qreal(angleOfIncidence) + angleOffset);
    incidenceLine.setLength(indexLength);
    painter.drawLine(incidenceLine);
    painter.drawText(QPoint(incidenceLine.x2(), incidenceLine.y2()), theta + QString("1"));

    QLineF refractiveLine;
    refractiveLine.setP1(QPoint(width / 2, height / 2));
    refractiveLine.setAngle(qreal(angleOfRefraction) - angleOffset);
    refractiveLine.setLength(indexLength);
    painter.drawText(QPoint(refractiveLine.x2(), refractiveLine.y2()), theta + QString("2"));
    painter.drawLine(refractiveLine);   
}

标签: c++qt

解决方案


QPainter::drawPie() 将起作用,现在实现它会很头疼。

我不太确定哪个细节会导致头痛。

关于QPainter::drawPie()有一些事情你必须注意:

  1. 矩形描述了绘制饼图的完整椭圆的范围。
    因此,如果ab是椭圆的水平和垂直半径,并且cx cy是中心点,则矩形必须是QRect(cx - a, cy - b, 2 * a, 2 * b)
  2. 有一个以 16 度为单位的startAngle 。
    如果角度 alpha 存储为浮点数,则 startAngle 可以通过 计算(int)(alpha * 16)
  3. spanAngle不是结束角度,而是作为第二个参数给出。跨度角是结束角和开始角的差。它也以 16 度数给出。
  4. 对于圆形饼图,只需将半径r用于ab
    圆只是椭圆的一个特例。

例子:

#include <QtWidgets>

class PieWidget: public QWidget {

  private:
    int _alpha, _omega; // start/end angle in degree

  public:
    PieWidget(QWidget* pQParent = nullptr):
      QWidget(pQParent)
    { }

    virtual ~PieWidget() = default;

    PieWidget(const PieWidget&) = delete;
    PieWidget& operator=(const PieWidget&) = delete;

    void setAngles(int alpha, int omega)
    {
      _alpha = alpha; _omega = omega;
      update();
    }

  protected:
    virtual QSize sizeHint() const override { return QSize(20, 20); }

    virtual void paintEvent(QPaintEvent* pQEvent) override;
};

void PieWidget::paintEvent(QPaintEvent* pQEvent)
{
  const int w = width(), h = height();
  QPainter qPainter(this);
  qPainter.setPen(Qt::blue);
  qPainter.setBrush(Qt::yellow);
  const int startAngle = _alpha * 16;
  const int spanAngle = (_omega - _alpha) % 360 * 16;
  qPainter.drawPie(0, 0, w, h, startAngle, spanAngle);
}

int main(int argc, char** argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  PieWidget qPie;
  qPie.setWindowTitle("QPainter::pie()");
  qPie.resize(256, 256);
  qPie.show();
  // setup animation
  QTimer qTimer;
  qTimer.setInterval(50); // 20/s seems reasonable
  int alpha = 0, omega = 0;
  QObject::connect(&qTimer, &QTimer::timeout,
    [&]() {
      qPie.setAngles(alpha, omega);
      alpha += 10; alpha %= 360;
      omega += 5; omega %= 360;
    });
  qTimer.start();
  // runtime loop
  return app.exec();
}

输出:

testQWidgetQPainterPie 的快照(GIF 动画)


推荐阅读