簡體   English   中英

使用JSpinner啟用/禁用JTable

[英]JTable with JSpinner Enable/Disable

我有一個3列JTable。 第2列是一個復選框,我想為該行啟用/禁用JSpinner。

除了一件事之外,我已經開始工作了 - JSpinner實際上看起來不像它的禁用(文本和微調按鈕灰顯)。 我不太清楚如何實現這一目標。 我試過在JSpinner上強行調用setEnabled(false),但表似乎沒有正確重繪。

以下是我通過其他StackOverflow示例進行的一些代碼:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class SpinnerTable {
    public JComponent makeUI() {
        String[] columnNames = { "Name", "Spinner Enable", "Spinner" };
        final Object[][] data = { { "aaa", true, 1 }, { "bbb", true, 10 },
                { "ccc", true, 10 } };

        final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
            @Override
            public Class<?> getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }
        };
        JTable table = new JTable(model) {

            @Override
            public void setValueAt(Object aValue, int row, int column) {
                super.setValueAt(aValue, row, column);

            }

            @Override
            public boolean isCellEditable(int row, int column) {

                if (column == 2)
                    return (Boolean) model.getValueAt(row, 1);

                return super.isCellEditable(row, column);
            }

        };

        table.setRowHeight(36);
        table.setAutoCreateRowSorter(true);
        TableColumn column = table.getColumnModel().getColumn(2);
        column.setCellRenderer(new ComboBoxCellRenderer());
        column.setCellEditor(new ComboBoxCellEditor());

        return new JScrollPane(table);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new SpinnerTable().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class SpinnerPanel extends JPanel {
    protected JSpinner spinner = new JSpinner() {
        @Override
        public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();
            return new Dimension(40, d.height);
        }
    };

    public SpinnerPanel() {
        super();
        setOpaque(true);
        add(spinner);
    }
}

class ComboBoxCellRenderer extends SpinnerPanel implements TableCellRenderer {
    public ComboBoxCellRenderer() {
        super();
        setName("Table.cellRenderer");
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        setBackground(isSelected ? table.getSelectionBackground() : table
                .getBackground());
        if (value != null) {
            spinner.setValue(value);
        }
        return this;
    }
}

class ComboBoxCellEditor extends SpinnerPanel implements TableCellEditor {
    public ComboBoxCellEditor() {
        super();
        spinner.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                fireEditingStopped();

            }
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                fireEditingStopped();
            }
        });
    }

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

    // Copid from DefaultCellEditor.EditorDelegate
    @Override
    public Object getCellEditorValue() {
        return spinner.getValue();
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        if (anEvent instanceof MouseEvent) {
            MouseEvent e = (MouseEvent) anEvent;
            return e.getID() != MouseEvent.MOUSE_DRAGGED;
        }
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        fireEditingStopped();
        return true;
    };

    transient protected ChangeEvent changeEvent = null;

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

    @Override
    public void cancelCellEditing() {
        fireEditingCanceled();
    }

    @Override
    public void addCellEditorListener(CellEditorListener l) {
        listenerList.add(CellEditorListener.class, l);
    }

    @Override
    public void removeCellEditorListener(CellEditorListener l) {
        listenerList.remove(CellEditorListener.class, l);
    }

    public CellEditorListener[] getCellEditorListeners() {
        return listenerList.getListeners(CellEditorListener.class);
    }

    protected void fireEditingStopped() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1])
                        .editingStopped(changeEvent);
            }
        }
    }

    protected void fireEditingCanceled() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1])
                        .editingCanceled(changeEvent);
            }
        }
    }
}

該表不知道在修改第1列時應重新繪制第2列中的單元格。 您可以通過手動觸發更新來通知表。 例如,擴展模型的setValueAt()

@Override
public void setValueAt(Object aValue, int row, int column) {
    super.setValueAt(aValue, row, column);
    if (column == 1)
        fireTableRowsUpdated(row, row);
}

這將禁用編輯器,並且微調器將變得不可編輯。 如果您需要在視覺上實際禁用微調器,那么,在渲染器內,您可以基於isCellEditable啟用/禁用微調器,即:

spinner.setEnabled(table.isCellEditable(row, column));

請注意,在當前實現中,您可以擴展JTable以實現isCellEditablesetValueAt 這些應該是模型的一部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM