Java JTableの利用
JTableとレンダラー、セルエディタのサンプル.
使用しているコンポーネント名は、
private javax.swing.JButton jButtonLoad;//日付に対応した文字列データをすべて保存
private javax.swing.JButton jButtonSave;//文字列データをすべてファイルから復元
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel5;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSpinner jSpinner1;//月の選択
private javax.swing.JSpinner jSpinner2;//年の選択
private javax.swing.JTable jTable1;//カレンダーの表示
カレンダーのセルをクリックすると,
その日付に対する文字列入力を行えるように入力用ダイアログが表示されます。入力された文字列はファイルへの保存と読み出しが行えます。
例によって、NetBeansで作成したソースファイルの自動生成部分以外の部分のみを掲載します。
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.SwingConstants; import java.awt.Color; import java.awt.Component; import javax.swing.JTable; import javax.swing.*; import javax.swing.table.TableColumn; import java.awt.Font; import java.io.*; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.TimeZone; /* * CalenderTable.java * */ /** * * @author kom */ public class CalenderTable extends javax.swing.JFrame { int counter=0; HashMap上のCalenderTableクラスの定義と以下のクラスMyRendererの定義およびクラスDateCalcの定義 は同じファイル内に書いて構いません。planMap = new HashMap (); private String[] columnNames = {"日", "月", "火", "水", "木", "金", "土"}; //デザイナのjTable1のプロパティのmodelに、ユーザコード→カスタムコードで、 //tableModelを設定。( jTable1.setModel(tableModel); ) DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0); String[][] tabledata = { //はじめはすべて空にするなら、単に配列の要素数指定でもよい {"","","","","","",""}, {"","","","","","",""}, {"","","","","","",""}, {"","","","","","",""}, {"","","","","","",""}, {"","","","","","",""} }; public CalenderTable() { initComponents(); for(int i = 0 ; i < tabledata.length ; i++){ tableModel.addRow(tabledata[i]); } jTable1.setFont(new Font(Font.DIALOG, Font.PLAIN, 32));//通常表示時のフォント MyRenderer myRen1 = new MyRenderer(); MyRenderer myRen2 = new MyRenderer(); myRen2.setBackground(Color.pink); for (int i = 0; i < jTable1.getColumnCount(); ++i) { TableColumn tc = jTable1.getColumn(jTable1.getColumnName(i)); if(i==0){ tc.setCellRenderer(myRen2);//Pink Background }else{ tc.setCellRenderer(myRen1); } } //以下の2行は、セル単位で選択できるようにするための記述。 jTable1.setColumnSelectionAllowed(false); jTable1.setRowSelectionAllowed(false); //以下は、起動時に現在の年月でカレンダが表示されるようにするためのもの。 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Japan")); Integer Year=new Integer(cal.get(Calendar.YEAR)); jSpinner2.setValue(Year); Integer Month=new Integer(cal.get(Calendar.MONTH)+1); jSpinner1.setValue(Month); makeTable(); } private void jTable1MouseClicked(java.awt.event.MouseEvent evt) { // jTable1のセルをマウスクリックしたときに、入力ダイアログが表示され、 //入力した文字列は、OKボタンをクリックするとHashMapクラスのplanMapに入力される。 //InputDlg1は別ファイルに外部クラスとして作ってある。 int row = jTable1.getSelectedColumn(); //行番号 int col = jTable1.getSelectedRow(); //列番号 int cy=(Integer)jSpinner2.getValue(); int cm=(Integer)jSpinner1.getValue(); int selRow = jTable1.getSelectedRow(); int selCol= jTable1.getSelectedColumn(); String strcd= (String)jTable1.getValueAt(selRow, selCol); if(strcd==null || strcd.equals("")){ return; } int cd=Integer.parseInt(strcd); if(cd<1 || cd>31){ return; }else{ DateCalc dt=new DateCalc(cy,cm,cd); setPlan(dt); } } private void jSpinner1StateChanged(javax.swing.event.ChangeEvent evt) { //スピナの値が変更されたらここに処理が移る //スピナで表示されている月のデータを,テーブルに表示する。 makeTable(); } private void jSpinner2StateChanged(javax.swing.event.ChangeEvent evt) { makeTable(); } private void jButtonSaveActionPerformed(java.awt.event.ActionEvent evt) { File file=null; JFileChooser filechooser = new JFileChooser("c:\\");//デフォルトC:\とする int selected = filechooser.showSaveDialog(this); if (selected == JFileChooser.APPROVE_OPTION){ file = filechooser.getSelectedFile(); saveMap(file.getAbsolutePath()); }else if (selected == JFileChooser.CANCEL_OPTION){ //Cansel }else if (selected == JFileChooser.ERROR_OPTION){ //Error } } private void jButtonLoadActionPerformed(java.awt.event.ActionEvent evt) { File file=null; JFileChooser filechooser = new JFileChooser("c:\\"); int selected = filechooser.showOpenDialog(this); if (selected == JFileChooser.APPROVE_OPTION){ file = filechooser.getSelectedFile(); loadMap(file.getAbsolutePath()); }else if (selected == JFileChooser.CANCEL_OPTION){ //Cansel }else if (selected == JFileChooser.ERROR_OPTION){ //Error } } private void saveMap(String fpath) { try { ObjectOutputStream objOutStream = new ObjectOutputStream(new FileOutputStream(fpath)); objOutStream.writeObject(planMap); objOutStream.close(); } catch (Exception e) { System.out.println("例外:"+ e +"発生。"); } } private void loadMap(String fpath) { try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fpath)); planMap = (HashMap )ois.readObject(); ois.close(); } catch (Exception e) { System.out.println("例外:"+ e +"発生。"); } } void dataClear(){ //DefaultTableModel jTable1Model = (DefaultTableModel)jTable1.getModel(); int ix=jTable1.getColumnCount(); int iy=jTable1.getRowCount(); for (int i=0; i =n){ jTable1.setValueAt(Integer.toString(m), ypos, i); m++; } } ypos++; //次の行へ while(m<= lastDay){ //lastDayは月の最終日 for(int i=0; i<7 && m<=lastDay; i++){ jTable1.setValueAt(Integer.toString(m), ypos, i); m++; } ypos++; } } /** * @param args the command line arguments */ public static void main(String args[]) { (内容は省略。NetBeansによる自動生成。) ............... } //ここまでがCalenderTableクラスの定義。
/* クラスMyRendererの定義 */ class MyRenderer extends DefaultTableCellRenderer { //JTableの表示をコントロールするためのクラス public boolean editable=false; //表の編集を不可にするために、編集不可属性のセルエディタを作成する。 JTextField txfld=new JTextField(""); JTextField txfldEditable=new JTextField(""); DefaultCellEditor defCE, editableCE; MyRenderer(){ txfld.setEditable(false); txfldEditable.setEditable(true); txfld.setFont(new Font(Font.DIALOG,Font.PLAIN, 24));//編集時のフォント txfldEditable.setFont(new Font(Font.DIALOG,Font.PLAIN, 24));//編集時のフォント defCE=new DefaultCellEditor(txfld); editableCE=new DefaultCellEditor(txfldEditable); } @Override public Component getTableCellRendererComponent( final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column ) { this.setHorizontalAlignment(SwingConstants.CENTER); for (int i = 0; i < table.getColumnCount(); ++i) { TableColumn tc = table.getColumn(table.getColumnName(i)); if(editable){ tc.setCellEditor(editableCE); }else{ tc.setCellEditor(defCE); } } return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } }
/* クラスDateCalcの定義 */ class DateCalc{ private int year; //現在年 private int month; //現在月 private int day; //現在日 public int totalDay; //西暦1年1月1日から現在までの日数 // DateCalc(){} // DateCalc(int cyear, int cmonth, int cday) { int wkYear, wkMonth; year = cyear; month = cmonth; day = cday; totalDay = day; for(wkYear=1; wkYear < year ; wkYear++){ if(isLeapYear(wkYear)) totalDay += 366; //閏年なら366日 else totalDay += 365; } for(wkMonth=1; wkMonth < month; wkMonth++){ //現在の年の現在の月の前月までの日数を計算 totalDay += dayNumber(year, wkMonth); } } DateCalc(int dayCount) { //AD1年1月1日からの経過日数をパラメータとしてコンストラクタを呼び出す場合 int wkSum=0; boolean sw=false; //作業用変数 totalDay = 0; year = 1; month = 1; while(true){ //まず、1年単位で日数を加えていき、与えられた日数を越えたら //ループを終了 if(isLeapYear(year)){ wkSum += 366; } else { wkSum +=365; } if(wkSum < dayCount){ totalDay=wkSum; year++; } else { break; } } while(true){ //その後、月単位で1月から順に日数を加えていく wkSum=dayNumber(year, month); //月の日数 if(totalDay+wkSum < dayCount){ totalDay += wkSum; month++; }else{ day = dayCount - totalDay; totalDay += day; break; } } } static boolean isLeapYear(int y){ if((y %4 == 0 && y % 100 != 0) || y % 400 == 0){ return true; }else{ return false; } } static int dayNumber(int yr, int mn){ int wk=0; if(mn==2){ if(isLeapYear(yr)){ wk=29; } else{ wk=28; } } else{ if(mn==4 || mn==6 || mn==9 || mn==11){ wk=30; } else{ wk=31; } } return wk; } int difference(DateCalc d2) { //他のDateCalcの持つ日数との差を計算する。 //月初めまでの日数を求めるために使う。 //月初めまでの日数がわかれば、月初めの曜日が計算できる。 return totalDay - d2.totalDay; } }以下はさらに予定文字列入力用のダイアログクラス。NetBeansで別ファイルに作成。 人間が入力した部分のみ。コンポーネントは入力用にJTextAreaのjTextArea1、JButtonのOKbtnを使用しています。
import java.awt.event.*; class InputDlg1 extends javax.swing.JDialog { public boolean btnflag=false; public String datatext=""; /** Creates new form InputDlg1 */ public InputDlg1(java.awt.Frame parent, boolean modal, String txt) { super(parent, modal); initComponents(); jTextArea1.setText(txt); addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent e) { btnflag=false; } }); moveCenter(); } private void moveCenter(){ Dimension dim=Toolkit.getDefaultToolkit().getScreenSize(); setLocation( (dim.width-getSize().width)/2,(dim.height-getSize().height)/2); } private void OKbtnActionPerformed(java.awt.event.ActionEvent evt) { datatext=jTextArea1.getText(); this.setVisible(false); } }
動作画面例
Kom., 2013