Qt5官方demo解析集33——Qt Quick Examples - Window and Screen

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873

接上文Qt5官方demo解析集32——Qt
Quick Examples - Threading

来到我们Qt Quick Examples的第二个例子了,之所以挑这个demo,主要是我们使用Qt开发界面(尤其是跨平台界面)时,本地屏幕信息与窗口调用是不可避免的课题。

这个例子便向我们展示了在QML中获取本地屏幕信息的方法。

项目树如图,其中shared.qrc是很多QML示例共享的一些资源,包括按钮,滑块等。

此外,为了良好的跨平台,demo中添加了两种格式的图标文件(MAC支持的icns, 以及其他平台通用的png)。

程序运行如图,我们可以调用一个子窗口,以窗口化或最大化形式显示。下方是我的笔记本屏幕的一些信息,包括分辨率,像素密度,方向等等。

由于使用到图标,我们有必要将pro文件拿出来看看:

window.pro:

TEMPLATE = app

QT += quick qml
SOURCES += main.cpp
RESOURCES +=     window.qrc     ../shared/shared.qrc
EXAMPLE_FILES =     window.qml

target.path = $$[QT_INSTALL_EXAMPLES]/quick/window
INSTALLS += target

ICON = resources/icon64.png           // 设置ICON 图标
macx: ICON = resources/icon.icns        // MAC平台额外定义图标
win32: RC_FILE = resources/window.rc

main.cpp:

#include <QtGui/QGuiApplication>            // 个人比较推荐的头文件包含方式
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickWindow>
#include <QtCore/QUrl>
#include <QDebug>

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);
    QQmlEngine engine;                     // 注意到在5.3以后我们大多使用QQmlApplicationEngine来加载qml文件                                                                                          // 它实际也就是封装了这里QQmlEngine + QQmlComponent,并提供了一些其他的便利函数
    QQmlComponent component(&engine);
    QQuickWindow::setDefaultAlphaBuffer(true);       // 如果我们需要应用透明窗体,需要在第一个QQuickWindow出现前设置该函数为true
    component.loadUrl(QUrl("qrc:///window/window.qml"));
    if ( component.isReady() )
        component.create();
    else
        qWarning() << component.errorString();
    return app.exec();
}

我们随着加载的顺序来看第一个qml文件

window.qml:

import QtQuick 2.0
import QtQuick.Window 2.1
import "../shared" as Shared

