2014-11-09 2 views
4

나는 방향을 사용하여 선을 그린 위치를 계산하는 눈금자 클래스 (Graduation)가 있습니다. 이 같은 : 방향이 Qt::Horizontal로 설정되어효과적으로 Qt에서 물리적으로 정확한 눈금자로 페인팅

enter image description here

내가 line_xpos = precendent_line_xpos + number을한다. 그런 다음 방향이 Qt::Vertical 인 경우 y 위치에 추가합니다.

나는 몇 가지 코드가있는 아래 내가 if...else?: 문이 작업을 수행하는 방법의 예입니다 있습니다 여기에

/* std::vector<QLineF> m_lines; */ 

void Graduation::resizeEvent(QResizeEvent *event) 
{ 
    qreal newLength = (m_orientation == Qt::Horizontal) 
     ? event->size().width() 
     : event->size().height(); 
    qreal oldLength = (m_orientation == Qt::Horizontal) 
     ? event->oldSize().width() 
     : event->oldSize().height(); 

    if(newLength != oldLength) { 
     if(newLength < oldLength) { /* Delete lines */ 
      int count = m_lines.size(); 
      if(count == 0) 
       return; 

      if(m_orientation == Qt::Horizontal) { 
       while(m_lines[count-1].x1() > newLength) { 
        --count; 
       } 
      } else { 
       while(m_lines[count-1].y1() > newLength) { 
        --count; 
       } 
      } 

      m_lines.erase(
       m_lines.begin()+count, 
       m_lines.begin()+m_lines.size() 
      ); 
     } else 
      /* ... Append lines ... */ 
    } 
} 

선이 그려집니다 방법을 보여 할 수있는 paintEvent은 다음과 같습니다

void Graduation::paintEvent(QPaintEvent *event) 
{ 
    Q_UNUSED(event) 

    QPainter painter(this); 
    painter.setPen(QPen(Qt::black, 0.5)); 

    for(unsigned int i = 0; i < m_lines.size(); ++i) 
     painter.drawLine(m_lines[i]); 
} 

수천 번 확인 된 조건을 지킬 수 있는지 알고 싶습니다. 어떤 코드 패턴을 사용하여 을 피할 수 있는지 관심이 있습니다 (라인 위치를 한 번만 계산하고 표시되는 것만 표시하는 것이 더 좋을 수도 있음).

+0

기능 포인터, 펑, 람다 – deviantfan

+0

@deviantfan. pointed 객체가 각 반복을 변경할 때 어떻게 m_lines [count-1] .x1()에서 함수 포인터를 사용할 수 있습니까? – Eliot545

+0

@ Eliot545 질문을 편집 해 주셔서 감사합니다. 이미지를 임베드했습니다 (더 많은 평판 포인트를 얻은 후에 직접 할 수 있습니다 ...). ['Length'] (http://en.wiktionary.org/wiki/length) 패턴이 규칙적이라면 라인 위치에 대한 각 쌍의 엔드 포인트를 저장하는 것이 필요하지 않습니다. 예 : 백만 픽셀 너비의 위젯은 모든 선을 벡터로 그릴 필요는 없습니다. * (사용자가 어떻게 든 움직일 수 없거나 이동할 장소가없는 한) * – HostileFork

답변

7

이미지를 게시 한 후에 훨씬 간단하고 효과적인 솔루션을 찾을 수있는 것처럼 보입니다.

라인이 반복 가능한 패턴을 형성하므로 전체를 그 으려 고 수동으로 라인을 관리하는 것은 낭비입니다. 당신은 작은 픽셀 맵을 생성하고이 같은 반복 패턴의 하나의 세그먼트를 그릴 수 있습니다 :

pattern

그런 다음 당신이 그것을 플립/그대로를 떠나거나 회전 할 수있는 방향에 따라. 그런 다음 QPainter을 사용하여 Graduation 위젯에 Qt::TexturePattern을 사용하여 QBrush::setTexture(pixmap)을 사용할 수 있으며 얼마나 많은 부분이 있더라도 패턴을 사용하여 전체 위젯 길이/높이를 빠르고 효율적으로 채울 수 있습니다.

눈금자의 스타일이나 간격을 변경하려면 캐시 된 패턴을 다시 그리는 것과 동일한 프로세스를 사용하여 눈금자를 업데이트해야합니다.

Qt가 제공하는 레이아웃을 사용하여 눈금자를 올바른 위치에 맞추어 자동으로 100 % 관리 할 수 ​​있으므로 현재 사용중인 논리가 중복됩니다.

OK, 여기 조금 더 도움이 될 것입니다. 그리고 이것은 선을 그리기 위해 각각의 모든 선을 가질 필요가 없다는 것을 보여줄 것입니다. 코드는 간단하고 주어진 DPI에 대한 패턴 세그먼트를 생성합니다 :

QPixmap drawCMPattern(qreal dpi) { 
    qreal dpcm = dpi/2.54; 
    QPixmap rulerCache(dpcm, dpcm/2); 
    rulerCache.fill(); 
    qreal dpmm = dpcm/10; 
    QPainter p(&rulerCache); 
    p.setRenderHint(QPainter::HighQualityAntialiasing); 
    qreal lineWidth = dpmm/5; 
    p.setPen(QPen(Qt::black, lineWidth)); 
    qreal xpos = lineWidth/2; 
    for (int i = 0; i < 10; ++i) { 
     if (i == 0) p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height())); 
     else if (i == 5) p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height()/2)); 
     else p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height()/4)); 
     xpos += dpmm; 
    } 
    return rulerCache; 
} 

보통 낮은 DPI 데스크톱 모니터에서는 라인이 약간 흐릿하게 들릴 수 있지만 "물리적으로 정확합니다"는 댓가로 지불해야하는 금액입니다. 메트릭 완벽하거나 완벽한 픽셀이며, 둘 다 가질 수는 없습니다 DPI가 미터 단위를 완벽하게 일치시키지 않으면 픽셀 사이에서 대부분의 선이 바인딩됩니다. 높은 DPI 모바일 장치에서는 나쁜 것처럼 보이지 않습니다.

HighQualityAntialiasing을 생략해도 선이 선명하지만 선이 동일한 거리에 있지 않을 수 있습니다.

PS ruler

PS 그러나 까다 롭습니다와 1cm의 작은 선이 너무 차이가로 타격으로되지 않습니다 : 그것은 포토샵과 같은 상용 소프트웨어에 대한 충분한 분명히 좋은 때문에 아직도, 이것은 당신을 위해 좋은 증명할 수 있습니다 각 mm마다 선이있을 때입니다. 여기에 그 코드의 결과가 내 108.79 DPI 바탕 화면에 모습입니다 :

this code

+0

잘 모르는이 기술에 감사드립니다. 그러나 내 마음 속에서 나는 눈금자를 cm와 인치로 교정해야하고 선은 위젯의 위쪽 가장자리, 중앙 또는 아래쪽 가장자리에 붙일 수 있고 가장 긴 줄에 숫자를 표시 할 수 있습니다. 당신이 제안하는 해결책이 가장 적합하지 않을 수도 있습니다. – Eliot545

+1

숫자를 그릴 때 다른 화가 패스를 추가하는 것이 더 효율적입니다. 눈금자가 물리적으로 정확하도록 캐시 픽스맵의 올바른 크기를 계산할 수 없습니다. – dtech

+0

좋습니다! 나는이 해결책을 시도 할 것이다. 고마워 ddriver. – Eliot545