0

JSpinnerをJTableに実装しようとしていますが、一見するとかなりうまくいきましたが、セルのフォーカスを失った後、編集されたセルは「Thu Jan 01 + time+UTC1970」に設定されています。正しく設定してください。時刻から日付を削除するにはどうすればよいですか?

これが私の穴ですSpinnerEditor.class、いくつかのコメントを追加しました。

コード:

public SpinnerEditor(String timeFormat) {
    super(new JTextField());

    // Default Time I want to Display (1 Hour)
    Time date = new Time(3600000);
    SpinnerDateModel timeModel = new SpinnerDateModel(date, null, null,Calendar.MINUTE);
    spinner = new JSpinner(timeModel);
    editorDate = new JSpinner.DateEditor(spinner, timeFormat);
    spinner.setEditor(editorDate);


    editorDate = ((JSpinner.DateEditor)spinner.getEditor());
    // println result : "Thu Jan 01 01:00:00 UTC 1970"
    System.out.println(editorDate.getTextField().getValue());
    textField = editorDate.getTextField();
    textField.addFocusListener( new FocusListener() {
        public void focusGained( FocusEvent fe ) {
            System.err.println("Got focus");
            //textField.setSelectionStart(0);
            //textField.setSelectionEnd(1);
            SwingUtilities.invokeLater( new Runnable() {
                public void run() {
                    if ( valueSet ) {
                        textField.setCaretPosition(1);
                    }
                }
            });
        }
        public void focusLost( FocusEvent fe ) {
        }
    });
    textField.addActionListener( new ActionListener() {
        public void actionPerformed( ActionEvent ae ) {
            stopCellEditing();
        }
    });
}

// Prepares the spinner component and returns it.
public Component getTableCellEditorComponent(
    JTable table, Object value, boolean isSelected, int row, int column
) {
    if ( !valueSet ) {
        spinner.setValue(value);
    }
    SwingUtilities.invokeLater( new Runnable() {
        public void run() {
            textField.requestFocus();
        }
    });
    return spinner;
}

public boolean isCellEditable( EventObject eo ) {
    System.err.println("isCellEditable");
    if ( eo instanceof KeyEvent ) {
        KeyEvent ke = (KeyEvent)eo;
        System.err.println("key event: "+ke.getKeyChar());    
        textField.setText(String.valueOf(ke.getKeyChar()));
        valueSet = true;
    } else {
        valueSet = false;
    }
    return true;
}

// Returns the spinners current value.
public Object getCellEditorValue() {
    return spinner.getValue();
}

public boolean stopCellEditing() {
    System.err.println("Stopping edit");
    // after stopcellEditing is called the TextField is being set with the wrong values (Thu Jan 01 01:00:00 UTC 1970)
    super.stopCellEditing();
    try {
        if( editorNumeric!=null) 
        {
            editorNumeric.commitEdit();
            spinner.commitEdit();

        }
        if( editorDate!=null)
        {
            SimpleDateFormat lFormat = new SimpleDateFormat("HH:mm");
            textField.setText((spinner.getValue() != null) ? lFormat.format(spinner.getValue()) : "");
        }

    } catch ( java.text.ParseException e ) {
        JOptionPane.showMessageDialog(null,
            "Invalid value, discarding.");
    }

    return true;
}
4

2 に答える 2

3

簡単な作業ではありません。つまり、ButtonGroupのJRadioButton、単純なJButton、およびJSpinnerには、2つの方法があります。

  • 2つのJSpinners(JButton eiと同じ要件)を使用し、SpinnerListModelを使用します。この場合、JTableで言及されているJButtonに必要なコードの束を減らすことができます。

このコードはNumberInstance用です

import java.awt.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;

