Extjs5之事件(Events)

事件驱动编程:为需要处理的事件编写相应的事件处理程序,代码在事件发生时执行。extjs是基于事件(Events)来响应用户操作的,extjs的事件分布在组件和类的生命周期的不同点上,事件让你的代码在程序状态发生改变的时候做出响应。 事件是extjs的一个重要概念。

1.什么是事件

有些时候我们需要在事件触发时做一些事情。例如,当Ext.Component呈现到屏幕上,Ext JS的渲染完成之后触发一个事件。我们可以通过配置侦听事件的一个简单的监听器对象来实现:
[code lang=”js”]
Ext.create(‘Ext.Panel’, {
html: ‘My Panel’,
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
Ext.Msg.alert(‘We have been rendered’);
}
}
});
[/code]
效果图

在这个例子中,一打开网页panel渲染到屏幕,紧接着提示窗口出来了。一个类的所有事件在这个类的api文档中列出来了。例如Ext.panel.Panel就有45个事件。

2.添加事件监听
组件的AfterRender是在某些情况下有用,但是其他事件也是非常有用的。例如,Ext.Button的点击事件:

[code lang=”js”]
Ext.create(‘Ext.Button’, {
text: ‘Click Me’,
renderTo: Ext.getBody(),
listeners: {
click: function() {
Ext.Msg.alert(‘I was clicked!’);
}
}
});
[/code]
运行结果

上面例子中我们实现了一个按钮的点击响应,通常一个组件可以包含多个的事件侦听器。在下面的例子中,在监听到鼠标移进来的事件中我们调用this.hide()来隐藏按钮。然后按钮隐藏一秒钟后我们再一次显示按钮。当this.hide()被调用时,该按钮被隐藏,隐藏事件触发。隐藏事件触发了隐藏侦听器,它会等待一秒钟,再次显示按钮:

[code lang=”js”]
Ext.create(‘Ext.Panel’, {
html: ‘My Panel’,
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
Ext.Msg.alert(‘We have been rendered’);
}
}
});
[/code]
运行效果

事件监听器在每一个事件被触发时被调用,这样你就可以随心所欲的隐藏和显示的按钮了。

3.延迟绑定事件监听

前面的例子中我们在创建一个控件的时候绑定了事件的监听器,通常我们还可用使用on函数来延迟添加事件的监听器,例如
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’
});

button.on(‘click’, function() {
Ext.Msg.alert(‘Event listener attached by .on’);
});
[/code]
同样你也可以使用on函数来添加多个事件的监听器,例如前面例子你可以这样实现:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’
});

button.on({
mouseover: function() {
this.hide();
},
hide: function() {
Ext.defer(function() {
this.show();
}, 1000, this);
}
});
[/code]
效果是一样的。

4.移除监听器

就像我们可以在任何时候添加监听器,我们也可以将其删除。这次我们要使用功能是删除一个监听器,要删除一个监听器我们需要得到引用它的控件。在前面的例子中,我们实现了一个按钮的点击事件监听。这一次,我们实现了之前的功能,并将其保存到一个名为doSomething的变量,它包含了我们的自定义函数。最初我们在创建控件的时候绑定doSomething到click事件中,随后我们通过defer方法延迟3秒后将doSomething移除。效果是刚才开始我们点击按钮会弹出一个提示框,三秒后点击就什么反应都没了。
[code lang=”js”]
var doSomething = function() {
Ext.Msg.alert(‘listener called’);
};

var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’,
listeners: {
click: doSomething,
}
});

Ext.defer(function() {
button.un(‘click’, doSomething);
}, 3000);
[/code]

5.配置监听器的作用域(Scope)

Scope是事件处理函数的一个内置属性,默认情况下Scope的值是当前控件。但是有些时候我们要实现某些特别的功能需要修改他的Scope,比如我们稍微改动一下前面的例子,我们将按钮的Scope设置为我们创建的panel,然后在点击的时候显示出当前的xtype。
[code lang=”js”]
var panel = Ext.create(‘Ext.Panel’, {
html: ‘Panel HTML’
});

var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’
});

button.on({
click: {
scope: panel,
fn: function() {
Ext.Msg.alert(this.getXType());
}
}
});
[/code]
运行效果:

从运行效果我们看看到打印处理的xtype是panel,这说明了事件的作用域已经被改变。

6.只响应一次事件

有些时候我们对一个事件的响应只需要响应一次,但是这个事件有可能会被多次触发,下面的代码可以实现我们的需求:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’,
listeners: {
click: {
single: true,
fn: function() {
Ext.Msg.alert(‘I will say this only once’);
}
}
}
});
[/code]

