当前位置: 首页 > 工具软件 > 舒尔特表 > 使用案例 >

使用QML编写舒尔特表小程序

贺山
2023-12-01

        舒尔特表是一种训练注意力的表格,表格内容是打乱顺序的自然数序列,练习时,需要按照顺序从最小数点到最大数,用时越少越好。下面说明如何以QML/javascript为主要编程语言来构建这么一个小程序。

        首先创建一个Qt Quick项目,构建套件选择两个,一个是Windows平台的,一个是android平台的,日后可以在android手机上玩儿,而且在Windows平台上调试比较方便。项目自动生成了两个代码文件,一个是main.cpp,一个是main.qml.前者不用修改,我们不去关注,后者是程序运行的主要框架代码文件,见下面的清单。

import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

import "qrc:///schulteGrid.js" as SchulteGrid

Window {
    id:screen
    visible: true

    SystemPalette { id: activePalette }

    Rectangle{
        id:toolbar
        width:parent.width
        height:30
        color:activePalette.window
        anchors.bottom: screen.bottom

        Button{
            id:button
            anchors{
                left:parent.left
                verticalCenter: parent.verticalCenter
            }
            text:"开始"
            onClicked: {
                SchulteGrid.setCurrentIndex(1);
                globalVar.rank = rank.value;
                SchulteGrid.createGrid(globalVar.rank);
                globalVar.seconds = 0;
                timer.running = true;

            }
        }
        SpinBox
        {
            id:rank
            minimumValue: 3
            maximumValue: 9
            anchors{
                left: button.right
                verticalCenter: parent.verticalCenter
            }
        }

        Text{
            id:time
            anchors{
                right:parent.right
                verticalCenter: parent.verticalCenter
            }

            text:"时间"
        }
    }

    Item{
        id:globalVar
        property int currentIndex
        property int seconds
        property int rank

        Timer{
            id:timer
            interval: 1000
            running: false
            repeat: true
            onTriggered: {
                globalVar.seconds += 1;
                time.text = "时间:" + globalVar.seconds.toString() + "秒"
            }
        }
    }
}

        代码构建了一条工具栏和一个保存了全局变量及定时器的项。工具条中放了一个按钮,一个数值调整框和一个显示标签。按钮用于触发游戏,数值调整框用于选择生成几阶的舒尔特表,显示标签用于显示当前所用的时间,一秒一秒地变化。

        这段代码中有两处值得关注的,一个是按钮是自己画的,这个按钮的定义是另外一个QML文件“Button.qml"定义的,清单见下面。

import QtQuick 2.0

Rectangle {
    id:container
    property string text:"Button"
    signal clicked

    SystemPalette { id: activePalette }

    width: textLabel.width + 20
    height: textLabel.height + 5
    border{
        width: 1
        color: Qt.darker(activePalette.button)
    }
    antialiasing: true
    radius: 5

    gradient:Gradient{
        GradientStop{
            position: 0.0
            color: {
                if(mouseArea.pressed)
                    return activePalette.dark
                else
                    return activePalette.light
            }
        }
        GradientStop{
            position: 1.0
            color: activePalette.button
        }
    }

    MouseArea{
        id: mouseArea
        anchors.fill: parent
        onClicked: container.clicked()
    }

    Text{
        id: textLabel
        anchors.centerIn: parent
        color: activePalette.buttonText
        text: container.text
    }
}

        另外一处则是程序的运行逻辑由”import "qrc:///schulteGrid.js" as SchulteGrid"这句话导入,是放在了"schulteGrid.js"里面,清单见下面。

var gridFactory;
var grid = new Array(100);
var index = new Array(100);

function createGrid(r) {
    for(var i=0; i<100; i++)
    {
        if(grid[i] != null)
            grid[i].opacity = 0;
        grid[i] = null;
    }

    for(var i=0; i<100; i++)
    {
        index[i] = i;
    }

    gridFactory = Qt.createComponent("qrc:///grid.qml");

    if(gridFactory.status == Component.Ready)
    {
        for(var i=0; i<r; i++)
        {
            for(var j=0; j<r; j++)
            {
                var random = getRandomNum(1, r*r-(i*r+j))
                var dynamicObject = gridFactory.createObject(screen);
                if(dynamicObject != null)
                {
                    dynamicObject.size = screen.width/r;

                    dynamicObject.pointSize = dynamicObject.size*3/4;

                    dynamicObject.x = j*dynamicObject.size;
                    dynamicObject.y = i*dynamicObject.size + 30;
                    dynamicObject.text = (index[random]).toString();
                    dynamicObject.color = "#0080ff";
                    dynamicObject.index = index[random];

                    grid[i*r+j] = dynamicObject;
                    for(var k=random; k<r*r; k++)
                    {
                        index[k] = index[k+1];
                    }
                }
                else
                {
                    console.log("createObject error");
                }
            }
        }
    }
    else
    {
        console.log("component not ready");
        console.log(gridFactory.errorString());
    }
}

function getRandomNum(Min,Max)
{
    var Range = Max - Min;
    var Rand = Math.random();
    return(Min + Math.round(Rand * Range));
}

function getCurrentIndex()
{
    return globalVar.currentIndex;
}

function setCurrentIndex(_currentIndex)
{
    globalVar.currentIndex = _currentIndex;
}

function getGridCount()
{
    return globalVar.rank * globalVar.rank;
}
        这个文件的主要作用就是动态创建一堆表格,每个格都显示一个数字,不能重复,这里面又用到了另外一个QML文件“grid.qml",用于创建单独的一个格,清单见下面。

import QtQuick 2.0

import "qrc:///schulteGrid.js" as SchulteGrid

Item {
    id:grid
    property int index
    property string text
    property string color
    property int size
    property int pointSize
    Rectangle
    {
        width:grid.size
        height:grid.size
        color:grid.color//"#0080ff"
        border.width:1
        border.color:"#000000"

        Text{
            text:grid.text
            font.pointSize: grid.pointSize
            anchors.centerIn: parent
        }
        MouseArea{
            id: mouseArea
            anchors.fill: parent
            onPressed: {
                if(grid.index != SchulteGrid.getCurrentIndex())
                {
                    grid.color = "#dd0000";
                }
                else
                {
                    grid.color = "#00ff00";
                    SchulteGrid.setCurrentIndex(grid.index + 1);
                    if(grid.index == SchulteGrid.getGridCount())
                    {
                        timer.running = false;
                    }
                }
            }
            onReleased:grid.color = "#0080ff"
        }
    }
}
        程序到这儿就完事儿了,总共200来行代码,不算简洁,但也可以看到QML/javascript编程方式的这种能力,可以将界面与运行逻辑分开处理,并且还可以将一些界面元素单独分离出来,比如说Button元素和Grid元素,我想这是符合现代程序设计理念的。

 类似资料: