之前在写 [10/02周主题] – 仿Gmail头像上传剪辑 时说,还有个JQuery的分页组件分享给大家,这个组件是别人设计的,我只是在其基础上,进行一些改动,以符合自身项目的需求。
之前在做Web项目时,分页功能的处理是放在服务器端,客户端只是用来显示分页导航条内容。 虽然将服务器端的分页功能进行封装,页码显示代码也进行了整理,但是总归不是很方便,做分页功能还是要做不少工作。
后来去看一些将分页功能放在客户端处理的例子,最后发现了这个比较不错的JQuery组件(如果你有好的方案也欢迎分享啊),原文章在这里:http://lym6520.javaeye.com/blog/540580,我就不做过多介绍了。
通过这个组件做分页功能,服务器端几乎不做什么处理,只需要显示数据列表时把总数传给该组件即可。至于分页组件的样式你完全可以自己去定制。
下面分享下自己的一些优化工作:
1、Loading和错误提示
Loading和错误信息的显示在获取数据时控制,这里用到了Ajax的几个状态来判断,比如beforeSend,success以及error。
2、分页组件的翻页和获取数据是异步的,这样如果出现服务器问题,无法获取翻页后的信息,但是分页导航条已经做了翻页了。由于服务器出错是在Ajax里面捕获的,这样就只能做个hack,通过dom操作来让翻页返回去,最终的效果会是这样的:假如现在在第三页,要跳转到第四页,点 “4” 翻页了,然后发现翻页后无法获取数据,出现服务器问题了,接着就又返回第三页了,显示错误信息。
2月份回家过年了,这个月的周主题选定了过年回家的一些见闻,看看农村的一些变化,和一些你不知道的事儿。
今年的火车票真TM的难买,看形势不对,也第一次开始排队买票,排第一个还买了座票,不得不操下铁道部,以及没良心的火车票代售点,压票不出。票贩子的票价也翻翻了,两百多的票,开口就是五六百。
火车晚点快1个小时到站了,凌晨6点到,家里下了雪,不小,车站封了,有几辆黑车在拉人,因为没国营公车,只能坐黑车了,票价已经翻番了,你不坐还找不到其他车了,运气不好的,半路就把你撂下,还不退钱,有理你也没地方说去。
上面说了黑车拉人,这里要说的是严重超载的问题,我当时坐的车15人左右的座位,中间加凳子多拉了10个,因为是春节,即使下雪,交警还是时不时出来查超载的,这辆车本来是想碰碰运气的,结果听前方通风报信的说有交警,于是就半路把10个乘客丢下了,漫天大雪,本来就车辆紧张的情况下,中途下车的后果基本上就是活受罪,能等到有座的车算中大奖了。唉,无语啊!
下雪路滑,小心漂移,一路上看到不少车撩路两边了,有两车相撞的,有碰水渠上的,有玩翻转,唉,大过年的,人要没事还好点,人要有事,这一家子过啥年啊。
这几年回家几次给我印象最深的,莫过于黑煤窑了,我们家乡是苹果之乡可近几年基本上是荒了,支撑经济的只有煤炭了,正规的煤炭企业养了县政府,黑煤窑养了煤窑所在村的村民,但是大部分钱都流到外省人手里,因为不管是正规煤炭企业还是黑煤窑基本上都是有钱的外省人,以山西人居多开的,要么就是本地人开卖给外地人。过年15天,黑煤窑是24小时加紧生产,一条山沟里黑煤窑不下200个,白天加紧生产,晚上往外运煤,村里不少人过年也没闲着啊。
现在的农村不是以前的农村了,农民的憨厚质朴也随着社会风气变的无情和自私,在家呆了好几天就遇上好几起事故,伤者躺在马路上没人管,路人估计也没人敢管,怕赖在自己身上。
说农村不是以前的农村,另一点就是农民的信誉现在可谓是到了低谷了,至少我感觉在我们那里是这样的,现在在村里弄个什么事情想筹点钱,可谓比上天难,甚至比贷款难多了,现在是没人敢借。
UED – 英文User Experience Design的缩写,中文翻译:用户体验设计。
关于UED更多信息可以Google之,本周分享下这几天收集的一些和UED有关的案例,在实际的项目中还是有些帮助的。
我们的按钮一般都是成对出现,比如提交和取消,保存和取消等,突出你认为重点的按钮,降低有消极面的按钮,甚至只给用户一个选择,比如注册,只能一路Next,当然这需要根据具体场景来分,但是让用户思考如何下一步,不如从我们的角度突出重点的建议用户就走这一步。
2、导航的标签设计
好的标签,应该使用客户的语言,避免使用术语、行话、缩写词等用户难以理解的词语;标签之间的互斥性要强,尽可能地寻找差异化;提前在客户的参与下约定项目的标签结构,而不是让每个项目成员自己去想;收集同类型或竞争对手网站的标签,以供参考。
迷路可不是一件好玩的事情,试想你驾车行驶到高速公路分叉口时,却看不见任何路牌,那该会怎样地困惑、沮丧、愤怒和恐惧。为了避免迷失方向,我们发明了各种导航工具,大到卫星定位系统,小到指南针,人类在这一事情上,极具创意。
在网站上迷失方向,虽然不是什么生死攸关的事,但会带来许多负面影响,如:用户体验下降、任务不能完成,用户流失等。我们可以通过良好的导航系统来避免这个情况发生。好的导航系统可以帮助人们找到在网站中的位置,并帮助他们制定更好的查询策略,增进对内容的理解。
1、尽量不要用图片,尤其是别把激活链接做成一个点击按钮。
2、尽量少的给链接,最好只有一个显眼的链接。其他链接一律变短,弱化。链接明文显示。
3、用简单的邮件头
4、给予适当的提醒和帮助
a、提示用户如果无法点击链接,直接拷贝链接激活。
b、提示这是一封系统发出的信,请勿直接回信。
5、表明身份,发信人使用网站名即可,如“口碑网”、“淘宝网”。
5、非原型 不设计
在风起云涌的互联网浪潮中,产品迭代的速度越来越快。随着用户需求的激增,可视化的内容远比文档的更易于被用户(以至我们的客户)所接受,就像用户研究项目中常说的一句话:“用户怎么说的,并不代表他们怎么想。
每个人关心的过程都不一样,站的角度不一样呈现出来的内容也就不一样。
7、注册和登录流程(除了首页,估计就数注册和登录对用户最重要了,也是最难整的一块,看似简单,里面有很多玄机)
* 网站注册那些事儿
今年的公司年会选择了滑雪和泡温泉,21日去了南山滑雪场滑了大半天,下午就去泡温泉了,可惜年会上一不小心喝多了,加上温泉池一热,更晕了,也没泡上。
下面说说滑雪,从06年第一次在陕西的翠华山滑雪场接触滑雪,到现在的第四次,基本上也就是一年一次,技术长进一般,上中级滑道还行,高级的没敢去。
滑雪运动起源并发展于斯堪的纳维亚国家(北欧大半岛,包括挪威和瑞典两个国家。长约1,850公里(1,150 哩)
SKI(滑雪)是一个挪 威词,意思是雪鞋。
转载网上的图示教程:







本周关注比较多的是JQuery部分,优化了一个分页组件,实现了一个仿Gmail头像上传并剪辑的功能。
分页组件稍后有时间可以分享一下,今天分享下仿Gmail头像上传剪辑的功能。
这个功能是参考了Gmail的头像上传功能,并参照其流程实现的,因此叫仿Gmail头像上传剪辑,建议想用类似功能的朋友先看看Gmail的头像上传流程。
1、JQuery
2、Jquery.Form.JS (JQuery的一个form插件),这里主要是在层里面用到它的ajaxSubmit功能。
3、JCrop(JQuery头像剪辑插件),之前有篇博文讲到。
1、比如更新用户信息时,要更新用户的头像,这里只是更新头像地址,而不是在更新用户信息页面时上传头像,头像上传和剪辑的处理交给其他组件完成,比如这个上传剪辑功能。
2、给一个链接,比如叫“上传照片”, 如下图:
点击该链接会弹出一个层, 如下图:
3、头像上传的事情在这个层内完成,先上传到系统的temp目录,因为这个图片最后是要删除的,JCrop 剪辑后的图片才是真正想要的。
4、将图片上传完后,进行同比例的显示缩放(注意我这里叫显示缩放,而不是真正的缩放,即仅在该层内等比例显示下即可,当然你也可以不显示缩放,结果是图片巨大个,显示不下或者出现滚动条),显示在该页面,然后加载JCrop插件,进行图片剪辑处理(这里为了简单,没有放像Gmail那样的预览小图,需要的朋友可以参照JCrop加上),如下图:
5、点击“应用更改”时,将在服务器上进行原图片的剪辑工作,JCrop需要的是剪辑框的x,y,w,h四个参数,但是剪辑是在原图片上进行的,因此此处的x,y,w,h需要做映射,将缩略后的x,y,w,h映射到原图片的x,y,w,h上,新图片剪辑后保存到你的头像目录,最后别忘记删除temp文件夹下的图片。如下图效果:
此功能的实现上没有什么新颖的东西,主要是将几个插件的使用揉合在一块,然后形成一个用起来比较顺手的功能,实现过程可能稍感麻烦,但是最终的效果还是不错!
这周来一直在赶一个Web项目,没多少时间focus到其他上面,于是这周的主题就干脆做个整理,整理下web项目开发时遇到的一些问题和解决办法。
建议统一使用UTF8,或者全局做个filter处理。
使用第三方校验框架, 而非自己去写,可以减少很多工作量。
首页尽量少用ajax,页面初次加载时常会加载不上来,尤其多个Ajax实例同时运行。
UI最好是出Demo,跟客户确认,定终稿,然后开发按最终效果图实现页面最好,否则没有页面或者效果图,即使有统一的规范,还是会浪费很多时间去调UI问题。
虽然IE6基本上淘汰了,可老机器上使用IE6的还是不少的,Css 在处理兼容问题时,建议分开处理,在页面进行浏览器version判断,读取不同的css,这样管理和调整起来都方便。
页面框架搭完了,看着效果不错,可是填完数据后会发现和想象的不太一样。
JPA与JDBC相比之下,使用JPA大大减少了编程人员的工作量,因此还是偏向使用JPA,特殊环境下再选择JDBC
分两部分:一部Java Net(大部分来自Java Doc), 一部分XML Parser, 通过一个Twitter的例子来描述简单的使用情况。
java.net 包的概述:
java.net包大致可分为两部分:
在整个 java.net API 中,地址或者用作主机标识符或者用作套接字端点标识符。
InetAddress 类是表示 IP(Internet 协议)地址的抽象,它拥有两个子类:
Inet4Address。Inet6Address。但是,在大多数情况下,不必直接处理子类,因为 InetAddress 抽象应该覆盖大多数必需的功能。
套接字是在网络上建立机器之间的通信链接的方法。java.net 包提供 4 种套接字:
Socket 是 TCP 客户端 API,通常用于将 (java.net.Socket.connect(SocketAddress)) 连接到远程主机。ServerSocket 是 TCP 服务器 API,通常接受 (java.net.ServerSocket.accept) 源于客户端套接字的连接。DatagramSocket 是 UDP 端点 API,用于发送和接收 java.net.DatagramPackets。MulticastSocket 是 DatagramSocket 的子类,在处理多播组时使用。使用 TCP 套接字的发送和接收操作需要借助 InputStream 和 OutputStream 来完成,这两者是通过 java.net.Socket.getInputStream 和 java.net.Socket.getOutputStream 方法获取的。
java.net 包中的许多类可以提供更加高级的抽象,允许方便地访问网络上的资源。这些类为:
URI 是表示在 RFC 2396 中指定的统一资料标识符的类。顾名思义,它只是一个标识符,不直接提供访问资源的方法。URL 是表示统一资源定位符的类,它既是 URI 的旧式概念又是访问资源的方法。URLConnection 是根据 URL 创建的,是用于访问 URL 所指向资源的通信链接。此抽象类将大多数工作委托给底层协议处理程序,如 http 或 ftp。HttpURLConnection 是 URLConnection 的子类,提供一些特定于 HTTP 协议的附加功能。建议的用法是使用 URI 指定资源,然后在访问资源时将其转换为 URL。从该 URL 可以获取 URLConnection 以进行良好控制,也可以直接获取 InputStream。
下面是一个示例:
URI uri = new URI("http://java.sun.com/");
URL url = uri.toURL();
InputStream in = url.openStream();
抽象类 URLConnection 是所有表示应用程序与 URL 之间通信链路的类的超类。该类的实例可以用来对由 URL 引用的资源进行读取和写入操作
HttpURLConnection 仅是支持了 HTTP 特定功能的 URLConnection
openConnection 方法产生一连接对象。connect 方法,实现对远程对象的实际连接。通过如下的方法修改设置参数:
通过使用如下的方法修改一般请求属性:
AllowUserInteraction 和 UseCaches 参数的缺省值可以通过使用 setDefaultAllowUserInteraction 和 setDefaultUseCaches 方法来设置。 而一般请求属性的缺省值可以通过方法 setDefaultRequestProperty 来设置 。
上面的每个 set 方法都有相应 get 方法来获取参数和一般请求属性的值。可用的特定参数和一般请求属性是特定于协议的。
对远程对象的连接完成后,用下列方法访问报头域和内容:
确认报头域能够被频繁访问。方法:
提供对这些域的便利访问。 getContentType 方法由 getContent 方法调用以确定远程对象的类型; 子类来覆盖方法 getContentType 可能是有利的。
下面是一个通过Twitter API去获信息的demo:
URL url = new URL("http://t.bbercn.com/statuses/user_timeline.xml");
String username = (String) params[0];
String password = (String) params[1];
String user_paw = username + ":" + password;
String encoding = "Basic " + Base64Converter.encode(user_paw.getBytes());
URLConnection uc = url.openConnection();
uc.setRequestProperty("Authorization", encoding);
InputStream content = (InputStream) uc.getInputStream();
剩下的工作就是对InputStream 进行本地处理,Twitter返回的是XML,那么我们下面就对XML进行解析,获取我们要获取的信息。
关于 xml 解析的工具有很多,具体可以看这里:http://www.open-open.com/31.htm 罗列的一些。
下面通过Commons-Digester来处理上面我们获取的InputStream
public class ParseTools {
private List statuses = new ArrayList<Status>();
public List<Status> getStatuses() {
Collections.sort(statuses);
return statuses;
}
public void parseStatus(InputStream stream) throws IOException, SAXException {
Digester digester = new Digester();
digester.setValidating(false);
digester.push(this);
digester.addObjectCreate("statuses/status", Status.class);
//status
digester.addBeanPropertySetter("statuses/status/id");
digester.addBeanPropertySetter("statuses/status/created_at");
digester.addBeanPropertySetter("statuses/status/text");
digester.addBeanPropertySetter("statuses/status/source");
digester.addBeanPropertySetter("statuses/status/truncated");
digester.addBeanPropertySetter("statuses/status/in_reply_to_status_id");
digester.addBeanPropertySetter("statuses/status/in_reply_to_user_id");
digester.addBeanPropertySetter("statuses/status/favorited");
digester.addBeanPropertySetter("statuses/status/in_reply_to_screen_name");
//user
digester.addObjectCreate("statuses/status/user", User.class);
digester.addBeanPropertySetter("statuses/status/user/id");
digester.addBeanPropertySetter("statuses/status/user/name");
digester.addBeanPropertySetter("statuses/status/user/screen_name");
digester.addBeanPropertySetter("statuses/status/user/description");
digester.addBeanPropertySetter("statuses/status/user/location");
digester.addBeanPropertySetter("statuses/status/user/profile_image_url");
digester.addBeanPropertySetter("statuses/status/user/url");
digester.addBeanPropertySetter("statuses/status/user/isProtected");
digester.addBeanPropertySetter("statuses/status/user/followers_count");
digester.addBeanPropertySetter("statuses/status/user/friends_count");
digester.addSetNext("statuses/status/user", "setUser");
digester.addSetNext("statuses/status", "addStatuses", Status.class.getName());
digester.parse(stream);
}
public void addStatuses(Status status) {
Status d = new Status();
d.setId(status.getId());
d.setCreated_at(status.getCreated_at());
d.setFavorited(status.isFavorited());
d.setText(status.getText());
d.setSource(status.getSource());
d.setTruncated(status.isTruncated());
d.setIn_reply_to_screen_name(status.getIn_reply_to_screen_name());
d.setIn_reply_to_status_id(status.getIn_reply_to_status_id());
d.setIn_reply_to_user_id(status.getIn_reply_to_user_id());
d.setUser(status.getUser());
getStatuses().add(d);
}
}
周三赶鸭子上架的组织了一次JQuery入门培训,由于时间上的原因,自己没做Demo,拿官方现成的,主要是认识JQuery,了解JQuery核心函数,介绍一些常用的选择器,还有事件处理,以及Ajax的使用,这里简单分享下:
$ 表示JQuery类,$(…) 构造一个JQuery类,这里的JQuery类是一个集合数组对象,而非Dom对象。
jQuery(expression,[context])
$("div > p"); $("input:radio", document.forms[0]); $("div", xml.responseXML);jQuery( html )
$("<div>Hello</div>").appendTo("body");主要用来加载html
jQuery( elements )
$(document.body).css("background-color", "black"); $(myForm.elements).hide();jQuery( callback )
$(function(){ alert('hello'); });JQuey中执行方法是在页面加载结束后,官方解释是:A shorthand for $(document).ready().
JQuery选择器是JQuery的一大亮点,快捷,高效的遍历整个HTML文档,常用的如下面几种:
$("#id"); $("div"); $(".className"); $("div,span,p.myClass") $("form input") $("form > input")强烈建议直接看官方文档:http://docs.jquery.com/Selectors
$("p").bind("click", function(e){}); $("p").click(function() {}) trigger( event, data ) //触发事件 triggerHandler( event, data ) //触发事件,但不触发浏览器的默认事件 $("p").live("click", function(){ //在p以及p的下面的子elements上都加上click事件 $(this).after("<p>Another paragraph!</p>"); });更多,参见官方文档:http://docs.jquery.com/Events
ajax这块感觉和其他框架没多少差别,用起来基本类似:
1、$.post(…) 和 $.get(…)$.post('save.cgi', { text: 'my string', number: 23 }, function() { alert('Your data has been saved.'); });2、$.ajax(…)
$.ajax({ url: 'getdata.action', type: 'GET', dataType: 'html', Timeout: 1000, beforeSend: function(){ // Handle the beforeSend event }, success: function(html){ // do something with html }, complete: function(){ // Handle the complete event }, error: function(){ alert('Error loading HTML document'); }, });
1、http://jquery.com/
2、jQuery 1.3 API 中文参考文档
3、http://jqueryui.com/
4、http://jquery.org.cn/
5、有关Ajax的一个中文文章
由于最近另一个项目的启动,工作方面基本上是掐着时间在忙,所以周主题的任务就只能稍微往后推一周了。
预计本周四结合公司的培训内容,出一个有关JQuery的入门介绍,这个内容顺便就补给上周的周主题。
顺便预告下:接下来这周和下周会整理有关Java.Net包下一些常用类的使用,包括HttpClient的使用,以及XML Parser方面的汇总。
选择这个主题,是因为上周公司刚好做了一个有关“Beginning Java AWT and Swing” 的培训,借此机会正好总结一下这方面的使用技巧。对于Swing界面方面的研究,我仅仅是应用而已,公司里有几位同事在这方面的研究比较深,这块的应用和使用技巧分两部分, 一部分是Swing 使用本身的,另一部分是Design工具NetBeans的,如果是刚入门建议从这里看起:Creating a GUI With JFC/Swing。
随着Java 6对于Swing性能的改进,Swing的运行速度已经开始得到了大大的提高,看看NetBeans就知道了,NetBeans就是Swing开发的,如果你跑Swing很慢,很耗资源,那么应该从自己的程序上找找问题,推荐使用NetBeans自带的Profile查找原因,教程在这里 – Profile Introduce 。
用Swing做企业应用时,LookAndFeel的选择和使用是决定这个项目能否被客户接受的一个很大因素,即要好看,又要考虑跨平台的兼容性,必要时自己还得设计部分LookAndFeel, 可以看看这里提供的一些开源LookAndFeel:http://www.open-open.com/61.htm 和http://www.javootoo.com/。
切换LookAndFeel:UIManager.setLookAndFeel(LookAndFeelName); SwingUtilities.updateComponentTreeUI(frame); frame.pack();
举个例子:之前我们项目中有一个地方,当打开程序时,会初始化几十个甚至成百个JPanel,这显然成为程序启动时慢的一个因素,也导致了用户体验的降低,这些JPanel完全可以在程序启动后再根据用户的需要去初始化,因为用户打开程序时这些Panel不是必须看到的。
比如Button的高度,进度条的高宽等,也可以通过UIManager给系统组件设置统一属性,比如统一设定Button的间距和字体:
UIManager.put("Button.margin", new Insets(2, 5, 2, 5)); UIManager.put("Button.font", new Font("宋体", Font.PLAIN, 13));
用Swing做的都是界面的东西,如果界面假死或者用户等待事件太长,那么用户体验必然是不好的,这里就需要用到多线程的使用了,当界面处理一个请求时,不能让界面假死了,需要后台另一个线程去做处理,然后将结果返回到Swing线程,这块可以看看SwingWorker的介绍。
布局管理器的使用在Swing里面是比较重要的,它直接决定了你界面的显示效果,也是比较难用的一块,不好举例子,建议多了解每个布局管理器的使用场景。
在Swing组件的使用中除了布局管理器,估计就数JTable和JTree的使用稍微有点麻烦了,下面我就分享一些实际项目中JTable的一些实例,关于JTree,可以点这里:JTree 经验 总结 。
JTable相关
1、自定义表头排序
TableRowSorter rs = (TableRowSorter) table.getRowSorter(); Comparator<Integer> intComparator = new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } }; rs.setComparator(3, intComparator);2、自定义Table Renderer
public class CommonTableCellRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean cellHasFocus, int row, int column) { JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, cellHasFocus, row, column); //表格的奇数偶数行交叉颜色显示 if (!isSelected) { if (row % 2 == 0) { comp.setBackground(UIConsts.HIGHLIGHTER_COLOR); } else { comp.setBackground(Color.white); } } //table column里面显示图标和对齐方式 switch (column) { case PaperTableModel.STATUS_COLUMN: switch ((EntityStatus) value) { case VALID: comp.setIcon(ENABLED_ICON); setHorizontalAlignment(JLabel.LEADING); break; case DISABLED: comp.setIcon(DISABLED_ICON); setHorizontalAlignment(JLabel.CENTER); break; } break; default: comp.setIcon(null); break; } return comp; } }3、自定义Table列宽
TableColumnModel colModel = table.getColumnModel(); colModel.getColumn(0).setPreferredWidth(70); colModel.getColumn(1).setPreferredWidth(55); colModel.getColumn(2).setPreferredWidth(120);4、禁止Table列拖动
table.getTableHeader().setReorderingAllowed(false);5、单选表格设置
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);6、设置表头默认支持排序
table.setAutoCreateRowSorter(true);7、设置列不可随容器组件大小变化自动调整宽度
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);8、固定Table上的某些列不滚动
这个需求是这样的,比如Table上左边有部分数据,是后面数据所共有的属性,那么当后面数据很多时,显示不下会出现滚动条,但是滚动时又不想让左侧的共有属性动,只滚动右侧的数据部分。
实现原理是:scrollPane里面放置一个表格,然后在scrollPane的左上角放置以共有属性的部分为Model的表格,剩下的右侧就是剩余的纯数据表格。
最终效果就是表格左侧的列锁定了,右侧数据出现滚动条时,可以滚动,但左侧不动。
核心代码:比如有HeaderTable和ReportTable, 其中ReportTable是放置在一个ScrollPanel里面,Model是所有数据的Model,将左侧的数据和右侧的数据分开//找到主表所在的scrollPane JScrollPane scrollPane = (JScrollPane) SwingUtilities. getAncestorOfClass(JScrollPane.class, reportTable.getTable()); //中间处理headerTable的数据和reportTable剩余的数据 //将新表HeaderTable放在scrollPane的左上角 scrollPane.setRowHeaderView(headerTable.getTable()); scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, headerTable.getTable().getTableHeader());9、Table上的直接编辑功能
两点:
1、重写 public boolean isCellEditable(int row, int columnIndex) 方法,定义可编辑的行列。
2、重写 public void setValueAt(Object obj, int rowIndex, int columnIndex) 方法,拿到原来的对象,设置新的对象值。10、Table的Excel导出功能
表格上的Excel导出功能还是比较实用的功能,企业应用一般都会用到,这里提供相关代码
try { WritableCellFormat titleFormat = new WritableCellFormat( new WritableFont(WritableFont.createFont("黑体"), 16, WritableFont.NO_BOLD)); titleFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐 titleFormat.setAlignment(Alignment.CENTRE); // 水平对齐 titleFormat.setWrap(true); // 是否换行 WritableCellFormat headerFormat = new WritableCellFormat(); headerFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条 headerFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐 headerFormat.setAlignment(Alignment.CENTRE); // 水平对齐 headerFormat.setWrap(true); // 是否换行 WritableCellFormat countFormat = new WritableCellFormat( new NumberFormat("0.000")); countFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条 countFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐 countFormat.setAlignment(Alignment.RIGHT); // 水平对齐 countFormat.setWrap(true); // 是否换行 WritableCellFormat moneyFormat = new WritableCellFormat( new NumberFormat("0.00")); moneyFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条 moneyFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐 moneyFormat.setAlignment(Alignment.RIGHT); // 水平对齐 moneyFormat.setWrap(true); // 是否换行 WritableCellFormat intFormat = new WritableCellFormat( new NumberFormat("0")); intFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条 intFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐 intFormat.setAlignment(Alignment.RIGHT); // 水平对齐 intFormat.setWrap(true); // 是否换行 WritableWorkbook book = Workbook.createWorkbook(exportFile); WritableSheet sheet = book.createSheet("综合统计报表", 0); int titleRow = 0; int headerRow = 3; int dataRow = 5; sheet.mergeCells(0, titleRow, model.getColumnCount() - 1, titleRow); Label titleLab = new Label(0, titleRow, tableTitleTxfd.getText(), titleFormat); sheet.addCell(titleLab); //生成表头 for (int j = 0; j < model.getColumnCount(); j++) { sheet.mergeCells(j, headerRow, j, headerRow + 1); Label lab = new Label(j, headerRow, model.getColumnName( j), headerFormat); sheet.addCell(lab); } for (int row = 0; row < model.getRowCount(); row++) { for (int col = 0; col < model.getColumnCount(); col++) { Object obj = model.getValueAt(row, col); if (obj instanceof String) { Label lab = new Label(col, dataRow + row, (String) obj, headerFormat); sheet.addCell(lab); } else if (obj instanceof Integer) { Number labelN = new Number(col, dataRow + row, (Integer) obj, intFormat); sheet.addCell(labelN); } else { Label lab = new Label(col, dataRow + row, "", headerFormat); sheet.addCell(lab); } } } //生成表尾 int footerRow = dataRow + model.getRowCount() + 1; int step = (int) (((double) (model.getColumnCount() - 2) / 3) + 1); Label footerLab = new Label(0, footerRow, "部门负责人:"); sheet.addCell(footerLab); footerLab = new Label(step, footerRow, "制表:" + creatorTxfd.getText()); sheet.addCell(footerLab); footerLab = new Label(model.getColumnCount() - 2, footerRow, NazcaFormater.getSimpleDateString(new Date())); sheet.addCell(footerLab); sheet.setColumnView(0, 16); sheet.setRowView(titleRow, 600); book.write(); book.close(); //导出成功 } catch (Throwable ex) { //导出报表失败 ex.printStackTrace(); }11、Table的打印功能
打印这块,之前已经提过,可以参考之前的文章 JTable Print
12、在Table上选择多行
int rowcounts=table.getSelectedRows().length; if(rowcounts>1) int[] rows=table.getSelectedRows(); for(int i=0;i<rows.length;i++){ String value=(String) tableModel.getValueAt(i, 1); } }
这里说NetBeans,主要是因为目前Swing开发方面,还没有哪个IDE能胜过NetBeans。
一、NetBeans的配置
1、配置为英文,大部分时间我们下载的都是中文的版本,可以通过在/$NetBeans_HOME/etc/netbeans.conf中添加 –locale en_US, 让启动时显示为英文,这个之前也有文章介绍:Netbeans 英文界面 和 最简单的Netbeans中英文切换
2、优化配置可以看之前介绍的这篇文章,就不重复了:Netbeans 6.5 优化建议二、经验分享
1、Swing的Debug虽然被很多人说不好用,但是在用NetBeans时,多用Debug可以提高效率,因为Debug模式下的修改,大部分只要点击应用,就可以不用重启项目而看到效果。
2、很好用的快捷键和快速补齐(限Windows + Linux下,如果在Mac下改成 ⌘ 试试),如:快捷键: Ctrl+R Rename Alt+Enter Fix Error(Eclipse Ctrl+1) Alt+Shift+F Quick Format Alt+Shift+I Fix Import F9 Build File F6 Run Main Project Shift+F6 Run File Ctrl+| Insert Code 快速补齐(英文输入状态下,输入完后按Tab键,也可以自己配置为其他键,在Options - Editor - Code Templates下): psvm public static void main sout System.out.println im implements Psfs public static final String psfi private static final String fore for($ : $){} fori for(int i = 0; i < arr.length; i++){} forl for(int i = 0; i < list.size(); i++){}三、插件分享
我们都知道NetBeans上的插件很多,可以说NetBeans正是因为这些插件才强大起来,支持的功能也更多了。分享的这几个插件是平时工作时,可以显著提高效率的,不好的不推荐,你如果有好的也别忘记分享下。1、Path Tools – 可以直接查找到类或者文件夹所在的磁盘位置,基本是我每次装完NetBeans的后第一个装的插件。
2、SQE(Software Quality Environment) – 是最近同事刚刚推荐的一个插件,看名字就知道了,是一个类似Firebug的插件,可以发现程序中存在的一些显著的错误,很不错。
3、UUID Generator - 同事写的一个快速生成UUID的插件。
4、SwingX 插件 – 用来添加一些SwingX组件的。
5、iReport – 打印报表用的插件,结合JasperReport使用。