QML学习——Qt Quick Extras Examples 1.4(八)

Qt Quick Extras Examples

阅读官方的源码然后尝试做了下

01 A car dashboard
  • 样例演示:

  • 在这里插入图片描述

  • 说明:

    • ValueSource组件控制数值相关的动画,例如图中数值的变化;
    • TurnIndicator组件是控制左右方向灯的闪烁和背景,里面使用了Canvas来绘制样式;
    • IconGaugeStyle是对DashboardGaugeStyle的封装,里面绘制了带图标仪表盘的样式,用于左边油量表和水温表的样式;
    • DashboardGaugeStyle是对CircularGaugeStyle的封装,用于中间的速度仪表的样式;
    • TachometerStyle是对DashboardGaugeStyle的封装,用于右边转速表的样式;

具体代码:

TestExtrasDashboard.qml

import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4

import "./Component"

Rectangle {
   
    id: root
    width: 1024
    height: 600

    color: "#161616"

    ValueSource {
   
        id: valueSource
    }

    // Dashboards are typically in a landscape orientation, so we need to ensure
    // our height is never greater than our width.
    Item {
   
        id: container
        width: root.width
        height: Math.min(root.width, root.height)
        anchors.centerIn: parent

        Row {
   
            id: gaugeRow
            spacing: container.width * 0.02
            anchors.centerIn: parent

            TurnIndicator {
   
                id: leftIndicator
                anchors.verticalCenter: parent.verticalCenter
                width: height
                height: container.height * 0.1 - gaugeRow.spacing

                direction: Qt.LeftArrow
                on: valueSource.turnSignal === Qt.LeftArrow
            }

            Item {
   
                width: height
                height: container.height * 0.25 - gaugeRow.spacing
                anchors.verticalCenter: parent.verticalCenter

                CircularGauge {
   
                    id: fuelGauge
                    value: valueSource.fuel
                    maximumValue: 1
                    y: parent.height / 2 - height / 2 - container.height * 0.01
                    width: parent.width
                    height: parent.height * 0.7

                    style: IconGaugeStyle {
   
                        id: fuelGaugeStyle

                        icon: "qrc:/Icons/Used_Images/Icons/02_10-fuel-icon.png"
                        minWarningColor: Qt.rgba(0.5, 0, 0, 1)

                        tickmarkLabel: Text {
   
                            color: "white"
                            visible: styleData.value === 0 || styleData.value === 1
                            font.pixelSize: fuelGaugeStyle.toPixels(0.225)
                            text: styleData.value === 0 ? "E" : (styleData.value === 1 ? "F" : "")
                        }
                    }
                }

                CircularGauge {
   
                    value: valueSource.temperature
                    maximumValue: 1
                    width: parent.width
                    height: parent.height * 0.7
                    y: parent.height / 2 + container.height * 0.01

                    style: IconGaugeStyle {
   
                        id: tempGaugeStyle

                        icon: "qrc:/Icons/Used_Images/Icons/03_10-temperature-icon.png"
                        maxWarningColor: Qt.rgba(0.5, 0, 0, 1)

                        tickmarkLabel: Text {
   
                            color: "white"
                            visible: styleData.value === 0 || styleData.value === 1
                            font.pixelSize: tempGaugeStyle.toPixels(0.225)
                            text: styleData.value === 0 ? "C" : (styleData.value === 1 ? "H" : "")
                        }
                    }
                }
            }

            CircularGauge {
   
                id: speedometer
                value: valueSource.kph
                anchors.verticalCenter: parent.verticalCenter
                maximumValue: 280
                // We set the width to the height, because the height will always be
                // the more limited factor. Also, all circular controls letterbox
                // their contents to ensure that they remain circular. However, we
                // don't want to extra space on the left and right of our gauges,
                // because they're laid out horizontally, and that would create
                // large horizontal gaps between gauges on wide screens.
                width: height
                height: container.height * 0.5

                style: DashboardGaugeStyle {
   }
            }

            CircularGauge {
   
                id: tachometer
                width: height
                height: container.height * 0.25 - gaugeRow.spacing
                value: valueSource.rpm
                maximumValue: 8
                anchors.verticalCenter: parent.verticalCenter

                style: TachometerStyle {
   }
            }

            TurnIndicator {
   
                id: rightIndicator
                anchors.verticalCenter: parent.verticalCenter
                width: height
                height: container.height * 0.1 - gaugeRow.spacing

                direction: Qt.RightArrow
                on: valueSource.turnSignal === Qt.RightArrow
            }
        }
    }
}

DashboardGaugeStyle.qml

