网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > J2EE/J2ME
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.游戏框架之心得体会(1).
.Eclipse入门?使用指南及开发Ecli.
.分析MIDP的高级事件处理机制.
.如何向MIDP2.0窗体中加入自定义的.
.在索尼爱立信JP7平台上自动启动M.
.JavaOS—Java独立应用平台.
.经典收藏:J2MEGame的开发笔记.
.从自定义字节数组创建图片.
.连接池深入J2EE的连接合用.
.漫谈EJB (3).
.通过SCMAD认证考试的经验.
.Post和Get 的问题解决.
.如何控制游戏中的FPS.
.基于MIDP1.0实现动画效果.
.使用 MIDP 底层用户接口 API.
.MIDP终端模拟之一:一个简单的模.
.使用Timer制作动画效果.
.正确利用J2EE的各种工具.
.调用 CGI 脚本.
.使用Filter记录日志、来访IP、UR.

解决日期选择问题,一劳永逸(使用Decorator模式实现日期选择组件)(三)

发表日期:2007-12-23


基本的selector接口
  
  日期选择类的核心是Date_selector_panel.仔细分析后,首先做了一些如下变量声明,不要被"常量初始化"语法掷出。(以为括号中的代码是静态的,和其他没有任何联系.)实例初始化声名使用this的结构避免了在构造器中连接另一个构造器。他们提供了保证在每个构造器都能有效调用的初始化方法。同时在一个地方给出所有的初始化代码也是非常方便的。散布在各个地方的没有初始化的变量很容易引起运行错误。当移动代码到构造器中也是非常困难的,因为移动过程中你必须考虑你已经改变的2个地方。比如说,在下面日历声明中代码就是实例初始化:
   public class Date_selector_panel extends JPanel implements Date_selector
{
//这些字符串应该应该在资源包中,因此它们是国际化的。    
        private String[] months =
    {   "Jan","Feb", "Mar","Apr", "May","June",
        "July","Aug","Sept","Oct","Nov","Dec"
    };

    private static final int DAYS_IN_WEEK = 7,  // 一个 星期的天数
   MAX_WEEKS    = 6;  // 在一月中最大的//星期数。
    // 用户选择的日期
private Date selected = null;

    private Calendar calendar = Calendar.getInstance();
    {   calendar.set( Calendar.HOUR,    0 );
        calendar.set( Calendar.MINUTE,  0 );
        calendar.set( Calendar.SECOND,  0 );
    }

    //显示在屏幕上的当前日期
    private final Calendar today = Calendar.getInstance();

下面便开始处理点击不同天的事件。我采用比较容易实现的外观即将每天都以一个标签是日期的按纽显示在屏幕上,我定义了一个简单的监听对象并加载到每个按纽中。由监听对象获取按纽标签值,由标签值可以得到日期与日历的位置,然后它将从日历中获取日期对象并且将日期字符串发送给监听器(通过调用fire_ActionEvent()的方式)。
//一个监听器适合所有calendar事件
private final Button_handler day_listener  = new Button_handler();

private class Button_handler implements ActionListener
{   public void actionPerformed(ActionEvent e)
    {
        if (e.getActionCommand().equals("D"))
        {   String text = ((JButton) e.getSource()).getText();

            if(text.length() > 0)  //  <=0 means click on blank square. Ignore.
            {   calendar.set
                (   calendar.get(Calendar.YEAR),    // Reset the calendar
                    calendar.get(Calendar.MONTH),   // to be the chosen
                    Integer.parseInt(text)          // date.
                );
                selected = calendar.getTime();
                fire_ActionEvent( SELECT_ACTION, selected.toString() );
            }
        }
    }
}

     Java的AWTEventMulticaster 类实现了动作监听。这种实现在我提供的文档(一篇关于multicasters的文章列在 Resources <http://www.javaworld.com/javaworld/jw-07-2003/>.)中叙述的比较清楚。
private ActionListener subscribers = null;
public synchronized void addActionListener(ActionListener l)
{   subscribers = AWTEventMulticaster.add(subscribers, l);
}
public synchronized void removeActionListener(ActionListener l)
{   subscribers = AWTEventMulticaster.remove(subscribers, l);
}
private void fire_ActionEvent( int id, String command )
{   if (subscribers != null)
         subscribers.actionPerformed(new ActionEvent(this, id, command) );
}


//在面板显示前调用addNotify()。它实际上创建了基本的图象对象,因此你可以调用super.addNotify()去调用面板。
//这里使用它是一个入口去发送初始化ActionEvent到支持标题的任何实体。
public void addNotify()
{
    super.addNotify();
    int month = calendar.get(Calendar.MONTH);
    int year  = calendar.get(Calendar.YEAR);
    fire_ActionEvent( CHANGE_ACTION, months[month] + " " + year );
}

    然后我创建并初始化了代表天的按纽数组。有趣的是,日历并不能用二维数组表示,于是,我把按纽放在GridLayout布局中,让布局管理器来获取他的状态。在线形数组中在Grid中的第一个按钮表示第一周的第一天;第八个按纽是第二周的第一天;等等。下面是代码 :

--");
        days[i] = day;
        day.setBorder (BorderFactory.createEmptyBorder(1,2,1,2));
         day.setFocusPainted (false);   // Cannot get focus
        day.setActionCommand    ("D");
        day.addActionListener   (day_listener);// Our single listener
        day.setOpaque (false);                  
  // Transparent background
    }
}

