質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.78%

カレンダーを作成中ですが、祝日の色変更をしようとしています。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,922

score 9

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.Calendar;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class debugTest {
 public static void main(String[] args) {
  JFrame frame = new JFrame("Swing Calender");
  frame.add(new SwingCalendar());
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.pack();
  frame.setVisible(true);
 }
}

class SwingCalendar extends JPanel {
 private JLabel  monthLabel = new JLabel();
 private JLabel  yearLabel = new JLabel();
 Calendar cal = Calendar.getInstance();

 //曜日、日付ラベル作成
 private JLabel[]    weekLabels = new JLabel[7];
 private JLabel[][]  dayLabels = new JLabel[6][7];

 //各パーツのColorの作成
 private static final Color WEEK_BG = new Color(102,102,102);
 //private static final LineBorder WEEK_BORDER = new LineBorder(new  Color(160,160,230), 2, false);

 //日付パネルの色
 private static final Color DAY_BG = new Color(102,102,102);
 private static final Color DAY_FG = Color.BLACK;
 private static final LineBorder DAY_BORDER = new LineBorder(new Color(102,102,102), 2, false);

 //日付のLabel
 private static final Dimension DAY_LABEL_SIZE = new Dimension(50,50);
 private static final String[] WEEK_NAMES = new String[] {"日", "月", "火", "水", "木", "金", "土"};
 private static final String[] MONTH_NAMES = new String[] {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};

 public SwingCalendar() {
 try {
 UIManager.setLookAndFeel(
 "javax.swing.plaf.nimbus.NimbusLookAndFeel"
 );
 } catch (ClassNotFoundException | InstantiationException
 | IllegalAccessException | UnsupportedLookAndFeelException e) {
 e.printStackTrace();
 }

 /* MONTH Label */
 Dimension dm = monthLabel.getPreferredSize();
 dm.width += 10; //dm.height += 1;
 monthLabel.setPreferredSize(dm);
 monthLabel.setForeground(DAY_FG);

 /* YEAR Label */
 Dimension dy = yearLabel.getPreferredSize();
 dy.width += 10; //dy.height += 1;
 yearLabel.setPreferredSize(dy);
 yearLabel.setForeground(DAY_FG);

 /* DAY PANEL */
 JPanel dayPanel = new JPanel();
 GridLayout layout = new GridLayout(7, 7);
 layout.setHgap(0);
 layout.setVgap(0);
 dayPanel.setLayout(layout);
 dayPanel.setBackground(DAY_BG);

 //曜日の配列
 for( int i=0; i<7; i++) {
  weekLabels[i] = new JLabel(WEEK_NAMES[i]);
  weekLabels[i].setHorizontalAlignment(SwingConstants.CENTER);
  weekLabels[i].setVerticalAlignment(SwingConstants.CENTER);
  weekLabels[i].setPreferredSize(DAY_LABEL_SIZE);
  weekLabels[i].setOpaque(true);
  weekLabels[i].setBackground(WEEK_BG);
 
  if( i == 0 ) {
    weekLabels[i].setForeground(Color.RED);
  } else if ( i == 6 ) {
    weekLabels[i].setForeground(Color.BLUE);
  }

  System.out.println("kakunin" + i);
  dayPanel.add(weekLabels[i]);
 }


 //日付の配列
  for( int i=0; i<6; i++) {
     for( int j=0; j<7; j++) {
        dayLabels[i][j] = new DayLabel("test");

            if(j == 0 ) {
              dayLabels[i][j].setForeground(Color.RED);
            } else if (j == 6 ) {
              dayLabels[i][j].setForeground(Color.BLUE);
            }  

      dayPanel.add(dayLabels[i][j]);
     }
      System.out.println("i" + i); //確認
          System.out.println("j" + j); //確認
  }

  JPanel monthPanel = new JPanel();
  monthPanel.setLayout(new GridLayout());
  monthPanel.add(yearLabel);
  monthPanel.add(monthLabel);
  monthPanel.setBackground(DAY_BG);

  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
  GridLayout gl = new GridLayout(1,2);
  gl.setHgap(10); gl.setVgap(10);

  //年月ボタン表示パネル、日にちパネルの追加
  add(monthPanel);
  add(dayPanel);

 }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • shuriboo

    2018/08/16 19:30

    @opyonさん ご指摘ありがとうございます。修正いたしました。

    キャンセル

  • m.ts10806

    2018/08/16 22:18

    コードブロック内はコードだけを書いてください。コード以外のものが入ると再現確認の際の弊害にしかなりません。また、インデントが全くない状態なので非常に読みづらいですし、ミスが起きやすくなっています。調整してください。あと「うまくいきません」では何が起きているか伝わらないのて起きている現象を具体的に記載してください。このあたりは「質問するときのヒント」を熟読して質問内容を調整すると良いです(質問内容が充実することで的確な回答を得やすくなります) https://teratail.com/help/question-tips

    キャンセル

  • m.ts10806

    2018/08/17 19:54