7.配置缓冲器(消抖)

有些事件在短时间内被触发多次,我们可以通过配置一个缓冲器的缓冲次数。在这种情况下我们的按钮的click侦听器两秒内只调用一次,不管你有多少次点击它,代码如下
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’,
listeners: {
click: {
buffer: 200,
fn: function() {
Ext.Msg.alert(‘I say this only once every 2 seconds’);
}
}
}
});
[/code]

8.制定自定义事件

自定义事件可以通过事件名字作为参数调用fireEvent函数来触发,例如下面的例子实现了一个名字为myEvent两个参数的事件,一个参数是按钮本身,一个参数是1到100的随机数:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: "Just wait 2 seconds",
listeners: {
myEvent: function(button, points) {
Ext.Msg.alert(‘myEvent fired! You score ‘ + points + ‘ points’);
}
}
});

Ext.defer(function() {
var number = Math.ceil(Math.random() * 100);

button.fireEvent(‘myEvent’, button, number);
}, 2000);
[/code]

我们通过Ext.defer函数延时两秒触发了这个事件。

9.监听dom事件

并不是每一个ExtJS的组件都能引发每个事件,例如容器的元素就没有click事件。我们可以将许多原生事件添加给组件就可以监听了。在这个例子中,我们的目标Ext.Container,容器没有一个click事件,让我们给它实现一个

[code lang=”js”]
var container = Ext.create(‘Ext.Container’, {
renderTo: Ext.getBody(),
html: ‘Click Me!’,
listeners: {
click: function(){
Ext.Msg.alert(‘I have been clicked!’) // This won’t fire without the code below
}
}
});

container.getEl().on(‘click’, function(){
this.fireEvent(‘click’, container);
}, container);
[/code]

如果没有第二块代码,容器的点击监听器将不会触发。我们为容器元素添加了点击监听器,我们增强了容器的事件的能力。

10.事件的统一化

事件统一化是让Ext JS的5应用程序在触摸屏设备上运行的关键。这种统一化发生在幕后,是从标准的鼠标事件的简单翻译为等效的触摸和指针事件。标准的W3C指针事件是一组在屏幕上的坐标,不管输入设备(鼠标,触摸,手写笔等)

当你的代码需要监听鼠标事件,只需要在控件附加一个类似的触摸或指针事件。例如,如果应用程序监听一个鼠标按下监听器:
myElement.on(‘mousedown’, someFunction);
触摸开始:
myElement.on(‘touchstart’, someFunction);
指针按下:
myElement.on(‘pointerdown’, someFunction);

这个翻译很到位,让你可以实现平板电脑和触摸屏的支持,而无需任何额外的编码。
在大多数情况下,该框架可以通过鼠标,触摸和指针输入之间的无缝转换。然而,也有一些鼠标交互(如鼠标悬停),不容易转化为触摸交互。这些事件将需要一个单独的基础上处理,并在下面的章节中讨论。

11.手势

除了标准的DOM事件,元素也实现了“手势”事件。基于Sencha Touch触摸事件系统构成的基础,在Ext JS的5新的事件系统中Sencha Touch用户可能已经熟悉了这个概念。
从浏览器的角度来看,鼠标、触摸、指针也有三个主要的事件包括start, move, 和 end:

通过处理这些事件的顺序和时间,该框架可以合成更复杂的事件,如拖动,轻扫,长按,捏,旋转和点击。 Ext JS的应用程序可以监听手势事件就像其他任何事件,例如长按:
Ext.get(‘myElement’).on(‘longpress’, handlerFunction);

原来Sencha Touch手势系统主要考虑触摸事件来设计。通过增加对指针和鼠标事件的手势系统的全面支持使得Ext JS5可以对任何类型的输入作出响应。这不仅意味着所有的手势可以使用触摸事件触发,而且所有单点手势(点击,拖拉等)可以使用鼠标事件触发。这导致一个手势系统,无缝跨越各种输入不同输入系统的设备。

Extjs5之Widgets 和 Widget Column

该Ext.Widget类,或者只是“小部件”,类似于组件的一个轻量级类,但仅由一个Ext.dom.Element和相关的监听器构成。由于Ext.Widget类不是从Ext.Component派生使得widget跟其他普通的组件(component)不同。组件提供了强大的生命周期管理器,它增加了巨大数额的功能。然而这些功能带来一些开销。

Ext JS 5提供几个股票小部件,包括:

