Qt模仿Windows文件夾縮略圖的三種實現(xiàn)方式
1、簡介
本文講的不是簡單的model/view或者widget的或者QML的基礎框架實現(xiàn),而是在這些框架之上的肉(文件夾縮略圖)的效果實現(xiàn)。本文將以QWidget、Qt Quick(QML)、以及QGraph三種實現(xiàn)方式來講解,如何做出和Windows類似的縮略圖……
2、效果圖

乍一看,好像把兩個圖片立起來,然后做成一個類似Windows文件夾有點難。一步一步拆開來分解,貌似就不難了,無非就是4個透明圖層(底層、圖片1、圖片2、上層)的組合。
3、三種實現(xiàn)方式
QWidget最簡單,但缺點也很明顯,mask形成QBitmap遮罩沒有辦法去鋸齒,我們會看到明顯的鋸齒,在追求完美的coder中是不可取的,不過你做著玩當我沒說……
3.1、QWidget的mask遮罩
3.1.1、bb叨
初學者可能有點懵,怎么講著講著講到了遮罩,那是什么,和實現(xiàn)這個東西又有什么關聯(lián)呢?遮罩這個東西,用途比較廣泛,但猶豫無法去鋸齒,也很少有完美主義者選擇mask。mask可以用來做QWidget組件或者窗體的遮罩,有啥用?比如說想實現(xiàn)一個漩渦鳴人的窗體(ps:作者關注火影和海賊),很簡單就能實現(xiàn)。

那么除了漩渦鳴人本身,其他都是透明的,因為你有一個這樣的圖片,所以能很快就實現(xiàn)出來。如果需求反過來,想把漩渦鳴人的這個圖的輪廓作為背景圖,里面的內(nèi)容是你想的用圖案來填充呢?那就會用到mask遮罩??梢钥吹接忻黠@的鋸齒,那我們模仿windows文件夾縮略圖也一樣會出現(xiàn)這個問題,這個問題源于mask本身是qbitmap,qbitmap的鋸齒目前版本的Qt是沒解決方案的。

3.1.2、核心源碼