    説明文全部削除したらただコード投げただけのも丸投げですよ・・・。コードも大事ですがそのコードで起きている現象やエラー、何がどう想定通りにできていないのか具体的に書くのも必要です。

    キャンセル

回答 1

checkベストアンサー

0

曜日の日付部分を色替えしたいという仕様と想定して回答いたします。
一般的なDatepickerのコードからやりたい事を憶測して
コードを見た感じでは

 //日付の配列
 for( int i=0; i<6; i++) {
  for( int j=0; j<7; j++) {
       // ↓ ※1 JLabelのテキスト文字を設定していません。
       dayLabels[i][j] = new JLabel(); //String.valueOf(i),(j)
       // 中略
    if( i == 0 && j == 0 ) { // ← ※2
      dayLabels[i][j].setForeground(Color.RED);
    } else if ( i == 6 && j == 0 ) { // ← ※3
      dayLabels[i][j].setForeground(Color.BLUE);
    }


この3箇所が変です。j==0の時しか前景色が変わりません。
あとi == 6と判定していますが、変数:iがループの中で6になることはfor( int i=0; i<6; i++)ループ上ありえないかと。

というわけでこんな感じでは。

    if(j == 0) {
      dayLabels[i][j].setForeground(Color.RED);
    } else if (j == 6) {
      dayLabels[i][j].setForeground(Color.BLUE);
    }

土、日の判定はこれで大丈夫ですが、
春分の日と秋分の日が年によって違うので祝日を判定するにはこれではダメです。
祝日の情報をどこかに持つ必要があります。
LocalDateを使って、LocalDate#plusDays で日付を1づつ加算して表を作るのをお勧めいたします。


余談
以下のようなコードは、JLabelを継承したクラスを1個作るとコード記述が減らせます。

   dayLabels[i][j] = new JLabel(); //String.valueOf(i),(j)
   dayLabels[i][j].setHorizontalAlignment(SwingConstants.CENTER);
   dayLabels[i][j].setVerticalAlignment(SwingConstants.CENTER);
   dayLabels[i][j].setOpaque(true);
   dayLabels[i][j].setBackground(DAY_BG);
   dayLabels[i][j].setPreferredSize(DAY_LABEL_SIZE);
class DayLabel extends JLabel {
   public DayLabel(String s) {
      super(s);
      this.setHorizontalAlignment(SwingConstants.CENTER);
      this.setVerticalAlignment(SwingConstants.CENTER);
      this.setOpaque(true);
      this.setBackground(DAY_BG);
      this.setPreferredSize(DAY_LABEL_SIZE);
   }
}
// 使い方
dayLabels[i][j] = new DayLabel("test");

曜日とコードがほぼ同じなので、コンストラクタを改良して共通化するのも一つの手かと。


LocalDateを使ったサンプルコードです、あとは自力で頑張ってくださいな。

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

class SwingCalendar extends JPanel {
    private JLabel[] dayLabels; // 一次元配列(0オリジン)
    public SwingCalendar() {
        // 前略
        dayPanel.setBackground(DAY_BG);
        // 当月1日
        final LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        // 一ヶ月間のラベルのリスト(最後に配列化)
        final List<JLabel> dayList = new ArrayList<>();

        for (LocalDate day : getDateList(firstDay)) {
            final int d = day.getDayOfMonth();
            System.out.println(d);
            JLabel label = new JLabel(String.valueOf(d));
            label.setHorizontalAlignment(SwingConstants.CENTER);
            label.setVerticalAlignment(SwingConstants.CENTER);
            label.setOpaque(true);
            label.setBackground(DAY_BG);
            label.setPreferredSize(DAY_LABEL_SIZE);
            // 土、日の判定のみなので、ここに祝日判定が必要
            switch (day.getDayOfWeek()) {
            case SUNDAY:
                label.setForeground(Color.RED);
                break;
            case SATURDAY:
                label.setForeground(Color.BLUE);
                break;
            default:
                label.setForeground(Color.WHITE);
                break;
            }
            dayList.add(label);
            dayPanel.add(label);
        }

        // GridLayoutが7*7=49で残りをFillする。
        IntStream.range(0, 49 - dayList.size()).forEach(x -> {
            // GridLayoutに項目を追加する。
            dayPanel.add(new JLabel(""));
        });
        // リストから配列に変換
        dayLabels = dayList.toArray(new JLabel[0]);
        JPanel monthPanel = new JPanel();
        // 以下省略
    }
    public static List<LocalDate> getDateList(final LocalDate start) {
        final int days = start.lengthOfMonth();
        return Stream.iterate(start, d -> d.plusDays(1)).limit(days).collect(Collectors.toList());
    }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/17 18:35

    個人的にはLocalDateを使ってループを回して1次元配列で管理するほうが、iとjの2重ループで2次元配列で管理するより楽なのではないかと思うのですが。

    キャンセル

  • 2018/08/17 18:50

    @umyuさん
    LocalDateで書き直してみます。
    ありがとうございます!

    キャンセル

  • 2018/08/20 13:29

    @umyuさん
    重ね重ねありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る