Progress Bar (Ext.ProgressBarWidget or “progressbarwidget”)
Slider (Ext.slider.Widget or “sliderwidget”)
Sparklines (Ext.sparkline.*)
Line (“sparklineline”)
Bar (“sparklinebar”)
Discrete (“sparklinediscrete”)
Bullet (“sparklinebullet”)
Pie (“sparklinepie”)
Box (“sparklinebox”)
TriState (“sparklinetristate”)

在本节中,我们将介绍如何使用和创建小部件。我们还将探索我们的最新创作,小工具栏。

1.使用Widgets
跟普通组件一样,widgets可以添加到容器的items中,下面的例子中,我们把sparkline(走势图)添加到toolbar中

[code lang=”js”]
var panel = Ext.create({
xtype: ‘panel’,
title: ‘Title’,
frame: true,
renderTo: Ext.getBody(),
width: 250, height: 150,
html: ‘Some text’,
tbar: [{
text: ‘Button’
}, ‘->’, {
xtype: ‘sparklineline’,
fillColor: ‘#ddf’,
width: 100,
height: 20,
values: [2, 3, 0, 4, -1]
}]
});

[/code]

效果图:

就sparklines而言,你必须提供一个尺寸(包括宽度和高度)或者使用一个Ext JS layout来使用它。 这是因为widgets需要一个确定的尺寸来绘制图形。

2.使用Widgets Column
为了更方便使用Ext JS很容易的将组件添加到gird中。下面我们一起跟Widget Column 说 hello。
Widget Column让你很轻松添加component或者widget到grid的cell中,之前是不可以的。仅仅是将你的column的xtype属性设置为widgetcolumn并指定它的 widget配置. widget配置包含xtype去创建每个cell。关于xtype可以参考任何Ext.Widget 或者 Ext.Component 类.

使用widget column来添加sparkline widgets到grid中你可以实现下图效果

