QML:在页面中加载50多个组件

时间:2018-12-24 09:49:02

标签: qt qml

我正在开发Qt Quick应用程序。我的目标是在qml页面上创建带有按下和释放按钮的键盘。该键盘有78个键。

我想用InnerShadow效果代表按下的键,并用DropShadow效果代表释放的键: pressed keys released keys

这是按键组件的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
        }

       ...
   }
}

2 个答案:

答案 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
      }
    }
  }

enter image description here

答案 1 :(得分:0)

虽然dtech会带给您良好的指导,但是这里有一些基本的操作可以用来提高应用程序的启动性能。

使用零售生产版本而不是调试版本来衡量加载性能。

Pre-compile your QML files。在某些情况下,这可以大大提高速度。

如果在应用程序启动时预计键盘不会正确显示,请在应用程序启动时将QML预加载到QQuickView中。然后在实际需要时调用“显示”。当然,这只是权衡了1秒钟的加载时间,以使应用程序加载时间更长。 YMMV。

在您的主要qml文件中使用Loader来加载实际内容。实际上,您可以拥有一个主要的qml文件,而只有一个装载程序来承载您的实际QML内容文件以及一个简单的动画“旋转器”控件,以显示UX正在加载。这不会使您的键盘显示更快,但是您的应用程序似乎不会卡住或挂起。