2014-05-16 10 views
0

QListView의 목록 항목의 픽스맵에 그래픽 효과를 적용하고 싶습니다.QListView의 이미지에 그래픽 효과를 적용하려면 어떻게해야합니까?

어떻게해야합니까?

내가 아는 한, 내 자신의 대리인을 만들어야합니다. 하지만 QGraphicsEffect를 어떻게 사용합니까?

업데이트.

QListWidget을 사용하는 경우 다음 효과를 얻을 수 있습니다. 모든 목록 항목에 대한 위젯을 만들고 원하는 QGraphicsEffect를 적용합니다.

class PortraitViewWidget : public QFrame 
{ 
    Q_OBJECT 

public: 
    explicit PortraitViewWidget(QWidget* parent = nullptr) 
{ 
    auto imageView = new QWidget(); 
    auto imageViewLayout = new QVBoxLayout(); 
    auto imageLabel = new QLabel(); 
    auto textLabel = new QLabel(); 

    // test defaults 
    imageLabel->setPixmap(QPixmap("/Lenna.png")); 
    imageLabel->setScaledContents(true); 

    static qreal quality = 0.f; 
    quality += 0.1752f; 

    if(quality > 1.f) 
     quality = 1.f; 

    textLabel->setText(QString("%1%").arg(quality * 100.f, 0, 'f', 1)); 
    textLabel->setAlignment(Qt::AlignCenter); 
    textLabel->setStyleSheet(
     "QLabel {" 
     " background-color: white;" 
     " color: black;" 
     " font-size: 16px;" 
     " padding: 2px; }"); 

    imageViewLayout->addWidget(imageLabel); 
    imageViewLayout->addWidget(textLabel); 

    imageViewLayout->setMargin(0); 
    imageViewLayout->setSpacing(0); 
    imageViewLayout->setContentsMargins(0, 0, 0, 0); 

    imageView->setLayout(imageViewLayout); 

    auto effect = new QGraphicsDropShadowEffect(); 
    effect->setBlurRadius(55); 
    effect->setOffset(0.f); 
    effect->setColor(Qt::green); 

    imageView->setGraphicsEffect(effect); 

    imageView->setSizePolicy(
     QSizePolicy::Expanding, 
     QSizePolicy::Expanding); 

    imageView->setMinimumSize(240, 320); 
    imageView->setMaximumSize(480, 640); 

    auto layout = new QVBoxLayout(); 
    layout->addWidget(imageView); 
    layout->setMargin(25); 

    setLayout(layout); 
} 

}; 

을하지만,이 경우에 나는 또한 거의 손으로 contnts을 반영하기 위해 위젯에 데이터를 업데이트 구현해야하며,이 QListView 변화와 함께, bothersome.Currently 철저하다 :이 위젯은 (예를 들어) 같이 갈 것 모델의 데이터는 간단하고 직관적이며, 사용 된 모델을 즉시 변경할 수도 있습니다.

항목의 동일한 전망을 달성하는 방법이 있습니까? 어쩌면 적용 할 수있는 대리자를 구현하는 패턴이 있습니다.

+0

좀 더 구체적으로 말씀해 주시겠습니까? 귀하의 QListView가 무엇입니까? 보이는대로 사용자 정의 하시겠습니까? (언급 한대로 위임자에게 표시됩니다)? "효과"를 추가하려면 이미 실행중인 코드가있을 수 있으며 여기에 일부 코드를 넣으면 확실하게 문제를 이해하는 데 도움이됩니다. – Uflex

답변

1

될 수 있다고 생각 : How to blur QPixmap image, 나는 다음에 와서 해결 방법 : QGraphicsEffect을 사용하는 대신 대리자에서 dropshadow 필터 구현을 사용하십시오.

그럼, 내가 도착하는이 있었다 :

QT_BEGIN_NAMESPACE 
    extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); 
QT_END_NAMESPACE 

#define RADIUS 20 

void 
GalleryDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const 
{ 
    if(option.decorationSize.isValid() && 
     (option.decorationPosition == QStyleOptionViewItem::Top)) 
    { 

     painter->save(); 

     QPixmap decoration(index.data(Qt::DecorationRole).value<QPixmap>()); 

     //1. paint background 
     painter->fillRect(option.rect, option.backgroundBrush); 
     //2. make image with shadow 
     QRect src(QPoint(0, 0), option.decorationSize); 
     src.translate(RADIUS, RADIUS); 
     QRect dst(src.adjusted(-RADIUS, -RADIUS, RADIUS, RADIUS + option.fontMetrics.height())); 

     QImage tmp(dst.size(), QImage::Format_ARGB32_Premultiplied); 
     tmp.fill(0); 
     QPainter tmpPainter(&tmp); 
     tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); 
     tmpPainter.fillRect(src.adjusted(-3, -3, 3, 3 + option.fontMetrics.height() * 1.2), Qt::white); 

     QRect textRectangle(RADIUS, src.bottom(), 
      tmp.width() - 2 * RADIUS, tmp.height() - src.bottom() - RADIUS); 

     tmpPainter.end(); 

     // blur the alpha channel 
     QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); 
     blurred.fill(0); 
     QPainter blurPainter(&blurred); 
     qt_blurImage(&blurPainter, tmp, RADIUS*1.5f, false, true); 
     blurPainter.end(); 

     tmp = blurred; 

     // blacken the image... 
     tmpPainter.begin(&tmp); 
     tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); 
     tmpPainter.fillRect(tmp.rect(),Qt::green); 
     tmpPainter.end(); 

     // draw the blurred drop shadow... 
     painter->drawImage(option.rect.topLeft(), tmp); 

     // Draw the actual pixmap... 
     painter->drawPixmap(src.translated(option.rect.topLeft()), 
      decoration.scaled(src.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); 

     //4. draw text under it 
     painter->fillRect(textRectangle.adjusted(0, 2, 0, -2).translated(option.rect.topLeft()), Qt::white); 
     painter->drawText(textRectangle.translated(option.rect.topLeft()), Qt::AlignCenter, 
      index.data(Qt::DisplayRole).toString()); 

     if(option.state & QStyle::State_Selected) 
     { 
      QPen highlight(Qt::magenta, 5); 
      QRect border(option.rect); 
      border.adjust(3, 3, -3, -3); 
      painter->setPen(index.data(Qt::red); 
      painter->drawRoundedRect(border, 5.f, 5.f); 
     } 

     painter->restore(); 
    } 
    else 
     QStyledItemDelegate::paint(painter, option, index); 
} 