对于上图效果,更完整的例子请访问Kitchen Sink. (http://dev.sencha.com/deploy/touch/examples/production/kitchensink)

废话少说, 接下来让我们用事实证明。接下来的例子我们创建一个小的记录集(store)来填充一个使用了widget column的grid。这个widget column中每一行都拥有一个progress控件。
[code lang=”js”]
var store = Ext.create(‘Ext.data.Store’, {
fields: [‘name’,’progress’],
data: [
{ name: ‘Test 1’, progress: 0.10 },
{ name: ‘Test 2’, progress: 0.23 },
{ name: ‘Test 3’, progress: 0.86 },
{ name: ‘Test 4’, progress: 0.31 }
]
});

Ext.create({
xtype: ‘grid’,
title: ‘Widget Column Demo’,
store: store,

columns: [{
text: ‘Test Number’,
dataIndex: ‘name’,
width: 100
}, {
xtype: ‘widgetcolumn’,
text: ‘Progress’,
width: 120,
dataIndex: ‘progress’,
widget: {
xtype: ‘progressbarwidget’,
textTpl: ‘{value:percent}’
}
}],

width: 220,
height: 250,
renderTo: Ext.getBody()
});

[/code]

效果如下

3.理解“widget”配置
一个widget的配置是widget column用于创建小部件实例。基于包含在该插件的配置的xtype,widget column创建一个无论是从Ext.Widget或从Ext.Component派生的对象,这个配置都不能是一个实例因为widget column需要为cell提供一个实例。

然而widget配置用于创建所需的组件或部件的多个实例时,每个实例必须与网格中的特定记录和行连接,在cell的生命周期中一个行创建的widget将被“回收”,并且连接到不同的记录和行。

4.使用缓冲渲染
widgets中权重组件和进度条或滑块构件可以使您的网格响应能力更强,如果您的网格是可能包含更多的行,少数时要使用的”bufferedrenderer”插件。Bufferedrenderer 创建固定的数量的组件或窗口小部件。这些项目是从未呈现行回收然后添加到新创建的行

5.自定义Widgets
虽然 Ext JS 5 沿用”widget-ized”版本的滑块和进度条,以及新的sparklines,但是很有可能你需要自己创建一个自定义Widgets。

通过继承Ext.Widget和定义一些元素模板以及相应的监听来创建一个自定义widget
[code lang=”js”]
Ext.define(‘MyWidget’, {
extend: ‘Ext.Widget’,

// The element template – passed to Ext.Element.create()
element: {
reference: ‘element’,
listeners: {
click: ‘onClick’
},
children: [{
reference: ‘innerElement’,
listeners: {
click: ‘onInnerClick’
}
}]
},

constructor: function(config) {
// Initializes our element from the template, and calls initConfig().
this.callParent([config]);

// After calling the superclass constructor, the Element is available and
// can safely be manipulated. Reference Elements are instances of
// Ext.Element, and are cached on each Widget instance by reference name.
},

onClick: function() {
// Listeners use this Widget instance as their scope
console.log(‘element clicked’, this);
},

onInnerClick: function() {
// Access the innerElement reference by name
console.log(‘inner element clicked’, this.innerElement);
}
});
[/code]

这看起来像Sencha Touch组件。这是因为 Ext.Widget 是Sencha Touch的Ext.AbstractComponent 增强的版。将监听器添加到元素模板的能力是一种增强功能,但有极少数的改变。请参阅在 Ext.Widget 上的更多详细信息的文档。

extjs5之helloWord

1、下载 sdk

官方下载地址:http://www.sencha.com/products/extjs/download/ (下载时要填写 e-mail)

2、目录说明

 

  • bootstrap.js 根据不同的使用环境以决定是应用ext开发调试包还是ext运行包
  • ext-all.js ext运行包,包含ext标准版所有的压缩代码
  • ext-all-debug.js ext开发调试包,包含ext标准版所有的未压缩代码
  • ext-all-debug-w-comments.js ext带注释的开发调试包,包含ext标准版所有的未压缩代码,并且带有注释
  • ext.js ext核心包,仅包含ext核心应用的压缩代码
  • ext-debug.js ext核心调试包,仅包含ext核心应用的未压缩代码

 

 

3、引入lib 文件并编写代码

 

[code lang=”js”]<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>
学习extjs
</title>
<link href="http://localhost/ext5.0.0/build/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all-debug.css" type="text/css" rel="stylesheet">
<script src="http://localhost/ext5.0.0/build/ext-all.js" type="text/javascript">

</script>
</head>

<body>
<script>
Ext.require([‘Ext.window.Window’]);

Ext.onReady(function() {
var win = Ext.create(‘Ext.window.Window’, {
autoShow: true,
title: ‘提示’,
width: 500,
height: 300,
minWidth: 300,
minHeight: 200,
layout: ‘fit’,
plain: true,
html:’你好!ext5.0′,
buttons: [{
text: ‘确定’
}]
});
});
</script>
</body>

</html>[/code]

运行效果如下图

上面代码大概分析下,首先引入ext-theme-crisp-all-debug.css和ext-all.js两个库文件,然后Ext.require([‘Ext.window.Window’]);这句导入我们需要用到的控件。在Ext.onReady事件被调用的时候创建一个窗口,然后显示窗口。

–每天一点点

Mavericks配置Apache

Apache配置

Mavericks同以往的OSX一样自带了apache2.2.24和php5.4.17,但默认情况下没有开启,打开终端

1
sudo apachectl start
这时在浏览器中输入localhost应该就会出现apache标准的It Works! 下面开启php,修改apache配置文件
1
sudo vim /etc/apache2/httpd.conf
找到 #LoadModule php5_module libexec/apache2/libphp5.so,去掉前面的# 默认的www文件夹非常不方便,还是改成在home里开发起来比较顺手,修改apache配置 ,还是上面的文件
1
#将引号中的目录修改为自己的目录
2
DocumentRoot “/Library/WebServer/Documents”
3
……
4
#将引号中的目录修改为和上面一样的目录
5

在自己的目录中创建文件index.php,写入
1

在浏览器中访问localhost,应该显示出php的info页。

ListView与Button、imageButton 的共存问题解决

昨天遇到ListView的setOnItemClickListener没响应问题好不容易才找的问题所在。原来是ImageButton跟ListView焦点冲突了,很少处理焦点问题,这次是长见识了。

自定义的listview的item里面有ImageButton、Checkbox等获取焦点的子控件时,为了仍保留点击想点击效果,以及listview的onItemClickListener事件,需要如此做:

1、在item的根布局添加一下属性:

android:descendantFocusability=”blocksDescendants”
2、在ImageButton的获取焦点的控件添加一下属性:

android:focusable=”false”
如此,就可以在setOnItemClickListener中实现item中的文本TextView的点击事件;

mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView arg0, View arg1, int position, long arg3) {

if (Constant.isDebugMode) {
Log.d(TAG, “列表被点击了”);
}

}
});
在自定义的Adapter中实现子控件ImageButton中的点击事件;

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.favorite_detail, null);

mViewHolder = new ViewHolder();
mViewHolder.textview = (TextView) convertView.findViewById(R.id.title);
mViewHolder.imageButton = (ImageButton) convertView.findViewById(R.id.deleteBtn);

