Press "Enter" to skip to content

Qt6 ColorOverlay 替代方案

Loading

Qt6 ColorOverlay

  

Qt6 ColorOverlay 替代方案

  我們公司的程式專案中有一個通用的小元件,它的功能是載入向量圖檔顯示,並在需要時可以繪製不同的顏色。當我們的專案還在 QT 5.X 版時很好實現,只要使用 QML 元件 ColorOverlay 就可以了。

  但是當我們把版本升級到 6.X 後,隨即發現 ColorOverlay 被移除掉了。我本來想說 Qt6 已經發行好多年了,應該早就有替代方案了吧,結果發現完全沒有類似的功能可以用,要達到相需求,只能另闢蹊徑。

走不通的路Shadereffect:

  在我剛開始尋找替代方案時,最常查到的有人說可以用 Shadereffect。那是一個可以直接使用 GLSL 語言來控制 QML 顯示畫面的元件(拿來做圖片顏色變更有點像用牛刀殺雞),因為看上去很合邏輯,我就嘗試了一下。

  但實際上這條路是行不通的,升級 Qt6 後 Shadereffect 也同樣有所變更。以前它允許在 QML 直接撰寫 GLSL,但改版後,需要把 GLSL 預先編譯成 .qsb 檔案,簡言之,它失去了在執行期間變更顏色的彈性,除非我預先把所有顏色都準備一份 .qsb。

  這顯然不符合我的需求,只能放棄這個想法(好笑的是就是因為升版了才需要這個,結果升了後反而不行),後來嘗試了第一種解法。

寫作 Button 讀作 ICON:

  我找到的第一個解決方案是利用 QML Button 系列元件(繼承 AbstractButton)擁有的 icon 屬性,這個屬性可以設定圖片的 source 跟 color 達到以特定顏色繪製圖片的功能。以下為我在 QML 封裝的元件 SvgImage。

Item {
    id: svgImage
    property alias color: btn.icon.color
    property alias source: btn.icon.source
    Button {
        id: btn
        anchors.centerIn: parent
        background: Item {}
        // 將背景換成空 Item,移除按鈕基本的按壓效果跟變色特效,單純顯示圖片。
        icon.width: parent.width
        icon.height: parent.height
    }
}

  這算是有達到我要的效果(吐槽一下,為什麼 Button 有這個功能但是 Image 元件沒有,莫名其妙)。但經我揣摩上意,覺得我主管可能不會接受這種塞著按鈕的圖片顯示器(不過我錯了,我主管更狠,他直接就用按鈕當圖框了,所以我們新程式現在顯示圖的地方都有按鈕變色特效,可能最新的 Material 風格就是這樣吧,我也不知道),所以我設計了第二種方法。

繼承 QQuickPaintedItem:

  QQuickPaintedItem 是一個繪製用的元件,透過 override paint( QPainter *painter ) 函數可以在元件上自由的繪圖。

  這個方案的原理是,利用 QSvgRenderer 物件讀取向量圖(.svg)後繪製到畫面上,再把繪製模式切換成 QPainter::CompositionMode_SourceAtop (官網相關說明),畫上一層顏色。

  因為這種模式下只有非透明像素會被繪製,所以如果繪製的圖形是只有 ICON 圖案的像素有顏色,其他透明的部分就不會被上色,達到置換圖形顏色的效果。以下只列出比較關鍵的 paint function 的 Code。

void SVGImage::paint( QPainter *painter )
{
    if(  !qSvgRenderer.isValid()  ) // 確認 QSvgRenderer 已經讀入圖片。
        return;

    painter->setRenderHint( QPainter::SmoothPixmapTransform, true );

    qSvgRenderer.render( painter, boundingRect() );

    painter->setCompositionMode( QPainter::CompositionMode_SourceAtop );

    painter->fillRect( boundingRect(), m_Color );
}

注意事項:

  我在測試碰到兩個問題,一併記錄在此。

  在讀取資源檔(.qrc)圖片時(我沒有測試存在硬碟裡的狀況),Button 的 icon 只接受 URL;而 QSvgRenderer 只接受 Path,如果你希望設定 source 時不要有限制,則需要額外判斷處理。
  
  加入資源檔的圖片沒有被正確包入執行檔中,在專案 cmake file 添加 set(CMAKE_AUTORCC ON) 解決(但這個錯誤不一定會發生)。

  研究證實,歡笑可以延壽,換言之,讓你捧腹不已的我的文章可以延壽,建議多看。歡迎透過側欄粉絲團或下方作者介紹欄按鈕訂閱,好文章不漏接,期待繼續與您以文相會。也歡迎留個言,讓我在寫作這條路上不覺孤單!

#ColorOverlay #QT6 #QML #基本元件 #UI

好文章應與世界一同分享

Leave a Reply