找回密码
 立即注册
收起左侧

QML中如何添加一条动态线段

4
回复
13402
查看
[复制链接]
累计签到:7 天
连续签到:1 天
来源: 2017-5-22 08:32:17 显示全部楼层 |阅读模式
1Qter豆
QML中有Rectangle等元素,可以配合Animation来产生动画,但是如何实现一条线段的缩放、旋转和伸缩呢?
我的几条想法,但是感觉不方便:
1、用Canvas,实现一条线段还行,实现多条时很不方便。。。
2、用一个很细的Rectangle代替线段,但是线段的坐标不好计算(要三角函数。。。)
3、C++中实现一个类,这个感觉有点鄙视了QML,连线段也得自己实现...
谢谢大家了~

回复

使用道具 举报

累计签到:742 天
连续签到:1 天
2017-5-22 08:53:30 显示全部楼层
刚看到你在 QTCN 上发了,又在这看到,个人来讲,用一个 QML 文件自定义这样一个东西,使用 Rectangle 来表示,坐标的计算规则全部放在 QML 文件里面,在外部直接用这个类,这样是比较好的方法,Canvas 做这个事情是不是不太好做呢,毕竟它是用来绘图的,在运算和消息处理方面显得不是那么方便~~~
回复

使用道具 举报

累计签到:7 天
连续签到:1 天
2017-5-22 12:26:05 显示全部楼层
嗯,网上搜了画线段还真没这方面的示例和讲解,没办法只好自己搞了,两个办法都用了,总结如下:
canvas实现单条线段比较容易,但是如果多条,首先取线段的数据比较麻烦,而且刷新不好控制,也如果做成一个QML文件,但是效果非常差(卡顿)..所以还是用了Rectangle实现,效果很不错,用了三角函数的一些知识(我居然都忘的差不多了),虽然比较繁琐但做成一个QML效果很不错,源代码如下(抛砖引玉一下~)

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

Item {

    property point srcPoint: Qt.point(300,300)
    property point dstPoint: Qt.point(300,500)

    width: 800
    height: 600
    Rectangle{//模拟线段
        id: rect
        property int value: 0
        x: 300
        y: 300
        width:200 //长
        height:200  //高
        color:"blue" //颜色

        MouseArea {
            anchors.fill: parent
            onClicked: {
                console.debug("value:",rect.value)
                switch(rect.value) {
                case 0:
                    dstPoint = Qt.point(300,500)
                    break;
                case 1:
                    dstPoint = Qt.point(200,500)
                    break;
                case 2:
                    dstPoint = Qt.point(100,500)
                    break;
                case 3:
                    dstPoint = Qt.point(100,400)
                    break;
                case 4:
                    dstPoint = Qt.point(100,300)
                    break;
                case 5:
                    dstPoint = Qt.point(100,200)
                    break;
                case 6:
                    dstPoint = Qt.point(100,100)
                    break;
                case 7:
                    dstPoint = Qt.point(200,100)
                    break;
                case 8:
                    dstPoint = Qt.point(300,100)
                    break;
                case 9:
                    dstPoint = Qt.point(400,100)
                    break;
                case 10:
                    dstPoint = Qt.point(500,100)
                    break;
                case 11:
                    dstPoint = Qt.point(500,200)
                    break;
                case 12:
                    dstPoint = Qt.point(500,300)
                    break;
                case 13:
                    dstPoint = Qt.point(500,400)
                    break;
                case 14:
                    dstPoint = Qt.point(500,500)
                    break;
                case 15:
                    dstPoint = Qt.point(400,500)
                    rect.value = -1
                    break;
                }
                rect.value ++;
                draw()
            }
        }
    }

    Rectangle{//模拟线段
        id: line
        width: 3 //长
        color: "#7FFF0000" //颜色

        //rotation: 180 //顺时针旋转的角度
        transformOrigin: Item.TopLeft


        PropertyAnimation {
            id: propAni
            target: line
            property: "height"
            duration: 5000

        }
    }

    function draw() {
        var jiaodu = 0
        var lineLength = Math.sqrt(Math.pow(dstPoint.x - srcPoint.x, 2) + Math.pow(dstPoint.y - srcPoint.y, 2))
        line.x = srcPoint.x
        line.y = srcPoint.y

        if(dstPoint.y == srcPoint.y) {
            if(dstPoint.x <= srcPoint.x) jiaodu = 90
            else jiaodu = 270
        }
        else if(dstPoint.x == srcPoint.x) {
            if(dstPoint.y < srcPoint.y) jiaodu = 180
            else jiaodu = 0
        }
        else {
            if(dstPoint.x < srcPoint.x && dstPoint.y > srcPoint.y) {
                jiaodu = Math.atan((Math.abs((dstPoint.x - srcPoint.x)) / Math.abs((dstPoint.y - srcPoint.y)))) * 180 / Math.PI
            }

            else if(dstPoint.x < srcPoint.x && dstPoint.y < srcPoint.y) {

                jiaodu = Math.atan((Math.abs((dstPoint.y - srcPoint.y)) / Math.abs((dstPoint.x - srcPoint.x)))) * 180 / Math.PI
                jiaodu += 90
            }
            else if(dstPoint.x > srcPoint.x && dstPoint.y < srcPoint.y) {

                jiaodu = Math.atan((Math.abs((dstPoint.x - srcPoint.x)) / Math.abs((dstPoint.y - srcPoint.y)))) * 180 / Math.PI
                jiaodu += 180
            }
            else if(dstPoint.x > srcPoint.x && dstPoint.y > srcPoint.y) {

                jiaodu = Math.atan((Math.abs((dstPoint.y - srcPoint.y)) / Math.abs((dstPoint.x - srcPoint.x)))) * 180 / Math.PI
                jiaodu += 270
            }
        }

        line.height = lineLength
        line.rotation = jiaodu

        //propAni.to = lineLength
        //propAni.start()
        console.debug("line:", lineLength, jiaodu)
    }

    Component.onCompleted: {
        //console.debug(Math.atan(1) / Math.PI * 180)
        //dstPoint = Qt.point(300,500)
        //draw()

    }
}
回复

使用道具 举报

尚未签到

2017-5-22 22:07:27 显示全部楼层
用一张图片来代替不行么。。。
回复

使用道具 举报

累计签到:7 天
连续签到:1 天
2017-5-30 08:08:45 显示全部楼层
用图片代替还得考虑旋转角度和长度啊,不过可以用图片代替我上面代码的Rectange,效果会更好
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了