待办事项日历的设计、实验文档

界面设计

如图所示。在日历的右侧设置了事项面板,并且根据按照全天和自定义的方式分别设置了两个框图,在下方是显示事件的栏目。

日历UI
左侧显示的是日历,当成功添加一个事件,对应的日期变为黄色。当删除一个事件的时候,变回原来的颜色。

点击左侧日期时,按钮变为灰色,并且全天事项变为当天。如果当天有事项,就在下方显示出对应的事项。

代办事项功能设计

待办事项是一个独立的功能,因此可以重写一个 CalendarItem 类,DateChooser 类,ItemUtil 类来控制这个功能。

CalendarItem 类

该类继承自 CalendarDate 类,表示日历中会用到的事项,并且提供了几个属性 :Date start,Date end 分别表示开始的日期和结束的日期;属性 text 保存相关的待办事项;

方法名 方法描述
CalendarItem(Date start, Date end, String text) 参数为代办事项的开始时间以及结束时间,输入的Date对象为null,或者text为null,那么就抛出异常(CalendarException)

ItemUtil 类

该类是工具类,提供事项和日期相关的一些计算和判断方法。该构造函数已经被声明为 private,因此不可以实例化。属性 list属于 static,得到保存的事项列表。

方法名 方法描述
checkInTime(Date start, Date end, CalendarItem item) 参数为查询的日期,以及事项,返回值为boolean值。当事项的时间与输入的时间段有交叉部分时2,返回true。注意:当输入的对象全部为null,或者开始时间大于结束时间的时候,返回false。
hasItem(Date start) 参数为一天的年月日,返返回值为boolean值。判断这一天是否有项目,这个是用于更新面板时的动作。如果这一天有事项存在,那么返回true。
注意:当输入的对象为null时,返回false。
getItems(DateChooser chooser) 参数为DateChooser面板类型的对象,返回值为List。输入需要查询的面板类型,从中可以得到面板上的时间,从而得到在该时间段所有的事列表。
注意:当输入的chooser对象为null,返回null。
formmat(Date date) 参数为日期对象,返回值为Date对象。主要作用是将这个日期设置为当天的23:59分。
注意:当传入的参数为null时,返回null

DateChooser 类

继承自 JPanl,这是一个定制化的面板,定制化 JSpinner 对象,用于选择日期,还有查询按钮和添加事件的按钮。因为全天设置查询和自定义的设置查询不同,因此日期选择的行为也不同,也就是选择器上显示的日期不同。

方法名 方法描述
DateChooser(int select) 输入为int值,1或者2,分别代表是全天查询还是任意查询。
setText(Date startDate, Date endDate) 参数为开始时间和结束时间,用于设置时间选择器上的日期显示,没有返回值。如果输入的时间为null,或者不符合逻辑,那么将日期重新设置为今天。

实验报告

设计思路

待办事项是一个独立的功能,因此可以重写一个 CalendarItem 类,DateChooser 类,ItemUtil 类来控制这个功能。

CalendarItem 类是一个保存有关事项的类,里面主要保存事件的开始时间和结束时间,以及内容。每次成功创立一个事件之后,都 new 一个 CalendarItem 对象,并且将它保存在一个 Static 的 list 列表中。

ItemUtil 类是一个工具类,构造函数已经被 private 修饰,因此不能实例化。里面封装了和事项有关的各种工具。这个类主要被 DateChooser 类调用。

DateChooser 类继承自 JPanel,这是一个定制化的面板,设置了两个 JSpinner 的对象,用于选择日期,还有查询按钮和添加事件的按钮。因为全天设置查询和自定义的设置查询不同,因此日期选择的行为也不同。

事项的面板和日历的属于不同的个体,在上面进行操作,两者的联系便在于开始日期和结束日期。因为在日历面板的上方可以得到当前年月,因此二者可以顺利的匹配。

设计亮点

此次设计主要有以下亮点:

  • 面板设置人性化,较为合理。在日历的右侧设置了事项面板,并且根据按照全天和自定义的方式分别设置了两个框图,在下方是显示事件的栏目,一目了然。
  • 用户交互十分友好。按照逻辑,显然开始时间必须小于等于结束时间,因此动态监听了时间选择器的内容改变事件。当结束时间小于开始的时候,就自动将结束时间调整为开始时间,极大地避免了用户因为失误而造成的逻辑混乱。
  • 时间选择器的设置。此次学习到采用定制的JSpinner 组件十分的方便快捷。如下所示,windows 的内部也是采用这个模型,显然十分的简捷和方便,易于编辑并且选择。对于用户的错误输入,他可以自行处理为正确的,比如超过合理的输入,它可以自动进行时分的运算,转换为对应的第二天;或者选择没有反应。
//获得时间日期模型
SpinnerDateModel model = new SpinnerDateModel();
//获得JSPinner对象
JSpinner year = new JSpinner(model);
year.setValue(new Date());

设计遗憾

  • 由于对 swing 组件的错误认知,导致界面上有许多可以继续改进的地方。比如颜色形状等。
  • 查询事件的时候,在下方的框内显示事项不怎么友好。因为时间原因,并且对于 swing 的 Box 布局不熟,多个事项往往会溢出整个 frame;并且当添加的事项内容过多的时候,只能查看到一部分。这些都是需要改进的地方。

所遇问题及解决方法

  1. 如何处理全天和自定义日期之间的关系?
`因为按照全天和自定义的日期进行操作,在本质上相同,都是有着开始和结束时间。因此可以将两者归为一类进行事件的处理。将全天的开始时间设为00:00,结束设为23:59,就可以和自定义的用同一种事件处理机制。`
  1. 如何设置时间选择器?
`想了很多种方法,最简单的就是直接设置两个TexxtField框,让用户进行文本的输入,再次进行判断。可是这样对于用户很不友好,因为需要输入的文本过长,因此可能导致错误的输入。因此采用**JSpinner的组件**,用户既可以输入,也可以点击两旁的按钮进行选择;并且可以处理用户的错误输入,比如超过合理的输入,它可以自动进行时分的运算,转换为对应的第二天;或者不反应。`
  1. 点击删除按钮的时候,如何正确删除事件?
`因为需要将删除按钮和事件进行绑定,因此需要得到delete按钮的属性。e.getSource得到的是一个event,我一开始无论如何都无法得到事件源的属性。最终终于得到一个方法,就是将event强制转化为JButton类型,才解决问题。`

Test 类的修改说明

  • 新的测试改变了工具类 ItemUtil 类的测试用例,因为重新定义了用户输入日期的组件,并且组件可以自动判断自身的合法性,因此无需再重新鉴定输入的合法。