2014-10-23 29 views
1

위젯이 스타일 시트를 사용하고 있다면 위젯에서 클리핑을 사용할 수 있습니까? painEvent?Qt에서 클리핑 사용하기

제 질문에 대한 배경과 이유는 위젯이 나타나고 사라질 때 애니메이션으로 만들고 싶습니다. (크기 조정 원이나 사각형과 같은 것이 센터에서 작은 영역으로 시작하면 커집니다.)

이 문제를 해결하는 방법에 대한 저의 첫 번째 생각은 QPainter의 클리핑을 사용하여 필요한 영역 만 그렸습니다.

위젯의 배경을 투명하게 만들고 기본 도면 기능을 QPainter에서 사용하면 잘 동작합니다. 하지만 위젯에 스타일 시트가 적용된 경우이를 어떻게 해결할 수 있습니까? 심지어 가능할까요?

  • 그것이 내가 언급 한 전략 원하는 것을 얻을 수있다 :

    사용 된 Qt는 버전

    내 질문은 Qt는 4.8.6인가?

  • 어떤 방식으로도 모든 어린이를 클립핑 할 수 있습니까?
  • 내 전략이 적절합니까 아니면 그렇게 나쁜 생각입니까?
  • 내가 원하는 것을 줄 수있는 다른 아이디어, 모범 사례, Qt 클래스가 있습니까? 나는이 클리핑 것들로 붙어 있기 때문에

추가 정보

나는 보여주기별로 코드가 있습니다. 하지만 여기에 제가 시도한 것에 대한 아이디어를 얻을 수있는 것이 있습니다 :

이것은 작동합니다.

/* Shows a small red circle inside the widget as expected */ 
void MyAnimatingWidget::paintEvent(QPaintEvent *ev) { 
    QPainter painter(this); 
    QRect rect = this->geometry() 
    QStyleOption opt; 

    painter.setClipRegion(QRegion(rect.width()/2, 
            rect.height()/2, 
            150, 150, 
            QRegion::Ellipse)); 
    painter.setPen(QColor(255, 0, 0)); 
    painter.setBrush(QColor(255, 0, 0)); 
    painter.setOpacity(1); 

    painter.drawRect(rect); 
} 

하지만 아무것도 변경되지 않습니다 다음 : 나는 전혀 style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); 줄을 제거하더라도, 스타일 시트도 그려지는 것을,

/* This shows the widget as usual */ 
void MyAnimatingWidget::paintEvent(QPaintEvent *ev) { 
    QPainter painter(this); 
    QRect rect = this->geometry(); 
    QStyleOption opt; 

    painter.setClipRegion(QRegion(rect.width()/2, 
            rect.height()/2, 
            150, 150, 
            QRegion::Ellipse)); 
    painter.setRenderHint(QPainter::Antialiasing); 
    painter.setOpacity(1); 

    opt.init(this); 
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); 
} 

이 또한 내가 눈치 챘을.

+1

[애니메이션 프레임 워크] (http://qt-project.org/doc/qt-5/animation-overview.html)를 확인 했습니까? – thuga

+0

QAnimation과 친구들은 애니메이션 자체에 대한 것입니다 (시간이 지남에 따라 가치가 변함). 하지만 내 문제는 애니메이션에없는 드로잉 (현재는)에 있습니다. – exilit

+0

사용중인 Qt의 버전을 알려 주셔야합니다. – user1095108

답변

1

위젯에 적용한 스타일 시트는 기본적으로 제공되는 OS 관련 스타일 위젯을 덮어 씁니다. 심지어 Windows를 사용하고 싶지만 여전히 스타일 시트를 사용하려는 경우 문제가 발생할 수 있습니다. 어쨌든 Qt 소스 디렉토리에서 각 스타일의 역할을 확인할 수 있습니다 : src/gui/styles. style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);를 들어, 코드 읽기 :

case PE_Widget: 
    if (w && !rule.hasDrawable()) { 
     QWidget *container = containerWidget(w); 
     if (styleSheetCaches->autoFillDisabledWidgets.contains(container) 
      && (container == w || !renderRule(container, opt).hasBackground())) { 
      //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now. 
      // (this may happen if we have rules like :focus) 
      p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole())); 
     } 
     break; 
    } 

당신이 클리핑이 어떤 식 으로든에 참견하지 않는 볼 수 있도록 클립 영역을 설정 당신의 생각은 작동해야한다. 이제 그림의 신비를 위해서. 배경 그림은 void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, QPainter *sharedPainter, QWidgetBackingStore *backingStore)에서 호출되는 void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const에서 발생합니다. 코드는 /src/gui/kernel/qwidget.cpp에서 찾을 수 있습니다. 관련 코드는 다음과 같습니다.

if (q->testAttribute(Qt::WA_StyledBackground)) { 
    painter->setClipRegion(rgn); 
    QStyleOption opt; 
    opt.initFrom(q); 
    q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q); 
} 

어쩌면 속성을 끄면 도움이 될까요? 제 대답에서 끌어 내려야 할 기본 교훈은 소스 다이빙에 익숙해지는 것입니다.Qt의 아이디어는 구현 세부 사항에 신경 쓰지 않고 컨트롤을 인스턴스화하는 데는 좋지만 실제로는 실제로 작동합니다. 즉, 종종 소스 다이빙을해야합니다.

는 예를 들어, 당신이 픽스맵로 캡처 할 수 있습니다, 임의의 클립 영역에 위젯의 아이를 클립하려면

QPixmap pixmap(widget->size()); 
widget->render(&pixmap); 

그리고 수동으로 픽스맵을 그립니다. 또한 (setUpdatesEnabled() 또는 숨기기를 통해) 자동으로 다시 칠하는 것을 방지 한 다음 paintEvent 핸들러를 수동으로 render에 호출 할 수 있습니다.

+0

공과를 가져 주셔서 감사합니다. 아직 시도하지는 않았지만, 여기에 보이는 접근 방식이 도움이되어 허용 된 답변으로 표시해야합니다. – exilit

+0

이곳에서 한 가지 질문 : 어떻게 관련 출처를 찾았습니까? 그냥 grepping하는거야? 그렇다면 grep/search는 무엇을 했습니까? 가능한 한 자주 코드로 '뛰어 들기'위해 노력하고 있지만 종종 실패한 검색으로 끝납니다. 그래서 어떻게 만들었습니까? – exilit

+1

@exilit 나는 자주 예배를 드렸습니다. 많은 다이빙을 마친 후에 관심있는 것이 어디에 있는지 알게됩니다. 그러나 다이빙은 처음에는 협박을합니다. 'find -t f -name "* .cpp"|을 시도해보십시오. xargs grep ' – user1095108