标题 这Date_selector_panel是重要部分现在我们来看看他的装饰Titled_date_selector类只做一件事情给未装饰的日历增加个标题这是对实现了Date_selector的JPanel面板的包装它只显示现有的Date_selector和显示日期的标签下面的实现是微不足道和用户界面无相关值得说的只有那其中行动作监听代码监听器获取日期改变通知(通过用户导航或者方法调用)便做相应的标签日期更新其他代码只是简单地创建面板和将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 ) { thisselector = selector; titlesetHorizontalAlignment(SwingConstantsCENTER); titlesetOpaque ( true); titlesetBackground ( comholubuiColorsLIGHT_YELLOW); titlesetFont ( titlegetFont()deriveFont( FontBOLD ) ); selectoraddActionListener ( new ActionListener() { public void actionPerformed( ActionEvent e ) { if( egetID() == Date_selector_panelCHANGE_ACTION ) titlesetText( egetActionCommand() ); else my_subscribersactionPerformed(e); } } ); setOpaque(false); setLayout( new BorderLayout() ); add( titleBorderLayoutNORTH ); add( (JPanel)selector BorderLayoutCENTER ); } /** 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 ) titlesetOpaque( false ); else titlesetBackground( label_background_color ); } private ActionListener my_subscribers = null; public synchronized void addActionListener(ActionListener l) { my_subscribers = AWTEventMulticasteradd(my_subscribers l); } public synchronized void removeActionListener(ActionListener l) { my_subscribers = AWTEventMulticasterremove(my_subscribers l); } public Date get_selected_date() { return selectorget_selected_date();} public Date get_current_date(){ return selectorget_current_date(); } public void roll(int f boolean up) {selectorroll(fup); } public intget(int f){ return selectorget(f); } } NAVIGATION/导航 下面展示的就是导航栏的实现代码虽然有点长但同样非常地简单代码由定义了个图象文件的代码开始(我计划以后放弃箭头采用代码实现但是现在仍然在用图象文件)用下面的代码把图象作为资源获取过来 ClassLoader loader = getClass()getClassLoader(); loadergetResource( 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/pxredarrowrightdoublegif NEXT_MONTH= images/pxredarrowrightgif PREVIOUS_YEAR = images/pxredarrowleftdoublegif PREVIOUS_MONTH= images/pxredarrowleftgif; // These constants are used to identify the button and // as the button caption in the event that the appropriate // image file cant 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 ) { thisselector = selector; setBorder( null); setOpaque( false ); setLayout( new BorderLayout() ); add( (JPanel)selector BorderLayoutCENTER ); navigationsetLayout(new FlowLayout()); navigationsetBorder( null ); navigationsetBackground( comholubuiColorsLIGHT_YELLOW ); navigationadd( make_navigation_button(BACK_YEAR) ); navigationadd( make_navigation_button(BACK_MONTH ) ); navigationadd( make_navigation_button(FORWARD_MONTH) ); navigationadd( make_navigation_button(FORWARD_YEAR ) ); add(navigation BorderLayoutSOUTH); } // // 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 = egetActionCommand(); if (direction==FORWARD_YEAR )selectorroll(CalendarYEARtrue); else if(direction==BACK_YEAR)selectorroll(CalendarYEARfalse); else if(direction==FORWARD_MONTH) { selectorroll(CalendarMONTHtrue); if( selectorget(CalendarMONTH) == CalendarJANUARY ) selectorroll(CalendarYEARtrue); } else if (direction==BACK_MONTH) { selectorroll(CalendarMONTHfalse); if( selectorget(CalendarMONTH) == CalendarDECEMBER ) selectorroll(CalendarYEARfalse); } else { assert false:Unexpected direction; } } } private JButton make_navigation_button(String caption) { ClassLoader loader = getClass()getClassLoader(); URL image = (cap |