import QtQuick 2.2
import QtQuick.Controls.Styles 1.4

CircularGaugeStyle {
   
    tickmarkInset: toPixels(0.04)
    minorTickmarkInset: tickmarkInset
    labelStepSize: 20
    labelInset: toPixels(0.23)

    property real xCenter: outerRadius
    property real yCenter: outerRadius
    property real needleLength: outerRadius - tickmarkInset * 1.25
    property real needleTipWidth: toPixels(0.02)
    property real needleBaseWidth: toPixels(0.06)
    property bool halfGauge: false

    function toPixels(percentage) {
   
        return percentage * outerRadius;
    }

    function degToRad(degrees) {
   
        return degrees * (Math.PI / 180);
    }

    function radToDeg(radians) {
   
        return radians * (180 / Math.PI);
    }

    function paintBackground(ctx) {
   
        if (halfGauge) {
   
            ctx.beginPath();
            ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2);
            ctx.clip();
        }

        ctx.beginPath();
        ctx.fillStyle = "black";
        ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.fill();

        ctx.beginPath();
        ctx.lineWidth = tickmarkInset;
        ctx.strokeStyle = "black";
        ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2);
        ctx.stroke();

        ctx.beginPath();
        ctx.lineWidth = tickmarkInset / 2;
        ctx.strokeStyle = "#222";
        ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2);
        ctx.stroke();

        ctx.beginPath();
        var gradient = ctx.createRadialGradient(xCenter, yCenter, 0, xCenter, yCenter, outerRadius * 1.5);
        gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0));
        gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13));
        gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1));
        ctx.fillStyle = gradient;
        ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2);
        ctx.fill();
    }

    background: Canvas {
   
        onPaint: {
   
            var ctx = getContext("2d");
            ctx.reset();
            paintBackground(ctx);
        }

        Text {
   
            id: speedText
            font.pixelSize: toPixels(0.3)
            text: kphInt
            color: "white"
            horizontalAlignment: Text.AlignRight
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.top: parent.verticalCenter
            anchors.topMargin: toPixels(0.1)

            readonly property int kphInt: control.value
        }
        Text {
   
            text: "km/h"
            color: "white"
            font.pixelSize: toPixels(0.09)
            anchors.top: speedText.bottom
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }

    needle: Canvas {
   
        implicitWidth: needleBaseWidth
        implicitHeight: needleLength

        property real xCenter: width / 2
        property real yCenter: height / 2

        onPaint: {
   
            var ctx = getContext("2d");
            ctx.reset();

            ctx.beginPath();
            ctx.moveTo(xCenter, height);
            ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2);
            ctx.lineTo(xCenter - needleTipWidth / 2, 0);
            ctx.lineTo(xCenter, yCenter - needleLength);
            ctx.lineTo(xCenter, 0);
            ctx.closePath();
            ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66);
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(xCenter, height)
            ctx.lineTo(width, height - needleBaseWidth / 2);
            ctx.lineTo(xCenter + needleTipWidth / 2, 0);
            ctx.lineTo(xCenter, 0);
            ctx.closePath();
            ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66));
            ctx.fill();
        }
    }

    foreground: null
}

IconGaugeStyle.qml

import QtQuick 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4