QtObject {                                           // 非可视化的轻量顶层对象
    property real defaultSpacing: 10                   // 各对象间隔
    property SystemPalette palette: SystemPalette { }  // SystemPalette可以很方便地提供本地化的控件样式

    property var controlWindow: Window {               // 主窗口
        width: visibilityLabel.implicitWidth * 1.2
        height: col.implicitHeight + defaultSpacing * 2
        color: palette.window
        title: "Control Window"
        Column {
            id: col
            anchors.fill: parent
            anchors.margins: defaultSpacing
            spacing: defaultSpacing
            property real cellWidth: col.width / 3 - spacing     // Grid 单元格宽度
            Text { text: "Control the second window:" }
            Grid {
                id: grid
                columns: 3
                spacing: defaultSpacing
                width: parent.width
                Shared.Button {                  // 来自Shared 控件包的Button
                    id: showButton
                    width: col.cellWidth
                    text: testWindow.visible ? "Hide" : "Show"
                    onClicked: testWindow.visible = !testWindow.visible
                }
                //! [windowedCheckbox]
                Shared.CheckBox {                  // CheckBox
                    text: "Windowed"
                    height: showButton.height
                    width: col.cellWidth
                    Binding on checked { value: testWindow.visibility === Window.Windowed }  // 注意Binding是一个QML类型,而不是关键字                                                                                   // 这个语句等于Binding{target: checked; value: testWindow.visibility === Window.Windowed}                                                                 // 相对于checked: XXX 的属性绑定方式,这种方式更适用于var 类型的属性绑定                                                                              // 因此对于bool 型的checked 而言,checked: testWindow.visibility === Window.Windowed 也可行
                    onClicked: testWindow.visibility = Window.Windowed
                }
                //! [windowedCheckbox]
                Shared.CheckBox {
                    height: showButton.height
                    width: col.cellWidth
                    text: "Full Screen"
                    Binding on checked { value: testWindow.visibility === Window.FullScreen }
                    onClicked: testWindow.visibility = Window.FullScreen
                }
                Shared.Button {                // Window.AutomaticVisibility 根据所在平台调整显示方式,比如在Windows 上为窗口,Android 则为全屏
                    id: autoButton
                    width: col.cellWidth
                    text: "Automatic"
                    onClicked: testWindow.visibility = Window.AutomaticVisibility
                }
                Shared.CheckBox {
                    height: autoButton.height
                    text: "Minimized"
                    Binding on checked { value: testWindow.visibility === Window.Minimized }
                    onClicked: testWindow.visibility = Window.Minimized
                }
                Shared.CheckBox {
                    height: autoButton.height
                    text: "Maximized"
                    Binding on checked { value: testWindow.visibility === Window.Maximized }
                    onClicked: testWindow.visibility = Window.Maximized
                }
            }
            function visibilityToString(v) {          // 状态转换String 函数
                switch (v) {
                case Window.Windowed:
                    return "windowed";
                case Window.Minimized:
                    return "minimized";
                case Window.Maximized:
                    return "maximized";
                case Window.FullScreen:
                    return "fullscreen";
                case Window.AutomaticVisibility:
                    return "automatic";
                case Window.Hidden:
                    return "hidden";
                }
                return "unknown";
            }
            Text {
                id: visibilityLabel
                text: "second window is " + (testWindow.visible ? "visible" : "invisible") +
                      " and has visibility " + parent.visibilityToString(testWindow.visibility)
            }
            Rectangle {
                id: horizontalRule
                color: "black"
                width: parent.width
                height: 1
            }
            ScreenInfo { }               // 屏幕信息获取,实现代码在下方
        }
    }              // !controlWindow

    property var testWindow: Window {             // 子窗口
        width: 320
        height: 240
        color: "#215400"              // 窗口背景色,但我们看到的颜色只在周围一圈,是因为中间为Rectangle,那一圈为间隔defaultSpacing
        title: "Test Window with color " + color
        flags: Qt.Window | Qt.WindowFullscreenButtonHint
        Rectangle {
            anchors.fill: parent
            anchors.margins: defaultSpacing         // 矩形与窗口间隔
            Text {
                anchors.centerIn: parent
                text: "Second Window"
            }
            MouseArea {                                 // 点击切换颜色
                anchors.fill: parent
                onClicked: testWindow.color = "#e0c31e"
            }
            Shared.Button {
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.margins: defaultSpacing
                text: testWindow.visibility === Window.FullScreen ? "exit fullscreen" : "go fullscreen"
                width: 150
                onClicked: {
                    if (testWindow.visibility === Window.FullScreen)
                        testWindow.visibility = Window.AutomaticVisibility
                    else
                        testWindow.visibility = Window.FullScreen
                }
            }
            Shared.Button {
                anchors.left: parent.left
                anchors.top: parent.top
                anchors.margins: defaultSpacing
                text: "X"
                width: 30
                onClicked: testWindow.visible = false             // 窗口隐藏
            }
        }
    }            // !testWindow

    property var splashWindow: Splash {            // 启动窗口
        onTimeout: controlWindow.visible = true         // 自定义信号处理函数,显示主窗口
    }
}

为了在QML获取屏幕信息,Qt为我们提供了Screen类型,它可以作为其他可视的QML类型的附加对象,指向该对象所显示的设备:

ScreenInfo.qml:

import QtQuick 2.1
import QtQuick.Window 2.1

Item {
    id: root
    width: 400
    height: propertyGrid.implicitHeight + 16

    function orientationToString(o) {             // 状态转string 函数
        switch (o) {
        case Qt.PrimaryOrientation:
            return "primary";
        case Qt.PortraitOrientation:
            return "portrait";
        case Qt.LandscapeOrientation:
            return "landscape";
        case Qt.InvertedPortraitOrientation:
            return "inverted portrait";
        case Qt.InvertedLandscapeOrientation:
            return "inverted landscape";
        }
        return "unknown";
    }

    Grid {
        id: propertyGrid
        columns: 2
        spacing: 8
        x: spacing
        y: spacing

        //! [screen]
        Text {
            text: "Screen \"" + Screen.name + "\":"      // 显示设备名称
            font.bold: true
        }
        Item { width: 1; height: 1 }                     // 设备名称右方的占位器

        Text { text: "dimensions" }                        // 分辨率
        Text { text: Screen.width + "x" + Screen.height }    

        Text { text: "pixel density" }                     // 像素密度
        Text { text: Screen.pixelDensity.toFixed(2) + " dots/mm (" + (Screen.pixelDensity * 25.4).toFixed(2) + " dots/inch)" }

        Text { text: "logical pixel density" }             // 逻辑像素密度
        Text { text: Screen.logicalPixelDensity.toFixed(2) + " dots/mm (" + (Screen.logicalPixelDensity * 25.4).toFixed(2) + " dots/inch)" }

        Text { text: "available virtual desktop" }         // 可用虚拟桌面,比分辨率的高度少了30 是因为Windows底下的状态栏
        Text { text: Screen.desktopAvailableWidth + "x" + Screen.desktopAvailableHeight }

        Text { text: "orientation" }                       // 屏幕方向
        Text { text: orientationToString(Screen.orientation) + " (" + Screen.orientation + ")" }

        Text { text: "primary orientation" }               // 优先方向
        Text { text: orientationToString(Screen.primaryOrientation) + " (" + Screen.primaryOrientation + ")" }
        //! [screen]
    }
}

最后是启动画面的实现

Splash.qml:

