🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JTable

JTableとは二次元的なセルの表を表示し編集するJava Swing用のコンポーネントです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

1回答

1166閲覧

JTableの一列目を日付欄にすることができたのですが追加ボタンを押すと今さっき追加した行の日付が更新されてしまいます。

rokkunroru

総合スコア10

JTable

JTableとは二次元的なセルの表を表示し編集するJava Swing用のコンポーネントです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2022/02/14 17:34

前提・実現したいこと

新しい行を追加しても前に追加した行の日付はそのままにしたい

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; public class SwingTest extends JFrame implements ActionListener { private DefaultTableModel tableModel; private JTable table; private String[] header = { "日付", "氏名", "振り仮名", "内容", "住所", "金額", "備考", }; private String[] emptyRow = {}; public static void main(String args[]) { SwingTest frame = new SwingTest("Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } SwingTest(String title) { setTitle(title); setSize(1000, 1080); tableModel = new DefaultTableModel(header, 0); table = new JTable(tableModel); table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); table.getTableHeader().setReorderingAllowed(false); table.setRowHeight(30); table.setFont(new Font("SansSerif", Font.BOLD, 20)); JButton btn1 = new JButton("追加"); btn1.addActionListener(this); btn1.setActionCommand("追加"); JButton btn2 = new JButton("削除"); btn2.addActionListener(this); btn2.setActionCommand("削除"); JScrollPane sp = new JScrollPane(table); sp.setPreferredSize(new Dimension(1000, 1000)); JPanel p = new JPanel(); p.add(sp); getContentPane().add(p, BorderLayout.CENTER); getContentPane().add(btn1, BorderLayout.NORTH); getContentPane().add(btn2, BorderLayout.SOUTH); } @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("追加")) { tableModel.addRow(emptyRow); table.getColumnModel().getColumn(0).setCellRenderer(new DateCellRenderer()); } else if (cmd.equals("削除")) { int option = JOptionPane.showConfirmDialog(this, "削除しますか?", "選択ダイアログ", JOptionPane.YES_NO_OPTION); if (option == JOptionPane.YES_OPTION) { int[] selection = table.getSelectedRows(); for (int i = selection.length - 1; i >= 0; i--) { tableModel.removeRow(table.convertRowIndexToModel(selection[i])); } } } } class DateCellRenderer implements TableCellRenderer { public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label = new JLabel(); Date date = new Date(); SimpleDateFormat sd = new SimpleDateFormat("yyyy/MM/dd/ (E) HH:mm:ss"); String valueDate = sd.format(date); label.setText(valueDate); return label; } } }

わからないこと

1.こうなってしまうのを防ぐためにはデータベースとかの知識が必要ですか?もしくはほかに何か必要な知識とかありますか?
2. https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12249187517
このサイトを参考にしてJTableに日付欄を作ったのですがそもそもレンダラーという物の使い方がわかりません。
レンダラーについて書いてある初心者にわかりやすいサイトがネットのどこにもなくて困ってるんですがそういうサイトがあれば教えていただきたいです。
3. Javaって2022年も現役でしょうか Swingとかこのまま使ってても何か支障がでたりしませんか?

補足情報(FW/ツールのバージョンなど)

All in One パッケージ Eclipse 2021

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

セルレンダラは、1つで全行の該当列の描画に使用されます。
ですのでデータ毎に設定する必要はありません。最初に一回設定するだけで済むはずです。
1つで全ての行の該当列の描画を行うため、描画に使用するデータは全てパラメータから得る必要があります。
描画する行・列は row, column 、フォーカス状態・選択状態は hasFocus, isSelected 、そしてデータそのものは value です。
value は JTable が TableModel の getValueAt から得たものです。
TableModel の該当行・列に表示したい日付が入っていて getValueAt で Date オブジェクトとして返されれば value はそのオブジェクトとなりますので、 Date にキャストして利用してください。

ざっくり直すとこんな感じです。

java

1package teratail_java.q_9uc7u8pf4rfyv0; 2 3import java.awt.*; 4import java.awt.event.ActionEvent; 5import java.awt.event.ActionListener; 6import java.text.DateFormat; 7import java.text.SimpleDateFormat; 8import java.util.Date; 9 10import javax.swing.*; 11import javax.swing.table.DefaultTableCellRenderer; 12import javax.swing.table.DefaultTableModel; 13 14public class SwingTest extends JFrame { 15 private static String[] header = { "日付", "氏名", "振り仮名", "内容", "住所", "金額", "備考", }; 16 17 public static void main(String args[]) { 18 new SwingTest().setVisible(true); 19 } 20 21 SwingTest() { 22 super("Sample"); 23 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 24 setSize(1000, 1080); 25 26 DefaultTableModel tableModel = new DefaultTableModel(header, 0); 27 28 JTable table = new JTable(tableModel); 29 table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); 30 table.getTableHeader().setReorderingAllowed(false); 31 table.setRowHeight(30); 32 table.setFont(new Font("SansSerif", Font.BOLD, 20)); 33 table.getColumnModel().getColumn(0).setCellRenderer(new DateCellRenderer()); 34 35 JButton btn1 = new JButton("追加"); 36 btn1.addActionListener(new ActionListener() { 37 @Override 38 public void actionPerformed(ActionEvent e) { 39 InputDataPanel inputDataPanel = new InputDataPanel(); 40 int option = JOptionPane.showOptionDialog(SwingTest.this, inputDataPanel, "追加", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null); 41 if(option != JOptionPane.OK_OPTION) return; 42 43 tableModel.addRow(inputDataPanel.getRowDatas()); 44 } 45 }); 46 47 JButton btn2 = new JButton("削除"); 48 btn2.addActionListener(new ActionListener() { 49 @Override 50 public void actionPerformed(ActionEvent e) { 51 int option = JOptionPane.showConfirmDialog(SwingTest.this, "削除しますか?", "選択", JOptionPane.YES_NO_OPTION); 52 if(option != JOptionPane.YES_OPTION) return; 53 54 int[] selection = table.getSelectedRows(); 55 for(int i = selection.length - 1; i >= 0; i--) { 56 tableModel.removeRow(table.convertRowIndexToModel(selection[i])); 57 } 58 } 59 }); 60 61 add(new JScrollPane(table), BorderLayout.CENTER); 62 add(btn1, BorderLayout.NORTH); 63 add(btn2, BorderLayout.SOUTH); 64 } 65 66 class DateCellRenderer extends DefaultTableCellRenderer { 67 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 68 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 69 70 setText(createDateFormat().format((Date)value)); 71 return this; 72 } 73 } 74 75 private static DateFormat createDateFormat() { 76 return new SimpleDateFormat("yyyy/MM/dd/ (E) HH:mm:ss"); 77 } 78 79 class InputDataPanel extends JPanel { 80 private Date date; 81 private JTextField nameText, howToReadText, contentsText, addressText, moneyText, etcText; 82 83 InputDataPanel() { 84 super(new GridBagLayout()); 85 86 date = new Date(); 87 88 GridBagConstraints gbc = new GridBagConstraints(); 89 90 JTextField dateText = createViews("日付", gbc); 91 dateText.setEditable(false); 92 dateText.setText(createDateFormat().format(date)); 93 94 nameText = createViews("氏名", gbc); 95 howToReadText = createViews("振り仮名", gbc); 96 contentsText = createViews("内容", gbc); 97 addressText = createViews("住所", gbc); 98 moneyText = createViews("金額", gbc); 99 etcText = createViews("備考", gbc); 100 } 101 102 private JTextField createViews(String labelText, GridBagConstraints gbc) { 103 gbc.gridx = 0; 104 add(new JLabel(labelText), gbc); 105 gbc.gridx = 1; 106 JTextField textfield = new JTextField(20); 107 add(textfield, gbc); 108 return textfield; 109 } 110 111 Object[] getRowDatas() { 112 return new Object[]{ date, nameText.getText(), howToReadText.getText(), contentsText.getText(), addressText.getText(), moneyText.getText(), etcText.getText()}; 113 } 114 } 115}

セルレンダラは、単に文字列を表示するだけであれば DefaultTableCellRenderer を使った方が isSelected や hasFocus の処理をしてくれますので便利です。 (JLabel を用いるより負荷を軽減するようにも設計されているようです。)

投稿2022/02/14 18:43

編集2022/02/16 15:29
jimbe

総合スコア13195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rokkunroru

2022/02/16 10:07 編集

すみません、初心者なもので 「 Date にキャストして利用してください。」ていうところのコードは getValueAtの中で★★★ = (Date)value; っていう感じでよろしいでしょうか、よかったらコードを教えてほしいです もう分かりません泣きそうです
jimbe

2022/02/16 11:21

セルレンダラの中の Date date = new Date(); という行を Date date = (Date)value; とするということです。
rokkunroru

2022/02/16 11:46

たびたびすみません。Date date = (Date)value;にして実行して追加ボタンを押すと date must not be null と出たので if(value instanceof Date){    Date date = (Date)value;    SimpleDateFormat sd = new SimpleDateFormat("yyyy/MM/dd/ (E) HH:mm:ss"); String str = sd.format(date); label.setText(str); } return label; に書き換えたらエラーは出ないんですが表示もされない状態になりました
jimbe

2022/02/16 13:30 編集

データの追加の部分を見ると、全くデータが入っていない空の配列を渡しているだけです。 tableModel.addRow(emptyRow); 表示すべきデータを入れなければ JTable としては表示のしようがありません。
rokkunroru

2022/02/16 14:02

リファレンスみると addRow public void addRow(Object[] rowData) モデルの最後に行を追加します。新しい行の値は、rowData が指定されていない場合は null になります。行の追加の通知が生成されます。 って書いてて、でも自分がやりたいのは空っぽの行を追加して値を入力して保存するっていうことなんですけど これじゃあ無理ってことですかね
jimbe

2022/02/16 14:15

> 空っぽの行を追加して値を入力して保存する コード的には逆のほうが分かり易いと思います。 つまり、追加ボタンを押したら ( 例えば ) 入力用のダイアログを出して日付や氏名等を入力し、 OK が押されたらそのデータで TableModel に addRow するということです。
rokkunroru

2022/02/17 11:28

すみません、いろいろ試したんですけどやっぱり Date date = new Date(); SimpleDateFormat sd = new SimpleDateFormat("yyyy/MM/dd/ (E) HH:mm:ss"); String str = sd.format(date); tableModel.addRow(new Object[] {str}); とやった方がわかりやすいし、次の行を追加してもその前の行の日付も変更されずに済みました こっちの場合「ファイルを名前を付けて保存」「上書き保存」っていう機能を付ければデータは残りますよね?
jimbe

2022/04/08 14:23 編集

どうするかはもちろん rokkunroru さんが決められることですので、問題ありません。 日付を文字列で保持すればセルレンダラも要りませんし、簡単になりますね。 > こっちの場合「ファイルを名前を付けて保存」「上書き保存」っていう機能を付ければデータは残りますよね? 保存するコードをどう書くかも rokkunroru さん次第ですので、何とも言えませんが、String だから出来、 Date だと出来ないということは無いと思います。 TableModel に Date で持っていても、ファイル入出力時に (SimpleDateFormat 等を使って) 文字列に/文字列から 変換すれば良いでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問