this is a extra element for clear the floated element
使用Decorator模式实现日期选择组件(4)
  • 12/31
  • 2008
设计模式 | Java 1236 次查看
  标题

  这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
您可能感兴趣的:

更多相关内容