我们需要实现一个垂直进度条效果,但使用图片裁剪的方式。具体需求: 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 // 默认不运行}
}