问:绘制完成后如何释放QPainterPath占用的内存?

时间:2012-12-03 01:38:12

标签: qt drawing qpainter

问题是:我想绘制由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 个答案:

答案 0 :(得分:0)

我找到了解决方案并与您分享。作为上面发布的示例代码,我在绘制之前删除了paintEvent函数中的QPainterPath,但它不起作用。所以我在跳转到paintEvent函数之前移动了删除操作,这可以释放QPainterPath占用的内存。感谢您的所有建议。 :)