2016-12-15 69 views
2

由於大多數熟悉QML的人都知道,QML Image中沒有內置的「刷新」功能。使用更新功能擴展QML圖像類型

我想創建一個新的QML類型,例如RefreshableImage來緩解這個問題,而不是訴諸於改變源代碼,我覺得它是一個醜陋的黑客,因爲它滲入到模型 - 視圖關係的所有層中,並且這種切換行爲是不自然的。此外,在Image上設置不同的source會破壞可能已設置的任何綁定(這實際上是問題的核心:我想要一個可更新的圖像來維護其綁定,並與QML隔離)。我知道我需要調用一些信號來實際刷新圖像,這很好。

我很難找到一種方式來擴展Qt自己的Image,以便我可以強制它重新加載它的源文件。我想避免編寫一個完整的組件,其中大部分很難複製Image以添加一個函數。有沒有辦法擴展一個內置的組件,就像我腦海中所想的那樣?

小筆記:

  • 到外部環境原因,我僅限於Qt的5.5。
  • 我們以source的形式使用底層圖像對象的UUID,QQuickImageProvider使用該UUID來獲取實際的QImage。因此,我不想在更新圖像時更改此設置。
+0

爲什麼你需要用相同的'source'等來更新'Image'?這是不是相同的圖像? – folibis

+0

@folibis技術上是的,但底層的數據已經改變。我們使用QML ImageProviders從我們的數據結構中提供QML到QML。我們使用的id是我們系統中圖像的uuid,所以我們可以從該uuid的其他地方檢索實際的對象。爲了簡單起見,我們只是重複使用這個uuid。 – rubenvb

+0

好的,你應該在問題中指定這個。我想這很重要。 – folibis

回答

3

您可以創建一個RefreshableImage類型來隱藏醜陋的源代碼。

有通過引入新的屬性源做的一個簡單的方法:

import QtQuick 2.0 

Image { 
    id: root 
    property string refreshableSource 
    source: refreshableSource 
    function refresh() { 
     source = ""; 
     source = Qt.binding(function() { return refreshableSource }); 
    } 
} 

你必須使用它這樣的:RefreshableImage { refreshableSource: "image.jpg" }

如果你想仍然使用source作爲一個屬性,你可以做一些別名shenanigans。由於只有在組件完全初始化後才能激活別名,因此可以覆蓋Imagesource屬性,但仍可以訪問底層的屬性。

import QtQuick 2.0 

Image { 
    id: root 
    property alias actualUnderlyingSource: root.source //this refers to Image.source and not the newly created source alias 
    property alias source: root.refreshableSource 
    property string refreshableSource 
    actualUnderlyingSource: refreshableSource 
    function refresh() { 
     actualUnderlyingSource = ""; 
     actualUnderlyingSource = Qt.binding(function() { return refreshableSource }); 
    } 
} 

然後,您可以使用它像這樣RefreshableImage { source: "image.jpg" },這將在事實上改變refreshableSource財產

+0

有沒有我可以添加一些底層C++來將其連接到實際的圖像對象嗎?在中,我可以用C++擴展QML Image嗎?我猜ImageRefresher C++/QML組件/對象的組合會使這成爲可能嗎?我希望它聽取/觀察附加到所討論的uuid的對象。謝謝! – rubenvb

0

粗略骨架直接使用的QImage從模型與註冊自定義項目

class DirectImage : public QQuickPaintedItem 
{ 
    Q_OBJECT 
    Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged) 

public: 
    void paint(QPainter *painer); 
    void setImage(const QImage &image); 
}; 

void DirectImage::paint(QPainter *painter) 
{ 
    painter->drawImage(m_image.scaled(width(), height()): 
} 

void DirectImage::setImage(const QImage &image) 
{ 
    m_image = image; 
    emit imageChanged(); 
    setImplicitWidth(image.width()); 
    setImplicitHeight(image.height()); 
    update(); 
} 

通過

qmlRegisterType<DirectImage>("MyElements", 1, 0, "RefreshableImage"); 

通過使用

import MyElements 1.0 

// ... 

RefreshableImage { 
    image: model.image 
} 

模型僅返回QImage當問及對圖像的作用,發出dataChanged()信號與圖像的角色,每當圖像變化。

如果需要根據需要生成圖像,那麼模型可以首先返回空圖像或佔位符圖像,並在實際內容可用時發出dataChanged()信號。