找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

qml学习总结【qt写界面】

admin 2019-3-5 06:52 881人围观 Qt相关

来源于微信公众号:程序员学习分享录

qml的总结


经过几天的学习,简单的了解了qml的一些基础,在此记录分享。

先说下:windows下怎么安装Qt软件【这个问题,曾经搞了我一阵子,万事开头难,这就是第一步啊】

先去官网 qt下载路径下载最新或者适合你的版本(因为你开发的东西是要给别的系统使用的,需要依赖系统的支持程度,比方说,之前认为系统也许支持QWidget,愣是看了好久的QWidget相关知识以及css的相关知识,最后放弃,选择看qml。听说:现在市面上都以qml开发为主)

其中有一步最重要的就是需要关联下载mingw和perl,这个需要自己勾选【默认是不勾选的】,





然后【下一步】就可以了。

进入正题


如果你学过js的话,那么就会简单很多

如果你学过Android的话,我会从Android的角度讲讲的

学习Qt的时候一定要知道你将要开发的系统支持的qt版本是多少,否则你用了很多新的api却在对方的平台上面运行异常,这些都是要考虑的

目前最新的qt版本是5.12 ,而我安装的是5.8的,因为目前大多数的设备都支持,一旦遇到不支持的,可能需要采取兼容的方案(即采用对方可支持的版本然后再实现)

最后记得如果遇到不懂的先看帮助文档,因为我遇到了好多本可以看下帮助文档就解决,却花在百度上面好久也没有找到方案的问题。eg:




解读:

  1. qmake 的意思是需要在项目的pro文件中加入 “quick” 的意思 即(QT += quick),才可以支持这个控件。

  2. Instantiated By 和 Inherits 表示实现和继承,所有的控件都是继承自QObject的(类似java的Object,而Qt里面的Item相当于Android的View和ViewGroup,是所有控件的基类)

  3. 如果需要在C++中使用这个控件需要导入include <QQuickItem> ,这一点没有Android的IDE来的好,一键导入所有的包。在Qt里面你需要老老实实的输入导入的头文件,否则你的IDE将联想不出来相关的api,当然编译会有问题的。

以下都是基于

系统:Debian9_64 ,

qt版本:5.8

qml 的布局


如果你在qml文件中,引入import QtQuick.Layouts 1.X,你可以使用的控件可以从右侧的设计板块中看到新引入的控件,一共有四个,分别是ColumnLayout,GridLayout,RowLayout,SplitView





当然可以用拖动来绘制布局,但是建议前期,还是自己学会怎么在qml文件中,编写具体的qml代码。毕竟知道qml的代码有助于你成为一个真正的界面大神,拖拽只是一种辅助而已。

说一下:Grid和GridLayout的区别,其他的布局和控件同理

GridLayout是个一堆控件的排序规则,而Grid是一个控件,这个控件里面还可以拥有控件的控件

qml的控件


import QtQuick.Controls 1.4 如果你加入这个,你就可以看到好多控件可以使用,比方说Button,Label等

简单介绍几个常用的控件
Rectangle 矩形控件

一般可以用来绘制圆角矩形,圆形还可以用作别的控件的子控件用来填充背景颜色。
Rectangle {
id: rectangle2
width: 200
height: 200
color: "#ffffff"
}
MouseArea 响应鼠标点击区域控件

一般用在桌面开发的控件,响应数据点击的事件,如果想用这个控件,而不知道怎么用,那么选中这个控件,然后按F1吧,会有帮助文档的,好好理解,一点有所收获。
MouseArea {
id: mouseArea
width: 100
height: 100
onClicked: console.log("hello world")
}

qml之listView


如果你学过Android那么你知道listview用来展示一堆数据的,可具有上下,或者左右滚动的控件。qt里面也是这样的。

先说怎么编写这个控件,然后再说怎么填充数据。
ListView {
anchors.fill: parent
model: 10
delegate: Text {
property var item:
try{
return modelData
}catch(e){
return ListView.view.model.get(index);
}
property int age: item || item.age
text:age
}
}

其中delegate表示适配器,就是布局需要展示的模样,这里可以加入js的代码来进行一些逻辑处理。delegate后面可以跟你想要的任何控件。 其中modelData表示引用填充的数据,相当于在view中使用具体内容的方式。model表示具体填充的数据。

在js中定义一个变量是var a =1 这里面是可以定义为property var a : 1表示这个值可以通过外部进行设置。

eg:你可以通过在一个控件中声明这个变量来让外部进行赋值,相当于为一个控件增加某个属性。
// Test.qml
Rectangle {
id :root
property var borderColor: "blue"
property var borderWidth: 2
radius: width/2
border.width: borderWidth
border.color: borderColor
}

//Main.qml
Test{
borderWidth: 10
}

接下来讲怎么讲数据绑定到视图。在Android里面可以通过适配器进行设置

介绍一种姿势:其他姿势请看参考资料
ObjectModel{
id:listModel
}
ListView {
id: listView
width: parent.width
height: parent.height
anchors.fill: parent
model: listModel
clip: true
}

//动态添加视图以及数据
function recvTxzSignal(cmd,param)
{
com = Qt.createComponent("qrc:/qml/Usr.qml")
if (com !== null)
{
listModel.append(com.createObject(listView,{json_data:json}))
listView.positionViewAtEnd()
}
}

