?我們需要實現一個垂直進度條效果,但使用圖片裁剪的方式。具體需求: 1. 圖片位置固定,容器對齊其左邊和下邊,寬度和圖片相同。 2. 容器背景透明,調整裁剪容器的高度,使其有高度進度條的感覺(從下往上增長)。 實現思路: - 固定圖片的位置(例如,在某個Item內定位)。 - 創建一個裁剪容器,寬度與圖片相同,高度由進度值控制(從0到圖片高度)。 - 裁剪容器內放置圖片,并將圖片的底部與裁剪容器的底部對齊(因為進度是從下往上增長,所以圖片需要向上移動)。 - 裁剪容器設置`clip: true`,這樣圖片超出裁剪容器的部分將被隱藏。 具體步驟: 1. 用一個Item作為圖片的容器(固定位置)。 2. 在容器內,再創建一個Item作為裁剪容器(寬度與圖片相同,高度由進度值控制)。 3. 裁剪容器內放置圖片,并設置圖片的y坐標為:-(圖片高度 - 裁剪容器高度),這樣圖片的底部就會與裁剪容器的底部對齊。 注意:圖片的錨定或位置設置要確保底部對齊。 假設我們有一張高度為200px的圖片,進度為50%時,裁剪容器高度為100px,此時圖片的y坐標應為-100px(即向上移動100px),這樣圖片的底部就對齊了裁剪容器的底部,而裁剪容器只顯示圖片的下半部分(從下往上顯示了一半)。 我們將通過一個進度值(0.0到1.0)來控制裁剪容器的高度(0到圖片高度)。
import QtQuick 2.7
import QtQuick.Controls 1.4import QtQuick.Controls.Styles 1.4
ApplicationWindow {id: mainWindowwidth: 800height: 600visible: truetitle: "圖片裁剪進度條 - 修正版"color: "#121212"// 圖片源 - 使用漸變圖片模擬進度條property string imageSource: "qrc:/image/a.png"// 進度值 (0.0 - 1.0)property real progress: 0.5// 圖片屬性property int imageWidth: 50property int imageHeight: 200// 主布局Item {anchors.fill: parent// 狀態信息 - 顯示在頂部Text {anchors.top: parent.topanchors.horizontalCenter: parent.horizontalCenteranchors.topMargin: 20text: "圖片裁剪進度條 - 固定在左下角"font.bold: truefont.pixelSize: 18color: "#4CAF50"}// ==============================================// 圖片容器 - 固定在左下角 (核心修正部分)// ==============================================Item {id: imageContainerwidth: imageWidth // 寬度與圖片相同height: imageHeight // 高度與圖片相同anchors.left: parent.left // 對齊父元素左邊anchors.bottom: parent.bottom // 對齊父元素底邊anchors.margins: 20 // 邊距// 背景網格 - 幫助可視化Rectangle {anchors.fill: parentcolor: "transparent"border.color: "#333"border.width: 1// 網格線Canvas {anchors.fill: parentonPaint: {var ctx = getContext("2d")ctx.clearRect(0, 0, width, height)ctx.strokeStyle = "#333"ctx.lineWidth = 1// 繪制水平線for (var y = 0; y <= height; y += 10) {ctx.beginPath()ctx.moveTo(0, y)ctx.lineTo(width, y)ctx.stroke()}// 繪制垂直線for (var x = 0; x <= width; x += 10) {ctx.beginPath()ctx.moveTo(x, 0)ctx.lineTo(x, height)ctx.stroke()}}}}// ==============================================// 核心修正:裁剪容器實現進度條效果// ==============================================Item {id: cropContainerwidth: parent.width // 寬度與圖片相同height: imageHeight * progress // 高度由進度值控制anchors.left: parent.left // 對齊左邊anchors.bottom: parent.bottom // 對齊底邊clip: true // 關鍵:啟用裁剪// 圖片元素Image {id: progressImagesource: imageSourcesourceSize.width: imageWidth // 原始寬度sourceSize.height: imageHeight // 原始高度asynchronous: true // 異步加載// 關鍵修正:圖片底部對齊容器底部anchors.bottom: parent.bottom}}// 當前進度文本Text {anchors.top: parent.top // 錨定到容器頂部anchors.topMargin: -30 // 在圖片上方顯示anchors.horizontalCenter: parent.horizontalCenter // 水平居中text: Math.round(progress * 100) + "%" // 顯示百分比font.pixelSize: 20 // 字體大小font.bold: true // 粗體color: "white" // 文本顏色style: Text.Outline // 文本輪廓styleColor: "#000" // 輪廓顏色}// 邊框裝飾Rectangle {anchors.fill: parent // 與圖片容器相同大小color: "transparent" // 透明背景border.color: "#4CAF50" // 邊框顏色border.width: 2 // 邊框寬度radius: 4 // 圓角半徑}}// ==============================================// 控制面板 - 在右側顯示// ==============================================Column {id: controlPanelwidth: 300anchors.left: imageContainer.right // 在圖片容器右側anchors.bottom: parent.bottom // 對齊底部anchors.margins: 30 // 邊距spacing: 20 // 子元素間距// 標題Text {text: "進度控制" // 標題文本font.bold: true // 粗體font.pixelSize: 24 // 字體大小color: "#4CAF50" // 標題顏色}// 進度滑塊Column {width: parent.widthspacing: 5// 滑塊標簽Text {text: "進度值: " + Math.round(progress * 100) + "%" // 顯示當前進度font.pixelSize: 18 // 字體大小color: "white" // 文本顏色}// 進度滑塊Slider {id: progressSliderwidth: parent.width // 寬度填滿minimumValue: 0.0 // 最小值maximumValue: 1.0 // 最大值value: progress // 當前值onValueChanged: progress = value // 值改變時更新進度// 自定義滑塊樣式style: SliderStyle {groove: Rectangle {implicitHeight: 8 // 滑槽高度radius: 4 // 圓角color: "#333" // 背景色// 進度填充Rectangle {height: parent.heightwidth: control.value * parent.width // 根據進度填充radius: 4 // 圓角gradient: Gradient {GradientStop { position: 0.0; color: "#4CAF50" } // 綠色GradientStop { position: 0.5; color: "#2196F3" } // 藍色GradientStop { position: 1.0; color: "#FF9800" } // 橙色}}}// 滑塊手柄handle: Rectangle {width: 24 // 寬度height: 24 // 高度radius: 12 // 圓形color: control.pressed ? "white" : "#f0f0f0" // 按下時白色,否則淺灰色border.color: "#4CAF50" // 邊框顏色border.width: 2 // 邊框寬度// 中心點Rectangle {anchors.centerIn: parentwidth: 8height: 8radius: 4color: "#4CAF50"}}}}}// 預設按鈕Grid {columns: 3 // 3列布局spacing: 10 // 按鈕間距width: parent.width// 預設按鈕文本property var presets: [{text: "0%", value: 0.0},{text: "25%", value: 0.25},{text: "50%", value: 0.5},{text: "75%", value: 0.75},{text: "100%", value: 1.0},{text: "隨機", value: -1}]// 生成預設按鈕Repeater {model: controlPanel.presetsButton {width: (controlPanel.width - 20) / 3 // 平均寬度text: modelData.text // 按鈕文本// 點擊事件onClicked: {if (modelData.value === -1) {// 隨機值progress = Math.random().toFixed(2)} else {// 預設值progress = modelData.value}}// 按鈕樣式style: ButtonStyle {background: Rectangle {radius: 5 // 圓角color: control.pressed ? "#4CAF50" : "#333" // 按下時綠色,否則深灰border.color: "#4CAF50" // 邊框顏色border.width: 1 // 邊框寬度}label: Text {text: control.text // 按鈕文本color: "white" // 文本顏色horizontalAlignment: Text.AlignHCenter // 水平居中verticalAlignment: Text.AlignVCenter // 垂直居中}}}}}// 動畫控制Row {spacing: 15// 開始動畫按鈕Button {text: "開始動畫"onClicked: progressAnimation.start()style: ButtonStyle {background: Rectangle {radius: 5color: control.pressed ? "#4CAF50" : "#333"border.color: "#4CAF50"border.width: 1}label: Text {text: control.textcolor: "white"}}}// 暫停動畫按鈕Button {text: "暫停動畫"onClicked: progressAnimation.pause()style: ButtonStyle {background: Rectangle {radius: 5color: control.pressed ? "#FF9800" : "#333"border.color: "#FF9800"border.width: 1}label: Text {text: control.textcolor: "white"}}}// 停止動畫按鈕Button {text: "停止動畫"onClicked: progressAnimation.stop()style: ButtonStyle {background: Rectangle {radius: 5color: control.pressed ? "#F44336" : "#333"border.color: "#F44336"border.width: 1}label: Text {text: control.textcolor: "white"}}}}}}// ==============================================// 動畫效果 - 自動改變進度值// ==============================================NumberAnimation {id: progressAnimationtarget: mainWindowproperty: "progress"from: 0.0to: 1.0duration: 3000 // 3秒完成easing.type: Easing.InOutQuad // 平滑的緩動效果loops: Animation.Infinite // 無限循環running: false // 默認不運行}
}