convertView.setTag(mViewHolder);
} else {
mViewHolder = (ViewHolder) convertView.getTag();
}

// 设置文本
mViewHolder.textview.setText(mLifeTitleList.get(position));

// 删除按钮监听事件
mViewHolder.imageButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//do something here
}
});

return convertView;
}

–每天一点点

Activity设置android:process

Activity设置android:process可以使得activity以新的进程打开。

android的oom是一个非常头痛的问题,特别是产品的图片比较多,而且分辨率高,页面多。就算是没有泄露也很容易照成oom。

android限制了每个进程占用的内存大小。所以通过Activity设置android:process可以创建一个新的进程互不影响的确是一个解决方案。这个还没在实际项目中试过,毕竟规范代码的编写习惯才是最好的。

–每天一点点

android获取view大小的方法

通过View.inflate(context, R.layout.xml, null);可以成xml中加载view。

android的四大布局非常强大,但是这种情况下想要获取所创建的view大小,如果直接使用getWidth(),获取到的将会是0.所以得通过其他方法

首先调用一下
view.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED)
然后就可以获取到正确的大小了
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();

用来实现下图效果非常好用

–每天一点点

deb脚本配置

deb安装前后通常需要做一些环境的配置,比如复制文件,添加权限等。当时通常的app没有root权限,很多动作的做不了,所以从deb安装包的脚本下手是一个不错的idea。

标准的 deb 脚本有4个, preinst, postinst, prerm 和 postrm ; 在 Cydia 中还存在一 个独立的脚本, extrainst_ , 从字面上来讲就是额外的安装脚本.
* preinst 在复制文件前执行的脚本
* postinst 在复制文件之后执行的脚本
* prerm 在卸载前执行的脚本
* postrm 在卸载之后执行的脚本
* extrainst_ 这个脚本是为解决某些脚本只需要在安装时执行, 在升级时不执行
而专门引入的一个脚本, 功能跟postinst差不多

比如我们需要在程序运行之前复制一个安装包到/var/root/Media/Cydia/AutoInstall文件夹,以达到重启后安装另外一个包的效果。只需要在postinst脚本中加入以下代码
#!/bin/sh
/bin/cp -f /xxx/xxx/xxx/* /var/root/Media/Cydia/AutoInstall

chmod 777 /var/root/Media/Cydia/AutoInstall/*

还需要给postinst文件加权限

–每天一点点

用itools提取cydia中下载的deb安装包

How to Download Deb Files From Cydia
Note: You must have a jailbroken device to use this tutorial.
注意:您的设备必须是已经被越狱(废话处理,因为CYDIA本来就是越狱才能使用的。)

Step 1: Connect to iPhone via FTP or another iPhone file utility
使用iTools等软件连接您的iPhone。
Step 2: Navigate to /private/var/cache/apt/archives
使用文件管理功能,进入路径 /private/var/cache/apt/archives
Step 3: Download an app or tweak from Cydia, but don’t reboot or restart springboard
在Cydia中下载你所需要的应用程序,但是下载安装完毕后不要点击 reboot 或者是 restart Springboard.
Step 4: Refresh the /private/var/cache/apt/archives directory, and you should see your .deb file ready for download
刷新 /private/var/cache/apt/archives 这个路径后,你就可以看见您所需要的deb文件已经被下载好了!。

–每天一点点

cocos2d-x新建工程分析

新建工程后目录结构如下

从xcode上看到的是下面这样的

我们要看的代码主要是Classes分组内,其他代码的主要作用是解决各平台环境的初始化。

首先看AppDelegate.cpp

这段代码是用户启动app后调用,可以看出这里创建了一个导演(director)对象,然后设置了OpenGLView,设置导演显示性能状态和帧频率。并创建了一个HelloWorld的场景(scene)并显示此场景。

接下来看HelloWorldScene.cpp
bool HelloWorld::init()里面是一些初始化场景的函数,比如设置可视区域和获取坐标原点。
MenuItemImage::create(
“CloseNormal.png”,
“CloseSelected.png”,
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
创建了一个按钮,并设置了监听函数

LabelTTF::create(“Hello World”, “Arial”, 24);
创建了一个文字图层,添加到场景中

Sprite::create(“HelloWorld.png”);
通过图片创建了一个精灵,添加到场景中

void HelloWorld::menuCloseCallback(Ref* pSender)
是点击按钮后的回调函数

看来cocos2d-x代码结构非常清晰,容易理解

–每天一点点