我们需要实现一个垂直进度条效果,但使用图片裁剪的方式。具体需求: 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.4
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
id: mainWindow
width: 800
height: 600
visible: true
title: "图片裁剪进度条 - 修正版"
color: "#121212"
// 图片源 - 使用渐变图片模拟进度条
property string imageSource: "qrc:/image/a.png"
// 进度值 (0.0 - 1.0)
property real progress: 0.5
// 图片属性
property int imageWidth: 50
property int imageHeight: 200
// 主布局
Item {
anchors.fill: parent
// 状态信息 - 显示在顶部
Text {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
text: "图片裁剪进度条 - 固定在左下角"
font.bold: true
font.pixelSize: 18
color: "#4CAF50"
}
// ==============================================
// 图片容器 - 固定在左下角 (核心修正部分)
// ==============================================
Item {
id: imageContainer
width: imageWidth // 宽度与图片相同
height: imageHeight // 高度与图片相同
anchors.left: parent.left // 对齐父元素左边
anchors.bottom: parent.bottom // 对齐父元素底边
anchors.margins: 20 // 边距
// 背景网格 - 帮助可视化
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: "#333"
border.width: 1
// 网格线
Canvas {
anchors.fill: parent
onPaint: {
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: cropContainer
width: parent.width // 宽度与图片相同
height: imageHeight * progress // 高度由进度值控制
anchors.left: parent.left // 对齐左边
anchors.bottom: parent.bottom // 对齐底边
clip: true // 关键:启用裁剪
// 图片元素
Image {
id: progressImage
source: imageSource
sourceSize.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: controlPanel
width: 300
anchors.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.width
spacing: 5
// 滑块标签
Text {
text: "进度值: " + Math.round(progress * 100) + "%" // 显示当前进度
font.pixelSize: 18 // 字体大小
color: "white" // 文本颜色
}
// 进度滑块
Slider {
id: progressSlider
width: 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.height
width: 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: parent
width: 8
height: 8
radius: 4
color: "#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.presets
Button {
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: 5
color: control.pressed ? "#4CAF50" : "#333"
border.color: "#4CAF50"
border.width: 1
}
label: Text {
text: control.text
color: "white"
}
}
}
// 暂停动画按钮
Button {
text: "暂停动画"
onClicked: progressAnimation.pause()
style: ButtonStyle {
background: Rectangle {
radius: 5
color: control.pressed ? "#FF9800" : "#333"
border.color: "#FF9800"
border.width: 1
}
label: Text {
text: control.text
color: "white"
}
}
}
// 停止动画按钮
Button {
text: "停止动画"
onClicked: progressAnimation.stop()
style: ButtonStyle {
background: Rectangle {
radius: 5
color: control.pressed ? "#F44336" : "#333"
border.color: "#F44336"
border.width: 1
}
label: Text {
text: control.text
color: "white"
}
}
}
}
}
}
// ==============================================
// 动画效果 - 自动改变进度值
// ==============================================
NumberAnimation {
id: progressAnimation
target: mainWindow
property: "progress"
from: 0.0
to: 1.0
duration: 3000 // 3秒完成
easing.type: Easing.InOutQuad // 平滑的缓动效果
loops: Animation.Infinite // 无限循环
running: false // 默认不运行
}
}