前回Javaでのカレンダーの基本的な作り方を学んだので今回はそれを利用してコンソールアプリを作成してみよう。前回は手続き型で処理を記述したが、今回はオブジェクト指向で作成していく。なお、この記事は前回の内容を理解している前提なのでまだの方はそちらからやっていただきたい。
実行例
実行すると以下のように今月のカレンダーを表示し、下に操作メニューが表示される。
pを入力すると前の月,nを入力すると次の月を表示する。以下は実行例
2021/1
Sun Mon Tue Wed Thu Fri Sat
1 2
3 4 5 6 7 8 *9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
prev:p,next:n,quit:q>p
2020/12
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
prev:p,next:n,quit:q>n
2021/1
Sun Mon Tue Wed Thu Fri Sat
1 2
3 4 5 6 7 8 *9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
prev:p,next:n,quit:q>n
2021/2
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
prev:p,next:n,quit:q>q
bye
qを入力するとアプリを終了する。現在の月を表示する際に今日の日付に*がついているのもポイントだ。
作成
まずは一般クラスとしてMyCalendarクラスを作成する。
MyCalendar.javaの作成
○以下のようにMyCalendar.javaを作成する。
import java.util.Calendar;
public class MyCalendar{
//アプリ実行中に変わることのない見出しは定数で定義
private static final String[] weeks= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
//今回主役となるCalendarインタンス
private Calendar cal;
//現在表示しているカレンダーの年
private int year;
//現在表示しているカレンダーの月(1~12)
private int month;
//現在表示しているカレンダーに本日があれば値が入る(なければ0)
private int today=0;
//コンストラクタ
public MyCalendar(){
//new された際に現在日時を持つカレンダーインスタンスを作成し
//フィールドにセットする。
this.cal=Calendar.getInstance();
//下にあるinitメソッドの実行
this.init();
}
//初期化処理
private void init() {
//カレンダーインスタンスからyearを設定
this.year=this.cal.get(Calendar.YEAR);
//カレンダーインスタンスからmonthを設定
this.month=this.cal.get(Calendar.MONTH)+1;
//表示してあるカレンダーに今日があるかの判定
//新規に現在のカレンダーインスタンスを作成し、それとフィールドを比較する
Calendar now=Calendar.getInstance();
if(now.get(Calendar.YEAR)==this.year && now.get(Calendar.MONTH)==this.month-1) {
//同じということは今見ているカレンダーは今月なので
//todayに今の日付を入れる
this.today=now.get(Calendar.DATE);
}else {
//違う月のカレンダーを見ている場合は0
this.today=0;
}
}
//見出し表示するメソッド
private void showHeader() {
System.out.printf("%16d/%d%n",this.year,this.month);
for(String s:weeks) {
System.out.printf("%4s",s);
}
System.out.println();
}
//月を変更するメソッド
protected void changeMonth(int offset) {
//引数で入ってきた値だけフィールドで保持しているカレンダーの月を
//ずらす(このメソッドはサブクラスからも呼べるようにprotectedとした)
this.cal.set(Calendar.MONTH,this.cal.get(Calendar.MONTH)+offset);
//月が変わったら初期化処理を行う
init();
}
//次の月に変更するメソッド
public void nextMonth() {
this.changeMonth(1);
}
//前の月に変更するメソッド
public void prevMonth() {
this.changeMonth(-1);
}
//実際に計算、描画を行うメソッド(詳しく前回の記事参照)
public void execute() {
this.cal.set(Calendar.DATE, 1);
int before=cal.get(Calendar.DAY_OF_WEEK)-1;
int daysCount=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
this.showHeader();
for(int i=0;i<before+daysCount;i++) {
String str="";
if(i>=before) {
int date=i+1-before;
str=String.valueOf(date);
if(date==this.today) {
str="*"+str;
}
}
System.out.printf("%4s", str);
if((i+1) % 7 == 0) {
System.out.println();
}
}
System.out.println();
}
}
publicとして公開しているのは前の月に移動するprevMonth(),次の月に移動するnextMonth(),実際に計算と描画を行うexecute()だけだ,このようにアクセス修飾を適切に行うと使いやすいクラスになる。
アプリケーションクラスの作成
それでは実行例のようになるようにアプリケーションクラスを作成していこう。
MyCalendarApp.javaを以下のように作成する。
import java.util.Scanner;
public class MyCalendarApp {
public static void main(String[] args) {
//ユーザー入力が受け取れるようにスキャナーインスタンス作成
Scanner sc=new Scanner(System.in);
//MyCalendarクラスのインスタン作成
MyCalendar mc=new MyCalendar();
while(true) {
//カレンダーの描画(最初は現在月)
mc.execute();
//メニュー表示
System.out.print("prev:p,next:n,quit:q>");
String select=sc.next();
if(select.equalsIgnoreCase("P")) {
//前の月に移動
mc.prevMonth();
}else if(select.equalsIgnoreCase("N")) {
//次の月に移動
mc.nextMonth();
}else {
//今回はp,n以外の入力をすべて終了とした。
break;
}
}
System.out.println("bye");
}
}
完成
以上で完成だ。今は必要最低限の機能しかないがメニューを増やし、直接2030年8月などの任意月を表示できるなど機能拡張してみてほしい。その際、直接MyCalnedarクラスを編集してもよいが、継承を利用してクラスを作ってみるのもよい勉強になるだろう。
関連記事
まずはこちらから学習するのをおすすめします!
コメント