我正在开发Qt Quick应用程序。我的目标是在qml页面上创建带有按下和释放按钮的键盘。该键盘有78个键。
我想用InnerShadow效果代表按下的键,并用DropShadow效果代表释放的键:
这是按键组件的qml代码:
Button {
id: root
text: "A"
property color textColor: "#397f92"
property color backgroundColor: "#f6f7fa"
property color borderColor: "#397f92"
property real fontSize: 14
property int offset : 2;
font.family: "Helvetica"
font.pointSize: fontSize
font.capitalization: Font.MixedCase
contentItem: Text {
anchors.centerIn: parent
text: root.text
color: textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: root.font
}
background: Rectangle {
implicitWidth: 55
implicitHeight: 55
color: backgroundColor
border.color: borderColor
radius: 10
border.width: 2
}
DropShadow {
visible: !root.down
anchors.fill: parent
horizontalOffset: 3
verticalOffset: 3
radius: 8.0
samples: 17
color: "#80000000"
source: root.background
cached: false
}
InnerShadow {
visible: root.down
anchors.fill: parent
radius: 8.0
samples: 16
horizontalOffset: 6
verticalOffset: 6
color: "#b0000000"
source: root.background
}
问题在于,加载这78个组件需要花费时间(超过1秒)。所以我一直在寻找一种具有类似视觉效果的更好的解决方案。
使用简单的Rectangle组件时,加载所需的时间很少(足够快,因此用户不会注意到它)。
当使用两个图像(用于按下和释放状态)时,加载也要花费时间(超过1秒)。
我一直在寻找文档和某些论坛上的解决方案,但也许我没有寻找正确的东西。我的提示之一是找到一种在启动应用程序时一次将其加载到应用程序中的组件的方法,而不是每次加载声明此按钮的页面时加载的方法,但是我还没有找到执行该操作的方法。
欢迎任何帮助改善此设计的性能...
以下是使用图像的代码:
KeyButton.qml
Button {
id: root
text: "A"
property color textColor: "#397f92"
property color backgroundColor: "#f6f7fa"
property color borderColor: "#397f92"
property real fontSize: 14
property int offset : 2;
font.family: "Helvetica"
font.pointSize: fontSize
font.capitalization: Font.MixedCase
contentItem: Text {
anchors.centerIn: parent
text: root.text
color: textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: root.font
}
background:Image {
id: bkg_img
source: root.down ? "qrc:/pressed.png" : "qrc:/release.png"
}
Keypad.qml
Item {
id: keypad_keys
anchors.horizontalCenter: parent.horizontalCenter
width: 57 * 14
anchors.horizontalCenterOffset: - width / 20
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -150
RowLayout {
id: row_layout_0
KeyButton {
id: esc_key
fontSize: 9
text: "esc"
Layout.preferredHeight: 30
Layout.preferredWidth: 57
}
KeyButton {
id: key_f1
fontSize: 9
text: "f1"
Layout.preferredHeight: 30
Layout.preferredWidth: 57
}
KeyButton {
id: key_f2
fontSize: 9
text: "f2"
Layout.preferredHeight: 30
Layout.preferredWidth: 57
}
...
}
}
答案 0 :(得分:1)
您的按钮具有较高的绘图复杂度。多重采样阴影特别费力。
您可以将阴影作为图像烘烤,至少对于重复的键大小而言,可以显着提高性能。
或者您可以使用BorderImage
将所有键实现为合成平面光栅图形。
关于使用慢速图像的说法并没有真正体现出来。图片应该很快,您可能做错了什么,但是由于缺少实际代码,所以无法分辨出什么。
此外,您可以将重复的键大小作为图像源进行烘焙,并使用简单的着色器非常有效地绘制缓存的结果,并且仅使键标题具有动态性。
最后但并非最不重要的是,您可以完全刮除阴影,并使用轮廓和填充颜色变化,缩放或线性渐变的组合来获得深度效果,该效果不会被阴影所模仿,而会被斜角所伪造。我的意思是,毕竟,在代表按下的按键时,内部阴影并不是那么逼真,按键并不会像那样沉没。
很多年前,阴影的东西已经不流行了。有多种实现深度效果的有效方法,下面是两个基本示例:
Row {
spacing: 6
Rectangle {
width: 100
height: 100
radius: 10
color: "lightgrey"
border.color: "#666666"
border.width: 2
Rectangle {
width: 90
height: 90
x: ma.pressed ? 3 : 6
y: x
radius: 10
color: "darkgrey"
}
MouseArea {
anchors.fill: parent
id: ma
}
}
Rectangle {
width: 100
height: 100
radius: 10
color: ma2.pressed ? "darkgrey" : "lightgrey"
gradient: Gradient {
GradientStop { position: ma2.pressed ? 0 : 1; color: "#666666" }
GradientStop { position: ma2.pressed ? 1 : 0; color: ma2.pressed ? "#777777" : "#efefef" }
}
border.color: "#666666"
border.width: 2
Rectangle {
width: 90
height: 90
anchors.centerIn: parent
radius: 10
scale: ma2.pressed ? .98 : 1
color: "lightgrey"
}
MouseArea {
anchors.fill: parent
id: ma2
}
}
}
答案 1 :(得分:0)
虽然dtech会带给您良好的指导,但是这里有一些基本的操作可以用来提高应用程序的启动性能。
使用零售生产版本而不是调试版本来衡量加载性能。
Pre-compile your QML files。在某些情况下,这可以大大提高速度。
如果在应用程序启动时预计键盘不会正确显示,请在应用程序启动时将QML预加载到QQuickView中。然后在实际需要时调用“显示”。当然,这只是权衡了1秒钟的加载时间,以使应用程序加载时间更长。 YMMV。
在您的主要qml文件中使用Loader来加载实际内容。实际上,您可以拥有一个主要的qml文件,而只有一个装载程序来承载您的实际QML内容文件以及一个简单的动画“旋转器”控件,以显示UX正在加载。这不会使您的键盘显示更快,但是您的应用程序似乎不会卡住或挂起。