然后便是构造器。主要工作都在这没有参数的构造器中。它创建了包含日历的面板,建立了gridlayout布局,并将按纽加入到布局中:

public Date_selector_panel()
{
    JPanel calendar_display = new JPanel();
    calendar_display.setOpaque(false);
    calendar_display.setBorder( BorderFactory.createEmptyBorder(5,3,0,1) );
    calendar_display.setLayout(new GridLayout(MAX_WEEKS /*rows*/, DAYS_IN_WEEK /*columns*/ ));

    for( int i = 0; i <  days.length; ++i )
        calendar_display.add(days[i]);

    setOpaque( false );
    setLayout( new BorderLayout() );
    add(calendar_display, BorderLayout.CENTER);
    update_calendar_display();
}

   全部代码清单还含有少量的的方便组件,使用他们比用当前日期能更好的初始化日历。在这里我没有谈到。
在Date_selector_panel中最值得说的是update_calendar_display()方法,当改变日历的时候该方法更新显示的日历。我使用java.util.Calendar()方法来判断星期日与月初的偏移量并在这些按钮上设置空字符串的标签。最后我将用空字符串来填写表示月末的按钮标签。
通过这种方式,你看到的每个按都在改变,即使它代表的是当前月中的无效天。这里并不需要用代码实现 ,因为当你 将按钮放入GridLayout中,布局便会自动列出你放入的按钮。
private void update_calendar_display()
{
    setVisible(false);  // Improves paint speed and redUCes flicker.

    clear_highlight();

    // The buttons that comprise the calendar are in a single
    // dimensioned array that was added to a 6x7 grid layout in
    // order. Because of the linear structure, it's easy to
    // lay out the calendar just by changing the labels on
    // the buttons. Here's the algorithm used below:
    //
    //  1) Find out the offset to the first day of the month.
    //  2) Clear everything up to that offset.
    //  3) Add the days of the month.
    //  4) Clear everything else.

    int month = calendar.get(Calendar.MONTH);
    int year  = calendar.get(Calendar.YEAR);

    fire_ActionEvent( CHANGE_ACTION, months[month] + " " + year );

    calendar.set( year, month, 1 ); // First day of the current month.

    int first_day_offset = calendar.get(Calendar.DAY_OF_WEEK);      /* 1 */

    assert Calendar.SUNDAY == 0;
    assert first_day_offset < days.length;

    int i = 0;
    while( i < first_day_offset-1 )                              /* 2 */
        days[i++].setText("");

    int day_of_month = 1;
    for(; i < days.length; ++i )                                 /* 3 */
    {
        if( calendar.get(Calendar.MONTH)==today.get(Calendar.MONTH)
        &&  calendar.get(Calendar.YEAR )==today.get(Calendar.YEAR )
        &&  calendar.get(Calendar.DATE )==today.get(Calendar.DATE ) )
        {   highlight( days[i] );
        }

        days[i].setText( String.valueOf(day_of_month) );

        calendar.roll( Calendar.DATE, /*up=*/ true );   // Forward one day.

        day_of_month = calendar.get(Calendar.DATE);
        if( day_of_month == 1 )
            break;
    }

    // Note that we break out of the previous loop with i positioned
    // at the last day we added, thus the following ++ *must* be a
    // preincrement because we want to start clearing at the cell
    // after that.

    while( ++i < days.length )                                 /* 4 */
        days[i].setText("");

    setVisible(true);
}

private JButton highlighted = null;
private void clear_highlight()
{
    if( highlighted != null )
    {   highlighted.setBackground( Color.WHITE );
        highlighted.setForeground( Color.BLACK );
        highlighted.setOpaque(false);
        highlighted = null;
    }
}

private void highlight( JButton cell )
{
    highlighted = cell;
    cell.setBackground( com.holub.ui.Colors.DARK_RED );
    cell.setForeground( Color.WHITE );
    cell.setOpaque( true );
}

    类的其他部分定义了获取calendar值的几种方法。都是些非常简单的,在这里就没有列出来。

ealy ,java 爱好者,Matrix jsp翻译小组成员,可以点击http://www.matrix.org.cn/user_view.ASP?username=ealy查看她的个人信息 
进入讨论组讨论。

(出处:)


上一篇:KVM的常量池 人气:618
下一篇:解决日期选择问题,一劳永逸(使用Decorator模式实现日期选择组件)(二) 人气:943
浏览全部J2EE/J2ME的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