权记

一个关于我们生活点滴的网站,一个记录我们酸甜苦辣的日志。

Archive for the ‘周主题’ Category

 

之前在写 [10/02周主题] – 仿Gmail头像上传剪辑 时说,还有个JQuery的分页组件分享给大家,这个组件是别人设计的,我只是在其基础上,进行一些改动,以符合自身项目的需求。

之前在做Web项目时,分页功能的处理是放在服务器端,客户端只是用来显示分页导航条内容。 虽然将服务器端的分页功能进行封装,页码显示代码也进行了整理,但是总归不是很方便,做分页功能还是要做不少工作。

后来去看一些将分页功能放在客户端处理的例子,最后发现了这个比较不错的JQuery组件(如果你有好的方案也欢迎分享啊),原文章在这里:http://lym6520.javaeye.com/blog/540580,我就不做过多介绍了。

通过这个组件做分页功能,服务器端几乎不做什么处理,只需要显示数据列表时把总数传给该组件即可。至于分页组件的样式你完全可以自己去定制。

下面分享下自己的一些优化工作:

1、Loading和错误提示

Loading和错误信息的显示在获取数据时控制,这里用到了Ajax的几个状态来判断,比如beforeSend,success以及error。

2、分页组件的翻页和获取数据是异步的,这样如果出现服务器问题,无法获取翻页后的信息,但是分页导航条已经做了翻页了。由于服务器出错是在Ajax里面捕获的,这样就只能做个hack,通过dom操作来让翻页返回去,最终的效果会是这样的:假如现在在第三页,要跳转到第四页,点 “4” 翻页了,然后发现翻页后无法获取数据,出现服务器问题了,接着就又返回第三页了,显示错误信息。

  • 0 Comments
  • Filed under: 周主题
  • 2月份回家过年了,这个月的周主题选定了过年回家的一些见闻,看看农村的一些变化,和一些你不知道的事儿。

    过年回家

    买回家的火车票

    今年的火车票真TM的难买,看形势不对,也第一次开始排队买票,排第一个还买了座票,不得不操下铁道部,以及没良心的火车票代售点,压票不出。票贩子的票价也翻翻了,两百多的票,开口就是五六百。

    下火车上黑车

    火车晚点快1个小时到站了,凌晨6点到,家里下了雪,不小,车站封了,有几辆黑车在拉人,因为没国营公车,只能坐黑车了,票价已经翻番了,你不坐还找不到其他车了,运气不好的,半路就把你撂下,还不退钱,有理你也没地方说去。

    严重超载,遇查弃人

    上面说了黑车拉人,这里要说的是严重超载的问题,我当时坐的车15人左右的座位,中间加凳子多拉了10个,因为是春节,即使下雪,交警还是时不时出来查超载的,这辆车本来是想碰碰运气的,结果听前方通风报信的说有交警,于是就半路把10个乘客丢下了,漫天大雪,本来就车辆紧张的情况下,中途下车的后果基本上就是活受罪,能等到有座的车算中大奖了。唉,无语啊!

    多个车玩漂移了

    下雪路滑,小心漂移,一路上看到不少车撩路两边了,有两车相撞的,有碰水渠上的,有玩翻转,唉,大过年的,人要没事还好点,人要有事,这一家子过啥年啊。

    黑煤窑撑经济

    这几年回家几次给我印象最深的,莫过于黑煤窑了,我们家乡是苹果之乡可近几年基本上是荒了,支撑经济的只有煤炭了,正规的煤炭企业养了县政府,黑煤窑养了煤窑所在村的村民,但是大部分钱都流到外省人手里,因为不管是正规煤炭企业还是黑煤窑基本上都是有钱的外省人,以山西人居多开的,要么就是本地人开卖给外地人。过年15天,黑煤窑是24小时加紧生产,一条山沟里黑煤窑不下200个,白天加紧生产,晚上往外运煤,村里不少人过年也没闲着啊。

    车祸人祸没人敢管

    现在的农村不是以前的农村了,农民的憨厚质朴也随着社会风气变的无情和自私,在家呆了好几天就遇上好几起事故,伤者躺在马路上没人管,路人估计也没人敢管,怕赖在自己身上。

    信誉问题

    说农村不是以前的农村,另一点就是农民的信誉现在可谓是到了低谷了,至少我感觉在我们那里是这样的,现在在村里弄个什么事情想筹点钱,可谓比上天难,甚至比贷款难多了,现在是没人敢借。

  • 3 Comments
  • Filed under: 周主题
  • UED – 英文User Experience Design的缩写,中文翻译:用户体验设计。

    关于UED更多信息可以Google之,本周分享下这几天收集的一些和UED有关的案例,在实际的项目中还是有些帮助的。

    1、多按钮共存——don’t make me think

    我们的按钮一般都是成对出现,比如提交和取消,保存和取消等,突出你认为重点的按钮,降低有消极面的按钮,甚至只给用户一个选择,比如注册,只能一路Next,当然这需要根据具体场景来分,但是让用户思考如何下一步,不如从我们的角度突出重点的建议用户就走这一步。

    2、导航的标签设计

    好的标签,应该使用客户的语言,避免使用术语、行话、缩写词等用户难以理解的词语;标签之间的互斥性要强,尽可能地寻找差异化;提前在客户的参与下约定项目的标签结构,而不是让每个项目成员自己去想;收集同类型或竞争对手网站的标签,以供参考。

    3、避免用户迷失在你的网站上

    迷路可不是一件好玩的事情,试想你驾车行驶到高速公路分叉口时,却看不见任何路牌,那该会怎样地困惑、沮丧、愤怒和恐惧。为了避免迷失方向,我们发明了各种导航工具,大到卫星定位系统,小到指南针,人类在这一事情上,极具创意。

    在网站上迷失方向,虽然不是什么生死攸关的事,但会带来许多负面影响,如:用户体验下降、任务不能完成,用户流失等。我们可以通过良好的导航系统来避免这个情况发生。好的导航系统可以帮助人们找到在网站中的位置,并帮助他们制定更好的查询策略,增进对内容的理解。

    4、如何设计注册激活邮件

    1、尽量不要用图片,尤其是别把激活链接做成一个点击按钮。

    2、尽量少的给链接,最好只有一个显眼的链接。其他链接一律变短,弱化。链接明文显示。

    3、用简单的邮件头

    4、给予适当的提醒和帮助

    a、提示用户如果无法点击链接,直接拷贝链接激活。

    b、提示这是一封系统发出的信,请勿直接回信。

    5、表明身份,发信人使用网站名即可,如“口碑网”、“淘宝网”。

    5、非原型 不设计

    在风起云涌的互联网浪潮中,产品迭代的速度越来越快。随着用户需求的激增,可视化的内容远比文档的更易于被用户(以至我们的客户)所接受,就像用户研究项目中常说的一句话:“用户怎么说的,并不代表他们怎么想。

    6、自然描述与自然任务

    每个人关心的过程都不一样,站的角度不一样呈现出来的内容也就不一样。

    7、注册和登录流程(除了首页,估计就数注册和登录对用户最重要了,也是最难整的一块,看似简单,里面有很多玄机)

    * 会员注册页面的交互细节

    * 谈网站注册、登录过程

    * 网站注册那些事儿

    * 某些媒体登陆脑残群体

  • 0 Comments
  • Filed under: 周主题
  • 今年的公司年会选择了滑雪和泡温泉,21日去了南山滑雪场滑了大半天,下午就去泡温泉了,可惜年会上一不小心喝多了,加上温泉池一热,更晕了,也没泡上。

    下面说说滑雪,从06年第一次在陕西的翠华山滑雪场接触滑雪,到现在的第四次,基本上也就是一年一次,技术长进一般,上中级滑道还行,高级的没敢去。

    滑雪运动起源并发展于斯堪的纳维亚国家(北欧大半岛,包括挪威和瑞典两个国家。长约1,850公里(1,150 哩)

    SKI(滑雪)是一个挪 威词,意思是雪鞋。

    转载网上的图示教程:

  • 0 Comments
  • Filed under: 周主题
  • 本周关注比较多的是JQuery部分,优化了一个分页组件,实现了一个仿Gmail头像上传并剪辑的功能。

    分页组件稍后有时间可以分享一下,今天分享下仿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文件夹下的图片。如下图效果:

    总结:

    此功能的实现上没有什么新颖的东西,主要是将几个插件的使用揉合在一块,然后形成一个用起来比较顺手的功能,实现过程可能稍感麻烦,但是最终的效果还是不错!

  • 1 Comment
  • Filed under: 周主题
  • 这周来一直在赶一个Web项目,没多少时间focus到其他上面,于是这周的主题就干脆做个整理,整理下web项目开发时遇到的一些问题和解决办法。

    本周主题:Web 项目开发中的常见问题

    一、中文乱码

    建议统一使用UTF8,或者全局做个filter处理。

    二、表单校验

    使用第三方校验框架, 而非自己去写,可以减少很多工作量。

    三、Ajax的使用

    首页尽量少用ajax,页面初次加载时常会加载不上来,尤其多个Ajax实例同时运行。

    四、UI 规范

    UI最好是出Demo,跟客户确认,定终稿,然后开发按最终效果图实现页面最好,否则没有页面或者效果图,即使有统一的规范,还是会浪费很多时间去调UI问题。

    五、浏览器的兼容问题

    虽然IE6基本上淘汰了,可老机器上使用IE6的还是不少的,Css 在处理兼容问题时,建议分开处理,在页面进行浏览器version判断,读取不同的css,这样管理和调整起来都方便。

    六、比较完整的测试数据

    页面框架搭完了,看着效果不错,可是填完数据后会发现和想象的不太一样。

    七、用JPA Or JDBC 与数据库交互

    JPA与JDBC相比之下,使用JPA大大减少了编程人员的工作量,因此还是偏向使用JPA,特殊环境下再选择JDBC

  • 0 Comments
  • Filed under: 周主题
  • 本周主题:Java Net and XML Parser

    分两部分:一部Java Net(大部分来自Java Doc), 一部分XML Parser, 通过一个Twitter的例子来描述简单的使用情况。

    一、Java Net

    java.net 包的概述:

    java.net包大致可分为两部分:

    低级API – 用于处理以下抽象:

    • 地址,也就是网络标识符,如 IP 地址。
    • 套接字,也就是基本双向数据通信机制。
    • 接口,用于描述网络接口。

    高级API – 用于处理以下抽象:

    • URI,表示统一资源标识符。
    • URL,表示统一资源定位符。
    • 连接,表示到 URL 所指向资源的连接。

    地址

    在整个 java.net API 中,地址或者用作主机标识符或者用作套接字端点标识符。

    InetAddress 类是表示 IP(Internet 协议)地址的抽象,它拥有两个子类:

    但是,在大多数情况下,不必直接处理子类,因为 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 方法获取的。

    高级API

    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 和 HttpURLConnection 的使用:

    抽象类 URLConnection 是所有表示应用程序与 URL 之间通信链路的类的超类。该类的实例可以用来对由 URL 引用的资源进行读取和写入操作

    HttpURLConnection 仅是支持了 HTTP 特定功能的 URLConnection

    1. 通过调用 URL 的 openConnection 方法产生一连接对象。
    2. 操纵设置参数和一般请求属性。
    3. 使用 connect 方法,实现对远程对象的实际连接。
    4. 远程对象一旦可用,就可以访问远程对象的域和内容。

    通过如下的方法修改设置参数:

    • setAllowUserInteraction
    • setDoInput
    • setDoOutput
    • setIfModifiedSince
    • setUseCaches

    通过使用如下的方法修改一般请求属性:

    • setRequestProperty

    AllowUserInteractionUseCaches 参数的缺省值可以通过使用 setDefaultAllowUserInteractionsetDefaultUseCaches 方法来设置。 而一般请求属性的缺省值可以通过方法 setDefaultRequestProperty 来设置 。

    上面的每个 set 方法都有相应 get 方法来获取参数和一般请求属性的值。可用的特定参数和一般请求属性是特定于协议的。

    对远程对象的连接完成后,用下列方法访问报头域和内容:

    • getContent
    • getHeaderField
    • getInputStream
    • getOutputStream

    确认报头域能够被频繁访问。方法:

    • getContentEncoding
    • getContentLength
    • getContentType
    • getDate
    • getExpiration
    • getLastModified

    提供对这些域的便利访问。 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 Parser

    关于 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);
        }
    }
    
  • 0 Comments
  • Filed under: 周主题
  • 三赶鸭子上架的组织了一次JQuery入门培训,由于时间上的原因,自己没做Demo,拿官方现成的,主要是认识JQuery,了解JQuery核心函数,介绍一些常用的选择器,还有事件处理,以及Ajax的使用,这里简单分享下:

    本周主题:JQuery

    一、JQuery核心认识

    $ 表示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选择器是JQuery的一大亮点,快捷,高效的遍历整个HTML文档,常用的如下面几种:

    $("#id");
    $("div");
    $(".className");
    $("div,span,p.myClass")
    $("form input")
    $("form > input")
    

    强烈建议直接看官方文档:http://docs.jquery.com/Selectors

    三、JQuery事件

    $("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

    四、JQuery Ajax

    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的一个中文文章

  • 0 Comments
  • Filed under: 周主题
  • 周主题推迟一周

    于最近另一个项目的启动,工作方面基本上是掐着时间在忙,所以周主题的任务就只能稍微往后推一周了。

    预计本周四结合公司的培训内容,出一个有关JQuery的入门介绍,这个内容顺便就补给上周的周主题。

    顺便预告下:接下来这周和下周会整理有关Java.Net包下一些常用类的使用,包括HttpClient的使用,以及XML Parser方面的汇总。

  • 0 Comments
  • Filed under: 周主题
  • 择这个主题,是因为上周公司刚好做了一个有关“Beginning Java AWT and Swing” 的培训,借此机会正好总结一下这方面的使用技巧。对于Swing界面方面的研究,我仅仅是应用而已,公司里有几位同事在这方面的研究比较深,这块的应用和使用技巧分两部分, 一部分是Swing 使用本身的,另一部分是Design工具NetBeans的,如果是刚入门建议从这里看起:Creating a GUI With JFC/Swing

    本期主题:Swing Tips

    一、性能问题

    随着Java 6对于Swing性能的改进,Swing的运行速度已经开始得到了大大的提高,看看NetBeans就知道了,NetBeans就是Swing开发的,如果你跑Swing很慢,很耗资源,那么应该从自己的程序上找找问题,推荐使用NetBeans自带的Profile查找原因,教程在这里 – Profile Introduce

    二、LookAndFeel

    用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不是必须看到的。

    四、要有统一的UI规范

    比如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里面是比较重要的,它直接决定了你界面的显示效果,也是比较难用的一块,不好举例子,建议多了解每个布局管理器的使用场景。

    七、JTable & JTree

    在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 6+ Tips

    这里说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使用。

  • 0 Comments
  • Filed under: 周主题
  •