2015-04-08 527 views
3

我想在QML創建與內陰影的矩形,什麼Photoshop做類似的事情:QML內陰影效果

enter image description here

QMLInnerShadow但我無法達到這種效果。我得到最接近的是這

import QtQuick 2.0 
import QtGraphicalEffects 1.0 

Item { 
    id: root 
    width: 300 
    height: 300 

    Rectangle { 
     id: myRectangle 
     anchors.centerIn: parent 
     width: 100 
     height: 100 
     color: "grey" 
    } 

    InnerShadow { 
     anchors.fill: root 
     cached: true 
     horizontalOffset: 0 
     verticalOffset: 0 
     radius: 16 
     samples: 32 
     color: "#b0000000" 
     smooth: true 
     source: root 
    } 
} 

這是我從this後得到的想法。然而這個例子只有在root的尺寸比myRectangle大很多時纔有效,我不想那樣做。我需要一個200x10正方形,其中陰影均勻分佈在矩形的邊緣。我嘗試了InnerShadow屬性的各種值,但我無法接近我想要的效果。

這可以通過使用QML來實現嗎?

+0

貌似QML的內心陰影的實現非常蹩腳,我的猜測是「由圖形設計中沒有背景的程序員完成的」。您可以嘗試使用自定義GLSL着色器實現該效果。 – dtech

+0

你只需要兩個像素的偏移量來獲得正確的內部陰影,這不是「顯着更大」,但肯定是醜陋的。將它與根的顏色結合起來不起作用?如果不是,着色器是你唯一的朋友。 – BaCaRoZzo

+1

因爲您沒有回答我以前的建議,所以我重複一下自己的照片。怎麼樣[這樣的事情](http://i59.tinypic.com/sqgrcx.png)? – BaCaRoZzo

回答

2

「正確」的方法 - 引號需要引號 - 使用的效果應該是這樣:

import QtQuick 2.0 
import QtGraphicalEffects 1.0 

Item { 
    id: root 
    width: 300 
    height: 300 

    Item { 
     id: src 
     anchors.fill: parent 

     Rectangle { 
      id: myRectangle 
      anchors.centerIn: parent 
      width: 100 
      height: 100 
      color: "grey" 
     } 
    } 

    InnerShadow { 
     anchors.fill: src 
     cached: true 
     horizontalOffset: 0 
     verticalOffset: 0 
     radius: 16 
     samples: 32 
     color: "#b0000000" 
     smooth: true 
     source: src 
    } 
} 

正如你可以看到它是從另一個問題提出的解決方案略有不同。使用此代碼,您仍然需要保留2個像素,才能產生效果,從而產生白色邊框(或任何背景顏色)。通過將root更改爲Rectangle可以輕鬆解決問題。

最終的解決方案如下。顯然,您可以提取root組件(及相關子項),並將其放入Component或另一個.qml文件中以備後用。

import QtQuick 2.4 
import QtQuick.Window 2.2 
import QtGraphicalEffects 1.0 

Window { 
    width: 200 
    height: 20 
    visible: true 

    Rectangle {  // was Item 
     id: root 
     anchors.fill: parent 
     color: "grey" 


     Item { 
      id: src 
      anchors.fill: parent 

      Rectangle { 
       id: myRectangle 
       anchors.centerIn: parent 
       width: root.width - 2 
       height: root.height - 2 
       color: "lightgrey" 
      } 
     } 

     InnerShadow { 
      anchors.fill: src 
      cached: true 
      horizontalOffset: 0 
      verticalOffset: 0 
      radius: 16 
      samples: 32 
      color: "#b0000000" 
      smooth: true 
      source: src 
     } 
    } 
} 

用於最終的代碼示例所得窗口:

enter image description here

+1

似乎執行是不合邏輯的。如果源爲myRectangle,則它不適用於偏移量0,但如果添加偏移量,則會出現神祕的效果。所以你必須使用「代理」項目。而且,如果您嘗試執行更復雜的操作,比如將其應用於「複合」項目,它看起來越來越尷尬。 – dtech

+1

永遠不要說我喜歡它......確實我把臭名昭着的引號放在「正確」的位置。原始代碼被提議作爲在討論中使用效果的方式發送到郵件列表。您可以在其他問題評論中找到鏈接。實施必須是不合邏輯的,以促成這種奇怪的用法。但是,你知道,儘管不合邏輯,但我們仍應該找到一種方法。 :) – BaCaRoZzo

+1

我寧願更喜歡「預期的行爲」。執行的情況就是這樣,由知道如何使用說photoshop的人完成。不幸的是,在Qt中,開發是高度分區的,導致API中的許多古怪事物並非「所有關於編程」。 – dtech

0

的在內陰影元件是最喜歡在QML圖形效應元件GLSL着色的,並且它找到邊緣的方法是通過尋找透明與不透明之間的轉換。如果將濾鏡應用於完全固定的圖形元素,則不會找到任何邊緣,因此不會出現陰影。這與Photoshop濾鏡的工作方式完全相同,它還通過掃描邊緣從透明到非透明(如您提供的示例)來查找邊緣。它可能會將圖形區域的邊緣視爲隱式邊緣,但這會極大地限制可用性。以下是InnerShadow的來源。根據fast屬性,它又使用FastInnerShadowGaussianInnerShadow

如果你想,你可以只添加到現有元素,而不必在乎有你可以使用這個透明和非透明邊緣之間的轉換的實現:

Rectangle { 
    id: myRectangle 
    anchors.centerIn: parent 
    width: 300 
    height: 300 
    color: "#AAAAAA" 
} 
Item { 
    id: _innerShadow 
    property var shadowSource: myRectangle 
    property var color: "#B0000000" 
    anchors.fill: shadowSource 
    Item { 
     id: _shadowMarker 
     //width: source.width+1; height: source.height+1 
     anchors.fill: parent; 
     anchors.margins: -10 
     ColorOverlay { 
      anchors.fill: _shadowMarker; 
      anchors.margins: 10 
      source: _innerShadow.shadowSource 
      color: "#00000000" 
     } 
     visible: false 
    } 
    InnerShadow { 
     anchors.fill: _shadowMarker 
     cached: true 
     horizontalOffset: 0 
     verticalOffset: 0 
     radius: 16 
     samples: 32 
     color: _innerShadow.color 
     smooth: true 
     source: _shadowMarker 
    } 
}