QPixmapDropShadowFilter 구현에서 가져 흐림을 수행하는 코드의 대부분.

0

음, 대답은 - QGraphicsEffect를 대리자 클래스에 사용하는 것이 좋습니다. Qt는 QGraphicsEffect를 특정 컨트롤이 그린 방법과 실제 그래픽 장치 사이의 파이프 라인으로 사용한다는 점이 다릅니다.

은 그 기본 클래스를 의미 - QGraphicsEffect 자체 내에서 여러 친구들의 효과가 활성화 '되어, Qt는 클래스 선언

class QGraphicsEffect { 
.... 
private: 
... 
    friend class QGraphicsItem; 
    friend class QGraphicsItemPrivate; 
    friend class QGraphicsScenePrivate; 
    friend class QWidget; 
    friend class QWidgetPrivate; 
... 

을};

사실 이러한 선언은 드로잉 루프 내에서 자체 동작을 수정하기 위해 그래픽 효과의 보호 된 메서드에 해당 클래스가 액세스 할 수 있음을 의미합니다. 다른 방법으로 말하면 자신을 그리기 전에 효과 필터에 자신의 모습을 전달합니다.

QAbstractItemDelegate가이 목록에 없기 때문에 상위 컨트롤에서 그래픽 효과 인스턴스에 액세스 할 수있는 경우에도 효과 메서드에 액세스 할 수있는 방법이 없습니다.

그래서, 최선의 방법은 (특정 pixmap에 대한 효과를 모방해야하는 경우) 기존의 효과를 사용하는 대신 작업을 수행 할 자체 클래스를 만드는 것입니다.

또 다른 옵션은 특정한 방식으로 당신에게 항목을 처리합니다 전체 QListView에 효과를 적용 분명하지만, 나는 그것이 매우 어려운 구현 다음과 같은 질문에 영감을

+0

품목별로 차이가있는 효과가 필요합니다. 예를 들어, 품목 데이터의 색상을 제외하는 경우. 효과를 모방합니다. Qt에서 기본 항목 위임 구현과 qgraphiceffect 구현을 살펴 보시겠습니까? – Srv19

+0

글쎄, 그래픽 효과를 고집하지 말라고 제안 할 것입니다. 하루가 끝나면 이미지 처리 만하고 자신의 구현을 만듭니다. – evilruff

+0

그는 QGraphicsScene을 사용하여 주어진 효과를 가진 주어진 pixmap을 렌더링 한 다음 그 결과를 죽일 필요가 있습니다. 효과, 그 코드를 게시 –

1

이 주제에 기여해 보겠습니다. Qt 5.3부터 함수를 따르면 QGraphicsEffectQImage에 적용하면 도움이 될 것입니다.흐림 효과를 적용한 후 원하는대로 컨테이너에 QImage을 추가합니다. 이미지를 흐리게이 기능을 사용하여

QImage applyEffectToImage(QImage src, QGraphicsEffect *effect, int extent = 0) 
{ 
    if(src.isNull()) return QImage(); //No need to do anything else! 
    if(!effect) return src;    //No need to do anything else! 
    QGraphicsScene scene; 
    QGraphicsPixmapItem item; 
    item.setPixmap(QPixmap::fromImage(src)); 
    item.setGraphicsEffect(effect); 
    scene.addItem(&item); 
    QImage res(src.size()+QSize(extent*2, extent*2), QImage::Format_ARGB32); 
    res.fill(Qt::transparent); 
    QPainter ptr(&res); 
    scene.render(&ptr, QRectF(), QRectF(-extent, -extent, src.width()+extent*2, src.height()+extent*2)); 
    return res; 
} 

그들

은 간단하다 :

물론
QGraphicsBlurEffect *blur = new QGraphicsBlurEffect; 
blur->setBlurRadius(8); 
QImage source("://img1.png"); 
QImage result = applyEffectToImage(source, blur); 
result.save("final.png"); 

,이 유용성의 단지 예이고, 저장 할 필요가 없습니다. 심지어 그림자 삭제할 수 있습니다 :

QGraphicsDropShadowEffect *e = new QGraphicsDropShadowEffect; 
e->setColor(QColor(40,40,40,245)); 
e->setOffset(0,10); 
e->setBlurRadius(50); 
QImage p("://img3.png"); 
QImage res = applyEffectToImage(p, e, 40); 

을 그리고 범위 매개 변수를주의, 그것은 그림자에 특히 유용 원본 이미지의 모든면, 픽셀의 extent 수를 추가하고 수 없습니다 차단을 흐리게합니다.