簡體   English   中英

只要單元格失去焦點,Jtable可以保存數據嗎?

[英]Can a Jtable save data whenever a cell loses focus?

高級:我有一個用戶可以用來編輯數據的JTable。

每當用戶按Enter或Tab鍵完成編輯時,數據都會被保存(我發現“保存”實際上意味着“調用TableModel的setValueAt()方法”。)

如果用戶在進行編輯后以任何其他方式離開單元格,則不會保存新數據,並且值保持原樣。 因此,例如,如果用戶更改了值,然后單擊屏幕上的其他窗口小部件,則更改不會“粘住”。

我相信這是一個充滿字符串的JTable的默認行為,是嗎?

由於各種原因,所需的行為是單元格在用戶離開單元格時保存任何和所有編輯。 讓Swing做到這一點的最佳/正確方法是什么?

表停止編輯解釋了發生了什么,並提供了幾個簡單的解決方案。

提出的一個簡單的解決方案

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

僅適用於String列。 問題是如果我有,例如,正在編輯的列的Float類型,在相應的單元格中輸入一個空字符串,然后單擊該窗口的任何其他控件 - Java在JTable.java CellEditorRemover.propertyChange()方法中拋出NullPointerException 它使用getCellEditor()調用來停止或取消編輯,但在這種情況下它返回null 如果輸入的值不為空或者如果我刪除terminateEditOnFocusLost標志,一切都很好。 可能,描述的情況是一個錯誤。

我希望我可以根據之前的帖子之一提供解決方案。 它不像我之前想象的那么簡單,但在我看來它是有效的。 我必須從默認單元格編輯器繼承我自己的單元格編輯器,並從JTextField繼承自己的文本字段,該文本字段具有FocusListener 當編輯單元格失去焦點時,此焦點偵聽器工作正常,而另一個窗口控件獲得焦點。 但是在細胞選擇改變的情況下,焦點聽眾是“聾”。 這就是為什么我還必須在編輯之前記住以前的有效值,如果輸入的值無效,則恢復它。

請參閱下面的代碼。 使用DoubleFloatInteger測試,但我希望這也適用於ByteString

帶焦點監聽器的文本字段:

public class TextFieldCell extends JTextField {
    public TextFieldCell(JTable cellTable) {
        super();                            // calling parent constructor
        final JTable table = cellTable;     // this one is required to get cell editor and stop editing

        this.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
            }

            // this function successfully provides cell editing stop
            // on cell losts focus (but another cell doesn't gain focus)
            public void focusLost(FocusEvent e) {
                CellEditor cellEditor = table.getCellEditor();
                if (cellEditor != null)
                    if (cellEditor.getCellEditorValue() != null)
                        cellEditor.stopCellEditing();
                    else
                        cellEditor.cancelCellEditing();
            }
        });
    }
}

默認單元格編輯器類:

class TextFieldCellEditor extends DefaultCellEditor {
TextFieldCell textField;    // an instance of edit field
Class<?> columnClass;       // specifies cell type class
Object valueObject;         // for storing correct value before editing
public TextFieldCellEditor(TextFieldCell tf, Class<?> cc) {
    super(tf);
    textField = tf;
    columnClass = cc;
    valueObject = null;
}

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    TextFieldCell tf = (TextFieldCell)super.getTableCellEditorComponent(table, value, isSelected, row, column);
    if (value != null) {
        tf.setText(value.toString());
    }
    // we have to save current value to restore it on another cell selection
    // if edited value couldn't be parsed to this cell's type
    valueObject = value;
    return tf;
}

@Override
public Object getCellEditorValue() {
    try {
        // converting edited value to specified cell's type
        if (columnClass.equals(Double.class))
            return Double.parseDouble(textField.getText());
        else if (columnClass.equals(Float.class))
            return Float.parseFloat(textField.getText());
        else if (columnClass.equals(Integer.class))
            return Integer.parseInt(textField.getText());
        else if (columnClass.equals(Byte.class))
            return Byte.parseByte(textField.getText());
        else if (columnClass.equals(String.class))
            return textField.getText();
    }
    catch (NumberFormatException ex) {

    }

    // this handles restoring cell's value on jumping to another cell
    if (valueObject != null) {
        if (valueObject instanceof Double)
            return ((Double)valueObject).doubleValue();
        else if (valueObject instanceof Float)
            return ((Float)valueObject).floatValue();
        else if (valueObject instanceof Integer)
            return ((Integer)valueObject).intValue();
        else if (valueObject instanceof Byte)
            return ((Byte)valueObject).byteValue();
        else if (valueObject instanceof String)
            return (String)valueObject;
    }

    return null;
}

它是表初始化的代碼,你必須添加以下內容:

myTable.setDefaultEditor(Float.class, new TextFieldCellEditor(new TextFieldCell(myTable), Float.class));
myTable.setDefaultEditor(Double.class, new TextFieldCellEditor(new TextFieldCell(myTable), Double.class));
myTable.setDefaultEditor(Integer.class, new TextFieldCellEditor(new TextFieldCell(myTable), Integer.class));

希望,這將有助於有同樣問題的人。

您需要添加焦點偵聽器 鑒於JTable基本上是其單元組件的容器,您實際上希望表中每個單元格的焦點偵聽器需要按照您指示的方式運行。

為此,您需要創建自定義單元格編輯器,該編輯器包裝具有已注冊焦點偵聽器的單元組件。 當您獲得失去焦點事件的回調時,您可以根據需要進行數據保存。

這幾乎是您需要做的大部分細節 實現焦點監聽器的細節不存在,但這是相當簡單的。

假設您確實使用JTextComponent作為單元組件。 然后:

public void focusLost(FocusEvent e) {
   JTextComponent cell = (JTextComponent) e.getSource();  
   String data = cell.getText();

   // TODO: save the data for this cell
}

[ps編輯]:

使用此事件調用您的線程是調度線程。 請勿將其用於具有高延遲的操作。 但是如果你只是在堆中翻轉位,那應該沒問題。

暫無
暫無

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

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