简体   繁体   English

QPainter 需要更多时间来绘制更粗的曲线?

[英]QPainter takes much more time to draw thicker curves?

I am drawing a sine wave (as a test) to check the time it takes to draw a curve using either QPainter::drawPolyline() or QPainter::drawPath() .我正在绘制一个正弦波(作为测试)来检查使用QPainter::drawPolyline()QPainter::drawPath()绘制曲线所需的时间。 In either case, if I set the pen width to more than 1, then the time it takes to draw the sine wave increases by more than 10 times.无论哪种情况,如果我将笔宽设置为大于 1,则绘制正弦波所需的时间将增加 10 倍以上。

Widget::Widget(QWidget* parent)
    : QWidget(parent)
{
    setAutoFillBackground(true);
    setAttribute(Qt::WA_NoSystemBackground, true);
    
    // creating the sine wave
    for(qsizetype ii = 0; ii < 1000000; ++ii)
        sineWave << (1.0 + sin(2 * M_PI * 3 * ii / 1000000));
}

void Widget::paintEvent(QPaintEvent* evt)
{
    QPainter painter(this);
    painter.fillRect(rect(), QColor(Qt::white));
    painter.setRenderHint(QPainter::Antialiasing);

    QPen pen;
    pen.setWidthF(2); // setting pen width
    painter.setPen(pen);

    QElapsedTimer timer;
    timer.start();

    qDebug() << "-> Paint Event\tPen Width:" << pen.widthF() << "\tWidget WxH:" << width() << "x" << height();

    QList<QPointF> pixPoints;
    for(qsizetype ii = 0; ii < sineWave.length(); ++ii) {
        double yPos = height() * (sineWave[ii] / 2.0);
        double xPos = width() * (ii / 1000000.0);
        pixPoints << QPointF(xPos, yPos);
    }
    qDebug() << "--> 1: Time [ms]:" << (timer.nsecsElapsed() / 1000000.0);
    painter.drawPolyline(pixPoints);
    qDebug() << "--> 2: Time [ms]:" << (timer.nsecsElapsed() / 1000000.0);
}

The output when I set the pen width = 2当我设置pen width = 2时的输出

-> Paint Event  Pen Width: 2    Widget WxH: 722 x 494
--> 1: Time [ms]: 109.352
--> 2: Time [ms]: 5887.08

The output when I set the pen width = 1我设置pen width = 1时的输出

-> Paint Event  Pen Width: 1    Widget WxH: 741 x 535
--> 1: Time [ms]: 105.882
--> 2: Time [ms]: 233.165

The time taken for creating the QList<QPointF> pixPoints in both cases is the similar (marked as 1: ), but the time it takes to draw the curve using QPainter::drawPolyline() function (marked as 2: ) is extremely high when I set the pen width to 2 compared to when the pen width is set to 1.两种情况下创建QList<QPointF> pixPoints所用的时间相似(标记为1: ),但使用QPainter::drawPolyline()函数绘制曲线所需的时间(标记为2: )非常高当我将笔宽设置为 2 时,与笔宽设置为 1 时相比。

Is there any way I could reduce this time gap?有什么办法可以减少这个时间差吗?

PS I have posted the same question on Qt Forum here PS我在这里的Qt论坛上发布了同样的问题

(moving from comments) (从评论移动)

It's normal... a single pixel-wide pens have a specific "easy" algorithm, while fat pens essentially require building a region (calculating joints correctly) and then doing a polyfill.这很正常......单个像素宽的笔具有特定的“简单”算法,而胖笔本质上需要构建一个区域(正确计算关节)然后进行填充。

Those times are very high, though, and that's expected due to the high number of points you are painting, way too many for your target resolution.但是,这些时间非常长,这是可以预期的,因为您正在绘制大量点,对于您的目标分辨率来说太多了。 To speed this up you should probably sample your sine wave at a period that is sensible for the required size of your widget.为了加快速度,您可能应该在对您的小部件所需大小合理的时间段内对您的正弦波进行采样。 Once you have one point per target pixel (or IDK 4 if you really want to put antialiasing under stress) you are good.一旦每个目标像素有一个点(如果您真的想将抗锯齿置于压力之下,则为 IDK 4),您就很好了。 You can just calculate it on the fly in your paint event (and saving ~8 MB of points in memory for something you can easily recalculate is a bad idea anyhow).您可以在您的绘画事件中即时计算它(并且在内存中为您可以轻松重新计算的东西节省约 8 MB 的点无论如何都是一个坏主意)。

void Widget::paintEvent(QPaintEvent* evt)
{
    QPainter painter(this);
    painter.fillRect(rect(), QColor(Qt::white));
    painter.setRenderHint(QPainter::Antialiasing);

    QPen pen;
    pen.setWidthF(2); // setting pen width
    painter.setPen(pen);

    QElapsedTimer timer;
    timer.start();

    qDebug() << "-> Paint Event\tPen Width:" << pen.widthF() << "\tWidget WxH:" << width() << "x" << height();

    double periods = 3.;
    int w = width(), h = height();
    QList<QPointF> pixPoints;
    for (int x = 0; x < w; ++x) {
        double alpha = double(x) / w * 2 * M_PI * periods;
        points << QPointF(x, (1. + sin(alpha)) / 2 * h);
    }
    qDebug() << "--> 1: Time [ms]:" << (timer.nsecsElapsed() / 1000000.0);
    painter.drawPolyline(pixPoints);
    qDebug() << "--> 2: Time [ms]:" << (timer.nsecsElapsed() / 1000000.0);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM