QML 从入门到放弃 第二卷
第二卷如何更快速的放弃,注重的是C++和QML的交互
<1>记事本。。

(1) 先测试下不在QML创建C++对象,仅仅在main.cpp添加一个属性函数供调用. 注意只使用槽函数来做到。
TextStreamLoader.h
#ifndef TEXTSTREAMLOADER_H
#define TEXTSTREAMLOADER_H #include <QObject>
#include <QTextStream>
#include <QDebug>
class TextStreamLoader : public QObject
{
Q_OBJECT
public:
explicit TextStreamLoader(QObject *parent = );
void test2(){qDebug()<<"test 2 without slots";}
signals:
void signal_readFile(QString buffer);
void signal_error(QString errorMsg);
void signal_saveFile(QString file,QString buffer);
public slots:
void slot_readFile(QString file);
void slot_saveFile(QString file,QString buffer);
void slot_test(){qDebug() << "test C++";}
QString slot_getBuffer(); private:
QString _buffer;
}; #endif // TEXTSTREAMLOADER_H
TextStreamLoader.cpp
#include "TextStreamLoader.h"
#include <QFile>
#include <QUrl>
TextStreamLoader::TextStreamLoader(QObject *parent) : QObject(parent)
{
qDebug() << "Construct the TextStreamLoader";
connect(this,&TextStreamLoader::signal_saveFile,
this,&TextStreamLoader::slot_saveFile);
} void TextStreamLoader::slot_readFile(QString file) // read a file to the _buffer
{ QUrl url(file);
QString localFile = url.toLocalFile(); QFile rfile(localFile);
if(!rfile.open(QIODevice::ReadOnly))
{
QString errorMsg = "Could not open " + file + "\n";
qDebug() << errorMsg;
emit signal_error(errorMsg);
return ;
} QTextStream in(&rfile);
_buffer = in.readAll();
emit signal_readFile(_buffer); rfile.close(); } void TextStreamLoader::slot_saveFile(QString file, QString buffer)
{
QUrl url(file);
QString localFile = url.toLocalFile();
QFile wfile(localFile);
if(!wfile.open(QFile::WriteOnly))
{
QString errorMsg = "Could not open " + localFile + "\n";
qDebug() <<errorMsg;
emit signal_error(errorMsg);
return ;
} QTextStream out(&wfile);
out << buffer;
wfile.close();
} QString TextStreamLoader::slot_getBuffer()
{
return _buffer;
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "TextStreamLoader.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv); QQmlApplicationEngine engine;
QQmlContext *context = engine.rootContext(); // 注意对象是在C++里构建
TextStreamLoader stream_01;
context->setContextProperty("stream_01",&stream_01);
// 构建完C++对象 // 加载我们的QML界面,只能调用槽函数
qDebug() << "load the main.qml";
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); qDebug() <<engine.rootObjects()[]->objectName(); // this will be debug "Houdini" return app.exec();
}
main.qml 用最简单的测试下我们的TextStreamLoader 里面的 "test()槽函数",一定要是槽函数才能被调用。
main.qml全部都是通过调用C++的对象的槽函数,而C++对象是在main.cpp创建,所以在qml随时可以访问 槽函数。
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.1
import QtQuick.Dialogs 1.2
Window
{
id:root
objectName: "Houdini"
visible: true
width: 640
height: 480
title: qsTr("Hello World")
color:"#202020"
function loadTextToTextEdit(text)
{
textEdit.clear()
var buffer = stream_01.slot_getBuffer()
textEdit.append(buffer) }
function saveTextToDisk(file,buffer)
{
stream_01.slot_saveFile(file,buffer)
} Column
{
id:mainLayout
padding: 5
spacing: 10
Row
{
id:buttonLayout
spacing: 10
Button
{
id:loadButton
text:"load file"
highlighted: true
onClicked:
{
openDialog.open()
}
}
Button
{
id:saveButton
highlighted: true
text:"save file"
onClicked:
{
saveDialog.open()
}
} }
Rectangle
{
height: 1
width: root.width
id:menuRect
color:"brown"
} Flickable
{
id:flick
width: root.width; height: root.height;
contentWidth: textEdit.paintedWidth
contentHeight: textEdit.paintedHeight
clip: true
function ensureVisible(r)
{
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x+r.width)
contentX = r.x+r.width-width;
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit
{
width: flick.width
height: flick.height
anchors.margins: 10
focus: true
id:textEdit
text: ""
color:"brown"
font.family: "Helvetica"
font.pointSize: 10
font.bold: true
cursorVisible: true
selectByKeyboard: true
selectByMouse: true
wrapMode:TextEdit.WrapAnywhere
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle) }
} }
FileDialog
{
id:openDialog
title: "Please choose a file"
folder: shortcuts.home
onAccepted:
{
console.log("You chose: " + openDialog.fileUrls)
stream_01.slot_readFile(openDialog.fileUrls)
var buffer = stream_01.slot_getBuffer()
loadTextToTextEdit(buffer) }
onRejected:
{
console.log("Canceled")
}
}
FileDialog
{
id:saveDialog
title:"Save to a file"
folder: shortcuts.home
selectExisting : false
onAccepted:
{
console.log("Save file : " + saveDialog.fileUrls)
var text = textEdit.text;
saveTextToDisk(saveDialog.fileUrl,text); }
onRejected:
{
console.log("Canceled")
} } }
(2)
这次变化使用了QML里的connections.
可以调用C++里的signal,signal带参数也可以传递过来。注意查看新的main.qml
代码区别就是读取用的C++信号读取的。
保存时用的信号在QML发射,然后调用C++的信号槽链接,来执行slot_saveFile()函数。
main.qml:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.1
import QtQuick.Dialogs 1.2
Window
{
id:root
objectName: "Houdini"
visible: true
width:
height:
title: qsTr("Hello World")
color:"#202020"
function loadTextToTextEdit(text)
{
textEdit.clear()
var buffer = stream_01.slot_getBuffer()
textEdit.append(buffer) }
function saveTextToDisk(file,buffer)
{
stream_01.slot_saveFile(file,buffer)
} Column
{
id:mainLayout
padding:
spacing:
Row
{
id:buttonLayout
spacing:
Button
{
id:loadButton
text:"load file"
highlighted: true
onClicked:
{
openDialog.open()
}
}
Button
{
id:saveButton
highlighted: true
text:"save file"
onClicked:
{
saveDialog.open()
}
} }
Rectangle
{
height:
width: root.width
id:menuRect
color:"brown"
} Flickable
{
id:flick
width: root.width; height: root.height;
contentWidth: textEdit.paintedWidth
contentHeight: textEdit.paintedHeight
clip: true
function ensureVisible(r)
{
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x+r.width)
contentX = r.x+r.width-width;
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit
{
width: flick.width
height: flick.height
anchors.margins:
focus: true
id:textEdit
text: ""
color:"brown"
font.family: "Helvetica"
font.pointSize:
font.bold: true
cursorVisible: true
selectByKeyboard: true
selectByMouse: true
wrapMode:TextEdit.WrapAnywhere
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle) }
} } Connections
{
target: stream_01
onSignal_readFile://当读取文件的时候回触发这个信号
{
var readText = buffer //buffer是signal_readFile(buffer)参数
textEdit.clear()
textEdit.append(readText)
}
} // 读取文件的窗口
FileDialog
{
id:openDialog
title: "Please choose a file"
folder: shortcuts.home
onAccepted:
{
console.log("You chose: " + openDialog.fileUrl) //这句话会触发signal_readFile信号
stream_01.slot_readFile(openDialog.fileUrl)
}
onRejected:
{
console.log("Canceled")
}
}
//保存文件窗口
FileDialog
{
id:saveDialog
title:"Save to a file"
folder: shortcuts.home
selectExisting : false
onAccepted:
{ console.log("Save file : " + saveDialog.fileUrl)
var text = textEdit.text; //保存触发信号,在C++中这个信号会触发保存
stream_01.signal_saveFile(saveDialog.fileUrl,text) }
onRejected:
{
console.log("Canceled")
} } }
(3)Q_PROPERTY宏,如果你想暴露一些member给QML对象。
Q_OBJECT Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
QString message(){return _msg;}
void setMessage(QString msg)
{
_msg = msg;
emit messageChanged();
}
类型如下:
Q_PROPERTY(任意类型 QML访问属性名 READ 读取函数名 WRITE 写的函数名 NOTIFY 信号触发)
<2>Q_INVOKABLE 宏,让QML可以随心所以调用函数。跟槽槽函数,信号一样调用。
<3>在C++修改QML对象的属性,从C++call javaScript
(1)修改qml root object的对象属性
qDebug() <<engine.rootObjects()[]->objectName(); // this will be debug "Houdini"
QObject *root_object = engine.rootObjects().value(); // houdini object ,it's the main object // set QML object property
//root_object->setProperty("x",600);
QQmlProperty::write(root_object, "x", ); // read QML object property
qDebug() << root_object->property("x").toInt();
qDebug() << QQmlProperty::read(root_object,"x").toInt(); // read root object child by name
//QObject *rect = root_object->findChild<QObject*>("rect");
(2) 假如qml root object 有个java函数:
function javefunctest(arg)
{
console.log(arg);
return "I'm jave script"
}
C++访问:
QObject *root_object = engine.rootObjects().value(); // houdini object ,it's the main object
QVariant firstArg("I am C++ arg");
QVariant retValue; // call the jave script
QMetaObject::invokeMethod(root_object,
"javefunctest",
Q_RETURN_ARG(QVariant,retValue),
Q_ARG(QVariant,firstArg)); qDebug() << "ret value is " << retValue;
输出:
qml: I am C++ arg
ret value is QVariant(QString, "I'm java script")
<4> EMCA:
(1) 基本类型
var flag =false //a boolean
var x =1,y=2
var str = 'abc' / "abc"
var test = {x:2,y:3}
console.log(test.x) //
console.log(test.y) //
test// object
(1) typeof()类型 关键字
To query the type of a variable, use the typeof keyword. typeof returns the name of the
type as a string.
var x=1;
typeof(x) //"number"
typeof {x:1} //'object '
typeof typeof { x : 1 } // ’string’ 因为typeof()返回的是字符串.
(2) 转换类型
1.3333333.toFixed(2) // ’1.33’
7..toString() // ’7’
(3) 可以显式的把boolean ,number,string转换成对象:
typeof 1. // ’number’
typeof new Number(1.) // ’object’
typeof new String(’Hi!’) // ’object’
(4)
Objects themselves can be expressed using an array or object literal. Arrays have no separate
type, but are specialized objects which use array indexes as properties:
var o = { name: ’Werner’, age: 84 } // allocate simple object
print(o.name, o[age])
// both notations are valid, but [] notation allows generated strings
var a = [’a’, ’b’, 7, 11.]
// an array, equivalent to {’0’: ’a’, ’1’: ’b’, ’2’: 7, ’3’: 11.}
typeof o, a // ’object’, ’object’
(2)函数
函数:所有的函数都会evaluates to something:
function f() {} //evaluates as 'undefined'
function f() {} +1 // evaluates as 1 ,because 'undefined' is casted to 0
(function f() {}) //evaluates to a function object
(function () {return 0;}) () /evaluates as 0
(3)
for loop :