public class SpinnerColumn extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

    private static final long serialVersionUID = 1L;
    private JSpinner editSpinner, renderSpinner;
    private JTable table;
    private String[] list;
    private Border originalBorder;

    public SpinnerColumn(JTable table, int column) {
        editSpinner = new JSpinner();
        renderSpinner = new JSpinner();
        originalBorder = editSpinner.getBorder();
        editSpinner.setBorder(new LineBorder(Color.BLUE));
        this.table = table;
        table.getColumnModel().getColumn(column).setCellEditor(this);
    }

    public SpinnerColumn(String[] list, JTable table, int column) {
        editSpinner = new JSpinner();
        editSpinner.setModel(new SpinnerListModel(list));
        renderSpinner = new JSpinner();
        originalBorder = editSpinner.getBorder();
        editSpinner.setBorder(new LineBorder(Color.BLUE));
        this.list = list;
        this.table = table;
        table.getColumnModel().getColumn(column).setCellEditor(this);
    }

    @Override
    public Object getCellEditorValue() {
        return editSpinner.getValue();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
            int row, int column) {
        if (list != null) {
            editSpinner.setValue(list[0]);
        } else {
            editSpinner.setValue(0);
        }
        if (value != null) {
            editSpinner.setValue(value);
        }
        return editSpinner;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        if (hasFocus) {
            renderSpinner.setBorder(new LineBorder(Color.BLUE));
        } else {
            renderSpinner.setBorder(originalBorder);
        }
        // *** here's where we set the spinner's value
        if (value == null) {
            renderSpinner.setValue(0);
        } else {
            int intValue = ((Integer) value).intValue();
            renderSpinner.setValue(intValue);
        }
        return renderSpinner;
    }

    @Override
    public boolean isCellEditable(EventObject evt) {
        return true;
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame("SpinnerColumn");
                JPanel panel = new JPanel(new GridLayout(1, 1));
                JTable table = new JTable(5, 1);
                SpinnerColumn spinnerColumn = new SpinnerColumn(table, 0);
                table.setDefaultRenderer(Object.class, spinnerColumn);
                panel.add(table);
                frame.setContentPane(panel);
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });
    }
}
  • TableCellEditorでJSpinnerを再作成する

コード

import javax.swing.*;
import javax.swing.table.*;
import java.util.Date;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.swing.UIManager.LookAndFeelInfo;

public class TableTestPanel extends JPanel {

    private static final String[] COLUMN_NAMES = {"List ID", "Expiration Date", "Status", "Date Created"};
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
    private static final long serialVersionUID = 1L;

    private static class StatusPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        private JRadioButton theSingleOption;
        private JRadioButton theMarriedOption;
        private JRadioButton theDivorcedOption;

        StatusPanel() {
            super(new GridLayout(3, 1));
            setOpaque(true);
            ButtonGroup buttonGroup = new ButtonGroup();
            theSingleOption = new JRadioButton("Single");
            theSingleOption.setOpaque(false);
            add(theSingleOption);
            buttonGroup.add(theSingleOption);
            theMarriedOption = new JRadioButton("Married");
            theMarriedOption.setOpaque(false);
            add(theMarriedOption);
            buttonGroup.add(theMarriedOption);
            theDivorcedOption = new JRadioButton("Divorced");
            theDivorcedOption.setOpaque(false);
            add(theDivorcedOption);
            buttonGroup.add(theDivorcedOption);
        }

        public Status getStatus() {
            if (theMarriedOption.isSelected()) {
                return Status.MARRIED;
            } else if (theDivorcedOption.isSelected()) {
                return Status.DIVORCED;
            } else {
                return Status.SINGLE;
            }
        }

