簡體   English   中英

QPainter 需要更多時間來繪制更粗的曲線?

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

我正在繪制一個正弦波(作為測試)來檢查使用QPainter::drawPolyline()QPainter::drawPath()繪制曲線所需的時間。 無論哪種情況,如果我將筆寬設置為大於 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);
}

當我設置pen width = 2時的輸出

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

我設置pen width = 1時的輸出

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

兩種情況下創建QList<QPointF> pixPoints所用的時間相似(標記為1: ),但使用QPainter::drawPolyline()函數繪制曲線所需的時間(標記為2: )非常高當我將筆寬設置為 2 時,與筆寬設置為 1 時相比。

有什么辦法可以減少這個時間差嗎?

PS我在這里的Qt論壇上發布了同樣的問題

(從評論移動)

這很正常......單個像素寬的筆具有特定的“簡單”算法,而胖筆本質上需要構建一個區域(正確計算關節)然后進行填充。

但是,這些時間非常長,這是可以預期的,因為您正在繪制大量點,對於您的目標分辨率來說太多了。 為了加快速度,您可能應該在對您的小部件所需大小合理的時間段內對您的正弦波進行采樣。 一旦每個目標像素有一個點(如果您真的想將抗鋸齒置於壓力之下,則為 IDK 4),您就很好了。 您可以在您的繪畫事件中即時計算它(並且在內存中為您可以輕松重新計算的東西節省約 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