2012-12-03 2 views
-1

USB 장치에서 생성 된 입력 데이터 (50MB 이상의 데이터 크기)로 계산 된 많은 선을 그려야합니다. QPainterPath :: lineTo 및 QPainterPath :: moveTo 함수를 사용하여 선을 그리면 성능이 좋지 않으며 메모리가 해제되지 않는 것으로 보입니다.Qt : [해결] 그리기가 끝나면 QPainterPath가 차지하는 메모리를 해제하는 방법은 무엇입니까?

내 환경은 다음과 같습니다. Windows 7 (8G RAM 및 Qt 4.7.2).

예를 들어 데이터 크기가 50MB이면 점유 된 메모리는 200MB가됩니다. 이전 도면이 완료되고 응용 프로그램이 다음에 그릴 준비가되면 200MB가 해제되지 않습니다. 따라서 여러 번 그릴 경우 응용 프로그램이 중단됩니다. 무효 QRasterPaintEngine에서 예외 포인트 : strokePolygonCosmetic (const를 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 바이트와 나는 값의 각 하나 개의 높은 전압 또는 낮은 전압 의존립니다.

+1

어떻게 메모리 사용량을 측정하고 있습니까? –

+0

자신 만의 코드를 보여줄 수 있습니까? –

+0

@Arnold Spence : 저는 windonw task manager를 사용하여 메모리 리소스를 모니터링합니다. – Xavier

답변

0

솔루션을 찾은 다음 공유했습니다. 위에 게시 한 샘플 코드는 paint하기 전에 paintEvent 함수의 QPainterPath를 삭제하지만 작동하지 않습니다. 그래서 나는 paintEvent 함수로 점프하기 전에 delete 액션을 움직 였고, 이것은 QPainterPath가 점유 한 메모리를 해제 할 수 있습니다. 귀하의 모든 제안에 감사드립니다. :)

관련 문제