服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

使用decorator模式实现日期选择组件(4)


  标题
  这date_selector_panel是重要部分。现在我们来看看他的装饰。titled_date_selector类只做一件事情:给未装饰的日历增加个标题。这是对实现了date_selector的jpanel面板的包装。它只显示现有的date_selector和显示日期的标签。下面的实现是微不足道。和用户界面无相关值得说的只有那其中10行动作监听代码。监听器获取日期改变通知(通过用户导航或者方法调用)便做相应的标签日期更新。其他代码只是简单地创建面板和将date_selector与jlable标题包装进面板中。
  这表明这部分代码易写、易管理比较简单。如果它被混合在date_selector_panel中,将会在 没有明显的优点的情况下增加了代码的复杂度。(代码有组织地放在某处比全混合在一个地方更加清晰。)如果我想要标题更加美观,只需要修改这一个类即可以实现根本就不需要动其他部分。
  
  public class titled_date_selector extends jpanel implements date_selector
  {  private    date_selector selector;
    private final jlabel title = new jlabel("xxxx");
  
    /** wrap an existing date_selector to add a title bar showing
     * the displayed month and year. the title changes as the
     * user navigates.
     */
  
    public titled_date_selector( date_selector selector )
    {  this.selector = selector;
  
      title.sethorizontalalignment(swingconstants.center);
      title.setopaque   ( true                   );
      title.setbackground ( com.holub.ui.colors.light_yellow     );
      title.setfont    ( title.getfont().derivefont( font.bold )  );
  
      selector.addactionlistener
      (  new actionlistener()
        {  public void actionperformed( actionevent e )
          {  if( e.getid() == date_selector_panel.change_action )
              title.settext( e.getactioncommand() );
            else
              my_subscribers.actionperformed(e);
          }
        }
      );
  
      setopaque(false);
      setlayout( new borderlayout() );
      add( title, borderlayout.north );
      add( (jpanel)selector, borderlayout.center );
    }
  
    /** this constructor lets you specify the background color of the
     * title strip that holds the month name and year (the default
     * is light yellow).
     *
     * @param label_background_color the color of the title bar, or
     *   null to make it transparent.
     */
    public titled_date_selector( date_selector selector, color label_background_color )
    {  this(selector);
      if( label_background_color == null )
        title.setopaque( false );
      else
        title.setbackground( label_background_color );
    }
  
    private actionlistener my_subscribers = null;
    public synchronized void addactionlistener(actionlistener l)
    {  my_subscribers = awteventmulticaster.add(my_subscribers, l);
    }
    public synchronized void removeactionlistener(actionlistener l)
    {  my_subscribers = awteventmulticaster.remove(my_subscribers, l);
    }
  
    public date get_selected_date()   { return selector.get_selected_date(); }
    public date get_current_date()   { return selector.get_current_date();  }
    public void roll(int f, boolean up) {    selector.roll(f,up);      }
    public int get(int f)       { return selector.get(f);        }
  }
  
  navigation/导航
  下面展示的就是导航栏的实现代码,虽然有点长,但同样非常地简单。代码由定义了4个图象文件的代码开始。(我计划以后放弃箭头采用代码实现,但是现在仍然在用图象文件。)用下面的代码,把图象作为资源获取过来。
  classloader loader = getclass().getclassloader();
  loader.getresource( "image_file_name" );
  classloader在找类的地方找图象资源;比如,程序在文件系统中运行,它将要在classpath中查找文件路径。因为没有用到绝对路径,代码是更加容易的打包成jar文件,并且文件也不再需要建立在文件系统中。导航栏是一个四个用图象做标签的按纽,按纽的动作监听通过date_selector的roll()来包装日历对象,并且月份的改变也激发标题栏的改变。有一点非常重要就是导航条不知道也不影响标题。标题包装器是一个监听,所以它能自动的更新标题。导航条根本就不知道标题包装器的存在。
  
  public class navigable_date_selector extends jpanel implements date_selector
  {  private    date_selector selector;
  
    // names of image files used for the navigator bar
    private static final string
      next_year    = "images/10px.red.arrow.right.double.gif",
      next_month   = "images/10px.red.arrow.right.gif",
      previous_year  = "images/10px.red.arrow.left.double.gif",
      previous_month = "images/10px.red.arrow.left.gif";
  
    // these constants are used to identify the button and
    // as the button caption in the event that the appropriate
    // image file can't be located
  
    private static final string forward_month  = ">"  ,
                  forward_year  = ">>"  ,
                  back_month   = "<"  ,
                  back_year    = "<<"  
  
    private jpanel navigation = new jpanel();
  
    public navigable_date_selector( date_selector selector )
    {  this.selector = selector;
      setborder( null );
      setopaque( false );
      setlayout( new borderlayout() );
      add( (jpanel)selector, borderlayout.center );
  
      navigation.setlayout(new flowlayout());
      navigation.setborder( null );
      navigation.setbackground( com.holub.ui.colors.light_yellow );
      navigation.add( make_navigation_button(back_year  ) );
      navigation.add( make_navigation_button(back_month  ) );
      navigation.add( make_navigation_button(forward_month) );
      navigation.add( make_navigation_button(forward_year ) );
  
      add(navigation, borderlayout.south);
    }
  
    // ...
    // i left out a few constructors and utility methods that go here
    // ...
  
    private final navigation_handler navigation_listener
                      = new navigation_handler();
  
    /** handle clicks from the navigation bar buttons */
  
    private class navigation_handler implements actionlistener
    {  public void actionperformed(actionevent e)
      {  string direction = e.getactioncommand();
  
        if   (direction==forward_year )selector.roll(calendar.year,true);
        else if(direction==back_year  )selector.roll(calendar.year,false);
        else if(direction==forward_month)
        {
          selector.roll(calendar.month,true);
          if( selector.get(calendar.month) == calendar.january )
            selector.roll(calendar.year,true);
        }
        else if (direction==back_month )
        {
          selector.roll(calendar.month,false);
          if( selector.get(calendar.month) == calendar.december )
            selector.roll(calendar.year,false);
        }
        else
        {  assert false: "unexpected direction";
        }
      }
    }
  
    private jbutton make_navigation_button(string caption)
    {
      classloader loader = getclass().getclassloader();
      url image =
        (cap

扫描关注微信公众号