//Usr.qml
Item {
property var json_data: null
Text{
text:getText(parent.json_data["query"])
}
}

参考资料:

QML 中的 ListView 中的隐藏秘技

qml中c++来填充数据

qml之动画


可以通过查看帮助文档进行查看,切记,帮助文档很强大的。





由图中可以看出基类Animation是所有动画的基类,实现的类有方框中的Inherited By
PropertyAnimation 是属性动画。
AnchorAnimation 是角度动画。
ParallelAnimation 是异步动画,可同时执行
SequentialAnimation 是同步动画,顺序执行

eg:
//表示顺序动画,先执行放大,在执行缩小,从而达到 小->大->小

property var oriChangeBegin: 0.9
property var oriChangeEnd: 0.3
SequentialAnimation {
id:soundAnim
loops: Animation.Infinite
running: true

NumberAnimation {
target: roundWave
property: "scale"
duration: 1000
easing.type: Easing.Linear
from:oriChangeBegin
to: oriChangeEnd
}

NumberAnimation {
target: roundWave
property: "scale"
duration: 1000
easing.type: Easing.Linear
to:oriChangeBegin
from: oriChangeEnd
}
}

当然还有其他动画,记得查看帮助文档。

qml之画布


和android的画布挺像,但是qt的画布,其实就是html的画布
//画个正弦
Item {
id:root
visible: true
width: Math.PI*2
height: 2
// 振幅
property var amplitude: height/2
property var borderWidth: 2
clip: true

Canvas{
id:canvas
width: parent.width
height: parent.height
onPaint: {

var ctx = getContext("2d");
context.reset();
ctx.lineWidth = 2;
ctx.strokeStyle= "blue"
var index = 0;
while (index <= width) {
var endY = (Math.sin(index / width * 2.0 * Math.PI) * amplitude + (height - amplitude)/2);
ctx.lineTo(index, endY);
index++;
}
ctx.stroke();

}

}
}

其中var ctx = getContext("2d"); 参数就只能是2d 然后就是画画了,画圆,画方都支持也可以支持画贝塞尔曲线。

详细文档

qml与c++交互【信号,方法】


通过发信号的方式[这里给出一种方案,其他方案看参考资料]
//main.cpp
QQmlApplicationEngine engine;
ActiveHelper activeHelper;
engine.rootContext()->setContextProperty("$ActiveHelper",&activeHelper); //将引用传递过去给qml进行绑定
engine.load(QUrl(QStringLiteral("qrc:/qml/TestFirstQml.qml")));

//TestFirstQml.qml
import QtQuick 2.6
import QtQuick.Controls 1.4
ApplicationWindow {
visible: true
width: 800
height: 800
id:item
Rectangle{
color: "red"
width: 200
height: 200

MouseArea{
anchors.fill: parent
onClicked: testSignal(item)
}
Component.onCompleted:
{
console.log();
item.width =20;
$ActiveHelper.sig_active.connect(item.testS);// 注意这里绑定信号与槽函数,c++通过发送这个信号可以调用qml中相绑定的方法
$ActiveHelper.activeResult(item) //调用ActiveHelper中的槽函数
}
signal testSignal(var anObject)
}
functiontestS(){
console.log("qml test");
}
}

//ActiveHelper.h
#ifndef ACTIVEHELPER_H
#define ACTIVEHELPER_H
#include <QObject>

class ActiveHelper : public QObject
{
Q_OBJECT
public:
explicit ActiveHelper(QObject *parent = 0);

/**
* @brief 执行激活流程
*/
void active();

/**
* @brief 发送激活信号
*/
void sendSigActive(){
emit sig_active();
}

signals:
/**
* @brief active信号
*/
void sig_active();

public slots:
/**
* @brief 激活结果回来(可能成功,可能失败)
*/
void activeResult(const QVariant &);
};

#endif // ACTIVEHELPER_H

//ActiveHelper.cpp
#include "activehelper.h"
#include "txz_common.h"

ActiveHelper::ActiveHelper(QObject *parent) : QObject(parent){}

void ActiveHelper::active()
{
TXZ_LOGD("active");
}

void ActiveHelper::activeResult(const QVariant &v)
{
TXZ_LOGD("active result");
emit sig_active(); //发送信号
}


参考资料 Interacting with QML Objects from C++

其他


  1. 间距不生效的问题

    在设置相对位置间距的时候,一定要设置相对应的锚边,然后才可以设置边距
    Rectangle {
    id: rectangle
    width: 200
    height: 200
    color: "#ffffff"
    anchors.right: parent.right //一定要设置这个属性,rightMargin才会生效
    anchors.rightMargin: 440
    }

    参考资料: qt帮助文档

  2. 加载不出来界面的问题
    //第一种方式:需要采用ApplicationWindow【window才可以展示】
    QQmlApplicationEngine engine;
    ActiveHelper activeHelper;
    engine.rootContext()->setContextProperty("$ActiveHelper",&activeHelper);
    engine.load(QUrl(QStringLiteral("qrc:/qml/TestFirstQml.qml")));
    //需要以Item等控件才可以展示
    QQuickView view(QUrl(QStringLiteral("qrc:/qml/Test.qml")));
    QQuickItem * item = view.rootObject();
    view.show();

  3. 内容自适应,好像没有找到【不知道有什么方法】

参考资料:

使用gdb进行调试


----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:程序员学习分享录,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!

我有话说......