0

問題は、USBデバイスから生成された入力データ(データサイズが50MBを超える)から計算された多くの線を描きたいということです。QPainterPath::lineTo と QPainterPath::moveTo 関数を使用して線を描画すると、パフォーマンスが悪くメモリが解放されないようです。

私の環境は、8G RAM と Qt 4.7.2 を搭載した Windows 7 です。

たとえば、データサイズが 50MB の場合、占有メモリは 200MB になります。前回の描画が終了し、アプリケーションが次回描画できるようになると、200MB は解放されません。そのため、何度も描画すると、アプリケーションがクラッシュします。void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointCount, PolygonDrawMode モード) の例外ポイント:

// Draw all the line segments.
for (int i=1; i<pointCount; ++i) {

    QPointF lp1 = points[i-1] * s->matrix + offs;  //  error here, the point is NULL
    QPointF lp2 = points[i] * s->matrix + offs;    //  error here, the point is NULL

    const QRectF brect(lp1, lp2);
    ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
    if (qpen_style(s->lastPen) == Qt::SolidLine) {
        drawLine_midpoint_i(qFloor(lp1.x()), qFloor(lp1.y()),
                            qFloor(lp2.x()), qFloor(lp2.y()),
                            penBlend, &s->penData,
                            i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
                            devRect);
    } else {
        drawLine_midpoint_dashed_i(qFloor(lp1.x()), qFloor(lp1.y()),
                                   qFloor(lp2.x()), qFloor(lp2.y()),
                                   &s->lastPen,
                                   penBlend, &s->penData,
                                   i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
                                   devRect, &dashOffset);
    }
}

ちなみに、描画前に QPainterPath の削除操作を行っているのですが、ここではうまくいかないようです。誰かがそれについて何か考えを持っていますか? ありがとう。

以下は私の描画コードです:

    int scaleFactor;
    double old_x, current_x;
    int current_y, oldval, newval, x_change_visible, tmp_x, tmp_y;
    int low = m_ui->renderAreaWidget->height() - 2, high = 20;
    int ch = getChannelNumber();
    uint64_t ss, se;

    if (sample_buffer == NULL)
        return;

    scaleFactor = getScaleFactor();

    if (painterPath != NULL)
        delete painterPath;
    if (dottedPath != NULL)
        delete dottedPath;
    if (textPath != NULL)
        delete textPath;

    dottedPath = new QPainterPath();
    painterPath = new QPainterPath();
    textPath = new QPainterPath();

    old_x = (getScrollBarValue() % stepSize);
    current_x = (getScrollBarValue() % stepSize);

    ss = (getScrollBarValue() + current_x) * scaleFactor / stepSize;
    se = ss + (getScaleFactor() * width()) * stepSize;
    if (se > getNumSamples()) // Do this _after_ calculating 'step'!
        se = getNumSamples();

    oldval = getbit(sample_buffer, ss, ch);
    current_y = (oldval) ? high : low;
    painterPath->moveTo(current_x, current_y);
    // add dummy line to indicate something
    if (ss < 100 && (isSetTriggerCondition || pretriggerPercent < 100)) {
        QPen pen;
        pen.setStyle(Qt::DotLine);
        bool textDrawed = false;

        bool isTextDrawed = false;
        for (int i = ss; i < 100; i += scaleFactor) {
            if (i >= 50 && i <= 60 && !isTextDrawed && pretriggerPercent != 100) {
                QFont font;
                //font.setFamily("Times");
                //font.setItalic(true);
                font.setPixelSize(18);
                textPath->addText(current_x, low + 1, font, QString("Pre-trigger %1%").arg(pretriggerPercent));

                isTextDrawed = true;
            }

            for (int j = 0; (j < scaleFactor) && (i + j < 100); j++) {
                dottedPath->lineTo(current_x, low);
                current_x += (double)stepSize / (double)scaleFactor;
            }
        }
        zeroX = current_x;
    }

    //current_x = (-getScrollBarValue() % stepSize);
    bool isTriggered = false;
    int oldy = current_y;
    painterPath->moveTo(current_x - ((double)stepSize / (double)scaleFactor), low);
    painterPath->lineTo(current_x, low);
    painterPath->lineTo(current_x, current_y);
    for (uint64_t i = ss; i < se; i += scaleFactor) {
        //Process the samples shown in this step.
        for (uint64_t j = 0; (j < scaleFactor) && (i + j < se); j++) {
           newval = (i + j < numSamples ? getbit(sample_buffer, i + j, ch): newval); // sample buffer is the data buffer, size is about 50M. getbit function is about to determine the specific byte in target channel is high or low.
            x_change_visible = current_x > old_x;
            if (oldval != newval && x_change_visible) {
                painterPath->lineTo(current_x, current_y);
                current_y = (newval) ? high : low;
                if (current_y != oldy && !isTriggered) {
                    isTriggered = true;
                    emit(triggerValue(getChannelNumber(), i));
                }
                painterPath->lineTo(current_x, current_y);
                old_x = current_x;
                oldval = newval;
            }
            current_x += (double)stepSize / (double)scaleFactor;
            oldy = current_y;
        }
    }
    current_x += stepSize;
    painterPath->lineTo(current_x, current_y);

各データ サンプルは 1 バイトで、その値に応じて高電圧または低電圧としてそれぞれを描画します。

4

1 に答える 1

0

解決策を見つけて、あなたと共有しました。上に載せたサンプルコードのように、描画前にpaintEvent関数内のQPainterPathを削除したのですが、うまくいきません。したがって、paintEvent 関数にジャンプする前に削除アクションを移動すると、QPainterPath が占有するメモリを解放できます。ご提案いただきありがとうございます。:)

于 2012-12-04T07:06:53.533 に答える