SMaskWidget
void SMaskWidget::updatePixmap(QPixmap sourcePix, QPixmap maskPix)
{
m_pixCurrent = sourcePix;
QBitmap bit = maskPix.mask();
this->setMask(bit);// 效果不好,QBitmap本身是有鋸齒的,機制問題
update();
}
void SMaskWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
painter.setPen(QPen(Qt::transparent));
painter.drawPixmap(0, 0, width(), height(), m_pixCurrent);
}
SPixmapWidget
SPixmapWidget::SPixmapWidget(QWidget *parent) : QWidget(parent)
{
m_down = new QLabel(this);
m_pixMask1 = new SMaskWidget(this);
m_pixMask2 = new SMaskWidget(this);
m_up = new QLabel(this);
m_down->setStyleSheet("border:0px solid red;background-color:transparent;");
m_up->setStyleSheet("border:0px solid red;background-color:transparent;");
}
void SPixmapWidget::updatePixmap(QPixmap pix1, QPixmap pix2)
{
QString str_mask_down = "E:/MyPro/TillDream/application/TillDream/sqrc/png/down__2x.png";
QString str_mask_up = "E:/MyPro/TillDream/application/TillDream/sqrc/png/up__2x.png";
QString str_bg_down = "E:/MyPro/TillDream/application/TillDream/sqrc/png/back2x.png";
QString str_bg_up = "E:/MyPro/TillDream/application/TillDream/sqrc/png/pre2x.png";
m_down->resize(QPixmap(str_bg_down).size());
m_up->resize(QPixmap(str_bg_up).size());
m_pixMask1->resize(QPixmap(str_mask_down).size());
m_pixMask2->resize(QPixmap(str_mask_up).size());
m_down->setPixmap(QPixmap(str_bg_down));
QPixmap mask1;
mask1.load(str_mask_down);
m_pixMask1->updatePixmap(pix1, mask1.scaled(QPixmap(str_mask_down).size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
QPixmap mask2;
mask2.load(str_mask_up);
m_pixMask2->updatePixmap(pix2, mask2.scaled(QPixmap(str_mask_up).size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
m_up->setPixmap(QPixmap(str_bg_up));
}
3.2、QML的QtGraphicalEffects遮罩
3.2.1、bb小叨
QML的發(fā)展一直是近幾年來Qt發(fā)展的趨勢,QML也發(fā)展的越來越好了,QML本身提供了對應的QtGraphicalEffects包,效果非常nice,而且代碼簡單。
3.2.2、核心源碼

import QtQuick 2.3
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Item {
visible: true
Item{
width: 104
height: 116
Image {
source: "file:///E:/MyPro/TillDream/application/TillDream/sqrc/png/back2x.png"
anchors.fill: parent
}
}
Item{
width: 104
height: 122
Image {
id: person
source: "file:///C:/Users/lenovo/Desktop/1.jpg"
anchors.fill: parent
visible: false
}
Image {
id: mask
source: "file:///E:/MyPro/TillDream/application/TillDream/sqrc/png/down__2x.png"
anchors.fill: parent
visible: false
}
OpacityMask {
id:om
anchors.fill: person
source: person
maskSource: mask
}
}
Item{
width: 80
height: 134
Image {
id: person2
source: "file:///C:/Users/lenovo/Desktop/2.jpg"
anchors.fill: parent
visible: false
}
Image {
id: mask2
source: "file:///E:/MyPro/TillDream/application/TillDream/sqrc/png/up__2x.png"
anchors.fill: parent
visible: false
}
OpacityMask {
anchors.fill: person2
source: person2
maskSource: mask2
}
}
Item{
width: 48
height: 134
Image {
source: "file:///E:/MyPro/TillDream/application/TillDream/sqrc/png/pre2x.png"
anchors.fill: parent
}
}
}
3.3、QGraph的三板斧
3.3.1、bb一小會兒
這里提了QWidget和QML的實現(xiàn),其實都不滿足我的需要。怎么說呢,QWidget的效果不是很好,顯而易見的鋸齒。QML效果雖好,但是整體的代碼都是用QWidget框架去寫的,如果要動態(tài)打包的話,再額外引用QML的動態(tài)鏈接庫,沒必要給程序總大小增加負擔。所以這里嘗試用QGraph的三板斧來實現(xiàn),具體不會QGraph的可以參考我的示例,也可以踩著搜索引擎去學習。
3.3.2、核心源碼

SGraphicsItem
QRectF SGraphicsItem::boundingRect() const
{
QRectF rf;
if (Type_down == m_type) {
rf = QRectF(0, 0, 104, 122);
} else if (Type_bg == m_type) {
rf = QRectF(0, 0, 104, 116);
} else if (Type_up == m_type) {
rf = QRectF(0, 0, 80, 134);
} else if (Type_pre == m_type) {
rf = QRectF(0, 0, 48, 134);
} else {
rf = QRectF(0, 0, 104, 134);
}
return rf;
}
void SGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
painter->setPen(QPen(Qt::transparent));
painter->setBrush(QBrush(m_color));
QPainterPath path;
QPolygonF ffl;
if (m_type == Type_down) {
ffl << QPointF(2.0, 2.0) << QPointF(boundingRect().width(), 16.0) << QPointF(boundingRect().width(), boundingRect().height()) << QPointF(2.0, 108.0);
path.addPolygon(ffl);
painter->setClipPath(path);
painter->drawImage(QRectF(0,0, boundingRect().width(), boundingRect().height()),QImage(m_pix));
} else if (Type_bg == m_type) {
painter->drawImage(QRectF(0,0, boundingRect().width(), boundingRect().height()),QImage(m_pix));
} else if (Type_up == m_type) {
ffl << QPointF(2.0, 2.0) << QPointF(boundingRect().width(), 28.0) << QPointF(boundingRect().width(), boundingRect().height()) << QPointF(2.0, 108.0);
path.addPolygon(ffl);
painter->setClipPath(path);
painter->drawImage(QRectF(0,0, boundingRect().width(), boundingRect().height()),QImage(m_pix));
} else if (Type_pre == m_type) {
painter->drawImage(QRectF(0,0, boundingRect().width(), boundingRect().height()),QImage(m_pix));
} else {
painter->drawRect(this->boundingRect());
}
}
control
QGraphicsScene* m_scene = new QGraphicsScene(ui->graphicsView);
SGraphicsItem *item1 = new SGraphicsItem(SGraphicsItem::Type_bg, str_bg_down);
SGraphicsItem *item2 = new SGraphicsItem(SGraphicsItem::Type_down, str_d1);
SGraphicsItem *item3 = new SGraphicsItem(SGraphicsItem::Type_up, str_d2);
SGraphicsItem *item4 = new SGraphicsItem(SGraphicsItem::Type_pre, str_bg_up);
m_scene->addItem(item1);
m_scene->addItem(item2);
m_scene->addItem(item3);
m_scene->addItem(item4);
ui->graphicsView->setSceneRect(0,0,104,134);
ui->graphicsView->setScene(m_scene);
ui->graphicsView->setStyleSheet("QGraphicsView{border:0px;background-color: rgba(255, 255, 255, 0);}");
QPixmap pix(QSize(104, 134));
pix.fill(Qt::transparent);
QPainter painter(&pix);
m_scene->render(&painter); //關鍵函數(shù)
pix.save("123.png", "PNG");
ui->label_new->setStyleSheet("background-color:rgb(123,123,123);");
ui->label_new->setPixmap(pix);
ui->label_new->setAlignment(Qt::AlignCenter);
以上就是Qt模仿Windows文件夾縮略圖的三種實現(xiàn)方式的詳細內(nèi)容,更多關于Qt文件夾縮略圖的資料請關注腳本之家其它相關文章!
相關文章
vc++ 監(jiān)控指定路徑下文件變化實現(xiàn)代碼
這篇文章主要介紹了vc++ 監(jiān)控指定路徑下文件變化實現(xiàn)代碼,需要的朋友可以參考下2019-04-04