        public void setStatus(Status status) {
            if (status == Status.MARRIED) {
                theMarriedOption.setSelected(true);
            } else if (status == Status.DIVORCED) {
                theDivorcedOption.setSelected(true);
            } else {
                theSingleOption.setSelected(true);
            }
        }
    }

    private static class Status {

        static final Status SINGLE = new Status("Single");
        static final Status MARRIED = new Status("Married");
        static final Status DIVORCED = new Status("Divorced");
        private final String myName; // for debug only

        private Status(String name) {
            myName = name;
        }

        @Override
        public String toString() {
            return myName;
        }
    }

    private static class TableEntry {

        private static int instanceNumber;
        private Long theId;
        private Date theExpirationDate;
        private Status theStatus;
        private Date theCreationDate;

        TableEntry() {
            instanceNumber++;
            theId = new Long(instanceNumber);
            theExpirationDate = new Date();
            theStatus = Status.SINGLE;
            theCreationDate = new Date();
        }

        TableEntry(Long anId, Date anExpirationDate, Status aStatus, Date aCreationDate) {
            theId = anId;
            theExpirationDate = anExpirationDate;
            theStatus = aStatus;
            theCreationDate = aCreationDate;
        }

        public Long getId() {
            return theId;
        }

        public Date getExpirationDate() {
            return theExpirationDate;
        }

        public Status getStatus() {
            return theStatus;
        }

        public Date getCreationDate() {
            return theCreationDate;
        }

        public void setId(Long anId) {
            theId = anId;
        }

        public void setExpirationDate(Date anExpirationDate) {
            theExpirationDate = anExpirationDate;
        }

        public void setStatus(Status aStatus) {
            theStatus = aStatus;
        }

        public void setCreationDate(Date aCreationDate) {
            theCreationDate = aCreationDate;
        }
    }

    private static class MyTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;
        private Vector<Object> theEntries;

        MyTableModel() {
            theEntries = new Vector<Object>();
        }

        @SuppressWarnings("unchecked")
        public void add(TableEntry anEntry) {
            int index = theEntries.size();
            theEntries.add(anEntry);
            fireTableRowsInserted(index, index);
        }

        public void remove(int aRowIndex) {
            if (aRowIndex < 0 || aRowIndex >= theEntries.size()) {
                return;
            }
            theEntries.removeElementAt(aRowIndex);
            fireTableRowsDeleted(aRowIndex, aRowIndex);

        }

        public int getRowCount() {
            return theEntries.size();
        }

        @Override
        public String getColumnName(int column) {
            return COLUMN_NAMES[column];
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return Long.class;
                case 1:
                    return Date.class;
                case 2:
                    return Status.class;
                case 3:
                    return Date.class;
            }
            return Object.class;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
            switch (columnIndex) {
                case 0:
                    try {
                        entry.setId(new Long(Long.parseLong(aValue.toString())));
                    } catch (NumberFormatException nfe) {
                        return;
                    }
                    break;
                case 1:
                    entry.setExpirationDate((Date) aValue);
                    break;
                case 2:
                    entry.setStatus((Status) aValue);
                    break;
                case 3:
                    entry.setCreationDate((Date) aValue);
                    break;
                default:
                    return;
            }
            fireTableCellUpdated(rowIndex, columnIndex);
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
            switch (columnIndex) {
                case 0:
                    return entry.getId();
                case 1:
                    return entry.getExpirationDate();
                case 2:
                    return entry.getStatus();
                case 3:
                    return entry.getCreationDate();
            }
            return null;
        }
    }

    private static class DateRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (!(value instanceof Date)) {
                return this;
            }
            setText(DATE_FORMAT.format((Date) value));
            return this;
        }
    }

    private static class DateEditor extends AbstractCellEditor implements TableCellEditor {

        private static final long serialVersionUID = 1L;
        private JSpinner theSpinner;
        private Object value;

        DateEditor() {
            theSpinner = new JSpinner(new SpinnerDateModel());
            theSpinner.setOpaque(true);
            theSpinner.setEditor(new JSpinner.DateEditor(theSpinner, "dd/MM/yyyy"));
        }

        @Override
        public Object getCellEditorValue() {
            return theSpinner.getValue();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            theSpinner.setValue(value);
            if (isSelected) {
                theSpinner.setBackground(table.getSelectionBackground());
            } else {
                theSpinner.setBackground(table.getBackground());
            }
            return theSpinner;
        }
    }

    private static class StatusEditor extends AbstractCellEditor implements TableCellEditor {

        private static final long serialVersionUID = 1L;
        private StatusPanel theStatusPanel;

        StatusEditor() {
            theStatusPanel = new StatusPanel();
        }

        @Override
        public Object getCellEditorValue() {
            return theStatusPanel.getStatus();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            theStatusPanel.setStatus((Status) value);
            if (isSelected) {
                theStatusPanel.setBackground(table.getSelectionBackground());
            } else {
                theStatusPanel.setBackground(table.getBackground());
            }
            return theStatusPanel;
        }
    }

    private static class StatusRenderer extends StatusPanel implements TableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            setStatus((Status) value);
            if (isSelected) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
            return this;
        }
    }
    private MyTableModel theTableModel;
    private JTable theTable;

    public TableTestPanel() {
        super(new BorderLayout(0, 5));
        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        theTableModel = new MyTableModel();
        theTable = new JTable(theTableModel);
        theTable.setDefaultEditor(Date.class, new DateEditor());
        theTable.setDefaultRenderer(Date.class, new DateRenderer());
        theTable.setDefaultEditor(Status.class, new StatusEditor());
        theTable.setDefaultRenderer(Status.class, new StatusRenderer());
// comment out the two preceding lines and uncomment the following one if you want a more standard editor
// theTable.setDefaultEditor(Status.class, new DefaultCellEditor(new JComboBox(new Status[]{Status.SINGLE, Status.MARRIED, Status.DIVORCED})));
        add(new JScrollPane(theTable), BorderLayout.CENTER);
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.add(new AbstractAction("Add new") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                theTableModel.add(new TableEntry());
                packTable();
            }
        });
        toolBar.add(new AbstractAction("Remove") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                theTableModel.remove(theTable.getSelectedRow());
            }
        });
        add(toolBar, BorderLayout.NORTH);
    }

    private void packTable() {
        TableColumnModel columnModel = theTable.getColumnModel();
        int columnCount = theTable.getColumnCount();
        int rowCount = theTable.getRowCount();
        int[][] preferredHeights = new int[columnCount][rowCount];
        TableCellRenderer renderer;
        Component comp;
        for (int col = 0; col < columnCount; col++) {
            renderer = columnModel.getColumn(col).getCellRenderer();
            if (renderer == null) {
                renderer = theTable.getDefaultRenderer(theTableModel.getColumnClass(col));
            }
            for (int row = 0; row < rowCount; row++) {
                comp = renderer.getTableCellRendererComponent(theTable, theTableModel.getValueAt(row, col), false, false, row, col);
                preferredHeights[col][row] = (int) comp.getPreferredSize().getHeight();
            }
        }
        for (int row = 0; row < rowCount; row++) {
            int pref = 0;
            for (int col = 0; col < columnCount; col++) {
                pref = Math.max(pref, preferredHeights[col][row]);
            }
            theTable.setRowHeight(row, pref);
        }
    }

    public static void main(String[] args) {
        try {
            // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if (info.getName().equals("Nimbus")) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        final JFrame frame = new JFrame("TestRadioButtonRenderer");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new TableTestPanel());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame.setSize(400, 300);
                frame.setVisible(true);
            }
        });
    }
}
于 2012-05-16T10:35:16.247 に答える
2

あなたは編集者とレンダラーを混乱させています。エディターは、セルが編集されているときに表示されるウィジェットです。セルが編集されなくなると、セルレンダラーを使用してセルが「ペイント」されます。これはすべてこの段落で説明されています。テーブルレンダリングがどのように実行されるかを明確に説明しているので、これを読むことを強くお勧めします。

必要なことは、関連する列にカスタムCellRendererを使用して、日付フォーマッターを使用することです。

セルエディタとセルレンダラーの詳細については、このチュートリアルをご覧ください。

于 2012-05-16T10:09:39.400 に答える