import QtQuick 2.0
import QtQuick.Window 2.1

//! [splash-properties]
Window {
    id: splash
    color: "transparent"
    title: "Splash Window"
    modality: Qt.ApplicationModal           // 应用窗口模式
    flags: Qt.SplashScreen                  // 启动画面
    property int timeoutInterval: 2000
    signal timeout                               // 自定义溢出信号
//! [splash-properties]
//! [screen-properties]
    x: (Screen.width - splashImage.width) / 2       // 居中
    y: (Screen.height - splashImage.height) / 2
//! [screen-properties]
    width: splashImage.width                 // 窗口大小与图片大小一致
    height: splashImage.height

    Image {
        id: splashImage
        source: "../shared/images/qt-logo.png"
        MouseArea {
            anchors.fill: parent
            onClicked: Qt.quit()           // 点击退出
        }
    }
    //! [timer]
    Timer {
        interval: timeoutInterval; running: true; repeat: false
        onTriggered: {
            visible = false         // 2秒后隐藏,并发出timeout信号,以显示主窗口
            splash.timeout()
        }
    }
    //! [timer]
    Component.onCompleted: visible = true
}
时间: 2024-11-16 14:01:31

Qt5官方demo解析集33——Qt Quick Examples - Window and Screen的相关文章

Qt5官方demo解析集32——Qt Quick Examples - Threading

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集31--StocQt 因为涉及到QML线程看到这个例子,发现它是属于Qt Quick Example这个系列的.这个系列共有19个demo,涵盖了Qt Quick中多种元素,有空我们把这个系列一篇篇做下来,相信是一趟不错的旅途~ 好了,在我们编写应用程序,尤其是用户界面程序,多线程往往是避不开的一个话题.界面卡死超过3秒,

Qt5官方demo解析集10——Qt Quick Particles Examples - Emitters

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 前段时间去听了Qt在北京的开发者大会,感觉QML是大势所趋,所以回来后想好好补补QML方面的东西.无奈无论是书籍还是网络上,这方面的教材都太少了. 霍亚飞的<Qt Creator快速入门>第二版中做了一些介绍,但也只是基本的元素,布局,动画等.QML绚丽的粒子特效,传感器,多媒体模块,WebView,GPS,蓝牙等等...都没有提及. 所以这段时间也

Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles

本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文 Qt5官方demo解析集12--Qt Quick Particles Examples - CustomParticles 先唠下嗑,在上文CustomParticles中我们接触了强大的ShaderEffect,笔者对其产生了极大的兴趣,于是去找了找有没有很多其它相关的例程,于是就发现了一个QML Video Shader Effects E

Qt5官方demo解析集12——Qt Quick Particles Examples - CustomParticles

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集11--Qt Quick Particles Examples - Affectors 使用Emitter和Affectors强大的功能,我们已经可以构造出丰富多彩的粒子特效,但当这些功能还不能满足我们的需要时,我们可以转而采用CustomParticle取代ImageParticle,在CustomParticle中我们

Qt5官方demo解析集11——Qt Quick Particles Examples - Affectors

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt Quick Particles Examples - Emitters Affectors是Qt官方粒子系统demo中的第二个例程,它是在Emitters上的进一步扩展.我们将看到,通过使用Affectors,我们能够创造更加灵活的粒子显示以及交互行为. 首先还是看下介绍:This is a collecti

Qt5官方demo解析集14——Qt Quick Particles Examples - System

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集13--Qt Quick Particles Examples - Image Particles 一转眼就到了我们粒子系列的最后一个demo了,既然是System,第一个小例子就给我们介绍了"模拟"一个粒子系统的方式,接着又向我们介绍了running属性的应用,然后是粒子群组等十分实用的技术. 来看看我们熟悉的

Qt5官方demo分析集11——Qt Quick Particles Examples - Affectors

在这个系列中的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt Quick Particles Examples - Emitters Affectors是Qt官方粒子系统demo中的第二个例程,它是在Emitters上的进一步扩展.我们将看到.通过使用Affectors,我们可以创造更加灵活的粒子显示以及交互行为. 首先还是看下介绍:This is a col

Qt5官方demo解析集34——Concentric Circles Example

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集33--Qt Quick Examples - Window and Screen 好像有一段时间没有更新这个系列了,一方面是很多的事掺杂着一起来了,稍微比原来忙了一些:但时间哪有挤不出来的呢,所以更重要的一个原因其实是很难找到一个特别合适的Demo来做这个主题.有的Demo内容很偏很少项目在做,有的Demo又过于基础,我

Qt5官方demo解析集20——Chapter 6: Writing an Extension Plugin

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集19--Chapter 5: Using List Property Types 在前文中我们定义的PieChart和PieSlice这两个自定义QML类型只用来供app.qml文件使用,如果希望我们所定义的类型可以被多个qml使用,那么可以将其创建为可扩展的插件.由于是将C++定义的类创建为供QML使用的插件,所以这与我