Tides_of_War

盤根錯節

JTable セルに入力された値を変換して再セットする

最近Java(Swing)でGUIアプリを作成する機会がありました。
特にJTable絡みで悩むことが多かったので、覚書を残しておきます。

セルに入力された値に応じて、アプリ側で値を再セットする処理を実装しました。

例えば「岡義勇」と入力されれば「岡義勇」と修正する、「オリックスバッファローズ」と入力されれば「オリックスバファローズ」と修正……というのは冗談ですが、ユーザーフォームで形式を指定するような場合には、ユーザーに修正を促すのではなく、こちら側で修正するという補助を実装できるのではないでしょうか。

以下の例では、セルに半角英小文字が入力されれば、大文字に自動で変換します。

package table;

import java.awt.BorderLayout;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class ChangeValueTable extends JFrame {

    private JPanel contentPane;
    private JTable table;

    public ChangeValueTable() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 400, 250);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JScrollPane scrollPane = new JScrollPane();
        contentPane.add(scrollPane, BorderLayout.CENTER);

        table = new JTable();
        table.setModel(new DefaultTableModel(
            new Object[][] {
                {null, null, null},
                {null, null, null},
                {null, null, null}
            },
            new String[] {
                "1", "2", "3"
            }
        ));
        scrollPane.setViewportView(table);

        // セルの値変更時に変換処理を行う
        table.getModel().addTableModelListener(
                new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                if (e.getType() == TableModelEvent.UPDATE) {
                    // 入力された値を取得
                    int row = e.getFirstRow();
                    int column = e.getColumn();
                    String value = (String)table.getValueAt(row, column);

                    // 半角小文字が含まれていれば大文字に変換
                    // ※チェックを行わずに変換処理を行うと無限ループに陥る
                    Pattern p = Pattern.compile(".*[a-z].*");
                    Matcher m = p.matcher(value);
                    if (m.find()) {
                        table.setValueAt(value.toUpperCase(), row, column);
                    }
                }
            }
        });
    }

    public static void main(String[] args) {
        ChangeValueTable frame = new ChangeValueTable();
        frame.setVisible(true);
    }
}


「yamada taro」と入力して、エンターキーを押す等、フォーカスを移動すると、

「YAMADA TARO」に変換されました。

コメントにも記載していますが、変換処理だけを行うと無限ループに陥りますので、判定処理は必ず実装します。
当たり前のことですが、私はここでハマってしまいました。