2012-12-03 169 views
-1

問題是:我想繪製許多由USB設備生成的輸入數據(數據大小超過50MB)計算的行。如果我使用QPainterPath :: lineTo和QPainterPath :: moveTo函數繪製線條,看起來性能很差,內存不會被釋放。Qt:[已解決]如何在繪圖結束後釋放QPainterPath佔用的內存?

我的環境是:具有8G RAM和Qt 4.7.2的Windows 7。

例如,如果數據大小爲50MB,則佔用的內存將爲200MB。當前一個繪圖完成並且應用程序準備下一次繪製時,200MB將不會被釋放。所以如果我畫很多次,應用程序會崩潰。 空隙QRasterPaintEngine的異常點:: strokePolygonCosmetic(常量QPointF *點,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

@Arnold Spence:我使用windonw任務管理器來監視內存資源。 – Xavier

回答

0

我找到了解決方案並與您分享。正如我上面發佈的示例代碼,我在繪製之前刪除了paintEvent函數中的QPainterPath,但它不起作用。所以我在跳轉到paintEvent函數之前移動了刪除操作,這可以釋放QPainterPath佔用的內存。感謝您的所有建議。 :)

相關問題