i 作为了index

(4)

delete p.z // remove p.z
p.z //undefined
(5)在列表中存入,或者在json对象中存在函数

(6) 创建对象new关键字
(1)

(2)创建对象默认构造函数:
这个时候Point其实就是个类。

为Point类添加个函数.
Each function in JavaScript can be used as a constructor in combination with the new operator.
To support inheritance, each function has a default property named prototype. Objects
created from a constructor inherit all properties from the constructor’s prototype. Consider the
following example:

其实 prototype里面的方法属于派生出来的,如何检查一个方法,或者一个类对象是原有的:

<2>公司一个小项目
按钮效果模仿的是Google material design风格。流动起来。参考上篇有详细代码.

V2:

3,CG Browser

New Version:0.00001

QML 从入门到放弃 第二卷的更多相关文章
- QML 从入门到放弃
发现了一个问题: QQuickView only supports loading of root objects that derive from QQuickItem. If your examp ...
- Python从入门到放弃系列(Django/Flask/爬虫)
第一篇 Django从入门到放弃 第二篇 Flask 第二篇 爬虫
- WPF从入门到放弃系列第二章 XAML
本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳. 参考资料 XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn ...
- [精品书单] C#/.NET 学习之路——从入门到放弃
C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...
- OpenStack从入门到放弃
OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...
- 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃
一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(一)
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
随机推荐
- 网络运维必回的模拟器-GNS软件下载和安装
网络运维必回的模拟器-GNS软件下载和安装 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.GNS简介 1>.什么是GNS GNS3是一款具有图形化界面可以运行在多平台( ...
- Ubuntu 下使用 putty并通过 ch340 usb 串口线进行调试
安装putty sudo apt-get install putty -y 插入usb转串口线 由于linux下没有Windos类似的设备管理器,所以我们可以通过其他方法获取对应的串口号 可以在插拔之 ...
- STM32学习笔记:【002】BIN文件通过ST-LINK烧录STM32芯片
以下提供2种下载方式 KEIL编译下载 KEIL 5 在开发中还算是比较强大的一种平台.在开发中通过编译再下载会显得很方便. 尽管这个是老生常谈的问题,但还是在这里补全这个设置步骤 1.点击“魔法棒” ...
- getResource()和getResourceAsStream以及路径问题【转】【补】
一 getResource 用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就 ...
- java 中对象比较大小
java 中对象比较大小 java 中对象比较大小有两种方法 1:实现Comparable 接口 的 public int compareTo(T o) 方法: 2:实现Comparator 接口 的 ...
- 【六】Hystrix Dashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard) , Hystrix会持续地记录所有通过 Hystrix发起的请求的执行信息,并以统计报表和图形 ...
- 28. SpringBoot 集成Redis
1.引入依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- springboot10-springcloud-eureka 服务注册与发现,负载均衡客户端(ribbon,feign)调用
创建5个项目: 1.服务注册中心 2.服务提供者1 3.服务提供者2(与服务提供者1的代码实现一样,这是是为了模拟负载均衡) 4.ribbon客户端项目 5.feign客户端项目 如图: 一.注册中心 ...
- PHP实现权限管理功能
权限管理系统,它主要是为了给不同的用户设定不同的权限,从而实现不同权限的用户登录之后使用的功能不一样. 首先先看下数据库 总共有5张表,users,roles和roleswork 3张表与另外2张表形 ...
- MyList 泛型委托
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...