2014-05-16 30 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更新數據,這是徹底bothersome.Currently,用而QListView改變模型中的數據非常簡單直接 - 我甚至可以即時更改使用的模型。

有沒有辦法實現項目的相同展望?也許有一種實施代表的模式,可能適用...

+0

你能更具體一點嗎?什麼包含你的QListView?你是否想要定製它的外觀(如你所提到的那樣在代表中)?如果你想添加「效果」,你可能會有一些已經運行的代碼,把它放在這裏肯定會幫助我們理解這個問題。 – Uflex

回答

1

通過以下問題的啓發:How to blur QPixmap image,我來到了以下解決方案:在代理中使用dropshadow過濾器的實現,而不是試圖在那裏使用QGraphicsEffect

所以,我來到的是:

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不在此列表中,因此即使您能夠從父控件訪問圖形效果實例,也更簡單,但無法訪問效果方法。所以,我認爲最好的方法(如果你需要模仿特定像素圖的效果)是創建自己的類,它將完成這項工作,而不是使用現有的效果。

另一種選擇顯然是適用於整個而QListView其中以某種方式將處理你的項目的影響,但我認爲這可能是相當棘手的執行

+0

我需要的效果根據項目的不同而不同 - 例如,在顏色上 - 根據項目的數據進行修改。 模仿效果 - 你是否建議在Qt中查看默認項目委託實現和qgraphiceffect實現? – Srv19

+0

那麼我會建議你不要堅持使用圖形效果..因爲在一天結束時它只是圖像處理和創建自己的實現 – evilruff

+0

他只需要使用QGraphicsScene渲染給定的pixmap與給定的效果,然後,當然,殺死效果,我發佈了代碼 –

1

讓我們爲這個主題做出貢獻。從Qt 5.3開始,以下函數將幫助您在申請QGraphicsEffectQImage(並且不會丟失alpha)時提供很多幫助。在應用模糊之後,只需將此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像素數的原始圖像的各方面,對陰影特別有用和模糊不被切斷。

相關問題