DashboardGaugeStyle {
   
    id: fuelGaugeStyle
    minimumValueAngle: -60
    maximumValueAngle: 60
    tickmarkStepSize: 1
    labelStepSize: 1
    labelInset: toPixels(-0.25)
    minorTickmarkCount: 3

    needleLength: toPixels(0.85)
    needleBaseWidth: toPixels(0.08)
    needleTipWidth: toPixels(0.03)

    halfGauge: true

    property string icon: ""
    property color minWarningColor: "transparent"
    property color maxWarningColor: "transparent"
    readonly property real minWarningStartAngle: minimumValueAngle - 90
    readonly property real maxWarningStartAngle: maximumValueAngle - 90

    tickmark: Rectangle {
   
        implicitWidth: toPixels(0.06)
        antialiasing: true
        implicitHeight: toPixels(0.2)
        color: "#c8c8c8"
    }

    minorTickmark: Rectangle {
   
        implicitWidth: toPixels(0.03)
        antialiasing: true
        implicitHeight: toPixels(0.15)
        color: "#c8c8c8"
    }

    background: Item {
   
        Canvas {
   
            anchors.fill: parent
            onPaint: {
   
                var ctx = getContext("2d");
                ctx.reset();

                paintBackground(ctx);

                if (minWarningColor != "transparent") {
   
                    ctx.beginPath();
                    ctx.lineWidth = fuelGaugeStyle.toPixels(0.08);
                    ctx.strokeStyle = minWarningColor;
                    ctx.arc(outerRadius, outerRadius,
                        // Start the line in from the decorations, and account for the width of the line itself.
                        outerRadius - tickmarkInset - ctx.lineWidth / 2,
                        degToRad(minWarningStartAngle),
                        degToRad(minWarningStartAngle + angleRange / (minorTickmarkCount + 1)), false);
                    ctx.stroke();
                }
                if (maxWarningColor != "transparent") {
   
                    ctx.beginPath();
                    ctx.lineWidth = fuelGaugeStyle.toPixels(0.08);
                    ctx.strokeStyle = maxWarningColor;
                    ctx.arc(outerRadius, outerRadius,
                        // Start the line in from the decorations, and account for the width of the line itself.
                        outerRadius - tickmarkInset - ctx.lineWidth / 2,
                        degToRad(maxWarningStartAngle - angleRange / (minorTickmarkCount + 1)),
                        degToRad(maxWarningStartAngle), false);
                    ctx.stroke();
                }
            }
        }

        Image {
   
            source: icon
            anchors.bottom: parent.verticalCenter
            anchors.bottomMargin: toPixels(0.3)
            anchors.horizontalCenter: parent.horizontalCenter
            width: toPixels(0.3)
            height: width
            fillMode: Image.PreserveAspectFit
        }
    }
}

TachometerStyle.qml

import QtQuick 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4

DashboardGaugeStyle {
   
    id: tachometerStyle
    tickmarkStepSize: 1
    labelStepSize: 1
    needleLength: toPixels(0.85)
    needleBaseWidth: toPixels(0.08)
    needleTipWidth: toPixels(0.03)

    tickmark: Rectangle {
   
        implicitWidth: toPixels(0.03)
        antialiasing: true
        implicitHeight: toPixels(0.08)
        color: styleData.index === 7 || styleData.index === 8 ? Qt.rgba(0.5, 0, 0, 1) : "#c8c8c8"
    }

    minorTickmark: null

    tickmarkLabel: Text {
   
        font.pixelSize: Math.max(6, toPixels(0.12))
        text: styleData.value
        color: styleData.index === 7 || styleData.index === 8 ? Qt.rgba(0.5, 0, 0, 1) : "#c8c8c8"
        antialiasing: true
    }

    background: Canvas {
   
        onPaint: {
   
            var ctx = getContext("2d");
            ctx.reset();
            paintBackground(ctx);

            ctx.beginPath();
            ctx.lineWidth = tachometerStyle.toPixels(0.08);
            ctx.strokeStyle = Qt.rgba(0.5, 0, 0, 1);
            var warningCircumference = maximumValueAngle - minimumValueAngle * 0.1;
            var startAngle = maximumValueAngle - 90;
            ctx.arc(outerRadius, outerRadius,
                // Start the line in from the decorations, and account for the width of the line itself.
                outerRadius - tickmarkInset - ctx.lineWidth / 2,
                degToRad(startAngle - angleRange / 8 + angleRange * 0.015),
                degToRad(startAngle - angleRange * 0.015), false);
            ctx.stroke();
        }

        Text {
   
            id: rpmText
            font.pixelSize: tachometerStyle.toPixels(0.3)
            text: rpmInt
            color: "white"
            horizontalAlignment: Text.AlignRight
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.top: parent.verticalCenter
            anchors.topMargin: 20

            readonly property int rpmInt: valueSource.rpm
        }
        Text {
   
            text: "x1000"
            color: "white"
            font.pixelSize: tachometerStyle.toPixels(0.1)
            anchors.top: parent.top
            anchors.topMargin: parent.height / 4
            anchors.horizontalCenter: parent.horizontalCenter
        }
        Text {
   
            text: "RPM"
            color: 
如果 libclang-dev 已经安装,但是编译仍然提示找不到 libclang,可能是由于 libclang 的头文件或库文件路径没有被正确设置导致的。 你可以尝试在编译 Qt 时手动指定 libclang 的路径。假设 libclang 库文件的路径是 `/usr/lib/x86_64-linux-gnu/libclang.so`,头文件的路径是 `/usr/include/clang/`,则可以使用以下命令进行编译: ``` ./configure -opensource -confirm-license -nomake examples -nomake tests -no-opengl -no-openssl -no-xcb -no-xkbcommon -no-icu -no-glib -no-pulseaudio -no-alsa -no-feature-geoservices_mapboxgl -no-feature-geoservices_mapbox -no-feature-geoservices_nokia -no-feature-geoservices_google -no-feature-geoservices_here -no-feature-geoservices_arcgis -no-feature-geoservices_ublox -no-feature-geoservices_maxar -no-feature-textodfwriter -no-feature-xmlpatterns -no-feature-testlib -no-feature-shared -no-feature-process -no-feature-printpreviewwidget -no-feature-printpreviewdialog -no-feature-printenginengeneric -no-feature-printsupport -no-feature-pdf -no-feature-paint_debug -no-feature-network -no-feature-mimetype -no-feature-journald -no-feature-jpeg -no-feature-ibus -no-feature-gif -no-feature-freetype -no-feature-fontconfig -no-feature-dbus -no-feature-cups -no-feature-cursor -no-feature-contextmenu -no-feature-completer -no-feature-commandlineparser -no-feature-codecs -no-feature-colornames -no-feature-colordialog -no-feature-colorpicker -no-feature-clipboard -no-feature-bearermanagement -no-feature-alsa -no-feature-accessibility -no-dbus-linked -no-compile-examples -no-openssl-linked -no-pch -system-zlib -system-libjpeg -system-libpng -system-freetype -system-harfbuzz -system-xcb -system-xkbcommon -no-gui -no-widgets -no-qml-debug -no-qml-debugger -no-compile-examples -no-libudev -no-feature-texthtmlparser -no-feature-textfreetype -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-texthtmlwriter -no-feature-textplaintextwriter -no-feature-textmarkdownreader -no-feature-sql-ibase -no-feature-sql-mysql -no-feature-sql-oci -no-feature-sql-odbc -no-feature-sql-psql -no-feature-sql-sqlite2 -no-feature-sql-sqlite -no-feature-sql-tds -no-feature-sqlite -no-feature-speex -no-feature-sse2 -no-feature-systemsemaphore -no-feature-systemsemaphore -no-feature-syslog -no-feature-tcpserver -no-feature-threads -no-feature-tiff -no-feature-toolbox -no-feature-unix-socket -no-feature-vnc -no-feature-wheelevent -no-feature-wizard -no-feature-xml -no-feature-xmlcatalog -no-feature-xmlstream -no-feature-xml -no-feature-xmlpatterns -no-feature-xmlrpc -no-feature-xcb-icccm -no-feature-xcb-image -no-feature-xcb-keysyms -no-feature-xcb-render -no-feature-xcb-shape -no-feature-xcb-xinput -no-feature-xinput2 -no-feature-xkb -no-feature-xrandr -no-feature-xrender -no-feature-xshm -no-feature-xsync -no-feature-xt -no-feature-ipv6ifname -no-feature-qt3d-logic -no-feature-qt3d-render -no-feature-qt3d-input -no-feature-qt3d-extras -no-feature-qt3d-animation -no-feature-qt3d-quick -no-feature-qt3d-simd -no-feature-qt3d-scene2d -no-feature-qt3d-scene3d -no-feature-qt3d-core -no-feature-qt3d-render -no-feature-qt3d-input -no-feature-qt3d-extras -no-feature-qt3d-animation -no-feature-qt3d-quick -no-feature-qt3d-simd -no-feature-qt3d-scene2d -no-feature-qt3d-scene3d -no-feature-qt3d-core -no-feature-qt3d -no-feature-qtvirtualkeyboard -no-feature-qtwayland -no-feature-qtmultimedia -no-feature-qtpurchasing -no-feature-qtsensors -no-feature-qtspeech -no-feature-qtvirtualkeyboard -no-feature-qtwayland -no-feature-qtmultimedia -no-feature-qtpurchasing -no-feature-qtsensors -no-feature-qtspeech -no-feature-qtwebchannel -no-feature-qtwebengine -no-feature-qtwebsockets -no-feature-qtwebview -no-feature-qtwebglplugin -no-feature-qtwebsockets -no-feature-qtwebview -no-feature-qtwebglplugin -no-feature-qtxmlpatterns -no-feature-qtx11extras -no-feature-qtxml -no-feature-qtxmlpatterns -no-feature-qtx11extras -no-feature-qtxml -no-feature-qtxmlpatterns -no-feature-qtx11extras -no-feature-qtxml -no-feature-qtxmlpatterns -no-feature-qtx11extras -no-feature-qtxml -feature-thread make -j$(nproc) LLVM_INSTALL_DIR=/usr/include/clang/ ``` 其中,LLVM_INSTALL_DIR 指定了 libclang 的路径,这里设置为 `/usr/include/clang/`,请根据实际情况修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Taiga_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值