3

以下のコードでは、同じテーブルのさまざまな行について、編集可能なコンボボックスを最初の行のエディター(ユーザーが使用可能な選択肢から選択するか、独自に入力できるようにするため)、2番目の行のファイルチューザーおよびデフォルトとして設定しようとしています。残りの行についてはtextFiled。

問題:そしてそれを再現するためのステップ:

1-コードを実行します 。2-2番目の行をクリックしてフォルダを選択します(行が黄色に変わります) 3-次に最初の行をクリックしてムービーのタイプを選択します(クリックするだけで、何も入力したり選択したりする必要はありません) 4-次に、2行目をもう一度クリックします(フォルダの選択)

この行の内容が最初の行にコピーされるのがわかりますか?!

スレッドセーフではないスイングの処理、参照の処理など、私が正しく行わなかったことがたくさんあることを私は知っています。皆さんが私がこのバグを修正してこのコードを何かしっかりしたものに変えるのを手伝ってくれるかどうか疑問に思いました。

ユーザーが選択する前に出力をプログラムする

上記の手順を実行した後:

ここに画像の説明を入力してください

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.TableModel;

public class CCellEditor extends DefaultCellEditor {

    private JTable m_Table = null;

    public CCellEditor(JFrame parentFrame, JTable table) { 
        super(new JTextField());
        super.setClickCountToStart(1);
        m_Table = table;
    }
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, final int row, int column){

        if(row==0) // comBoBox for First row
        {
            Object[] objectArray = {"3D","2D"};
            JComboBox comboBox = new JComboBox(objectArray);
            comboBox.setEditable(true);
            comboBox.setSelectedItem(value);

            ItemListener itemListener = new ItemListener() {
                public void itemStateChanged(ItemEvent e) {
                    if(e.getStateChange() == ItemEvent.SELECTED) {
                        if(null != m_Table.getCellEditor()){ 
                            m_Table.getCellEditor().stopCellEditing();
                        }

                        m_Table.setValueAt(e.getItem(), row, 1);
                    }
                }
            };
            comboBox.addItemListener(itemListener);

            PopupMenuListener popMenuEvent = new PopupMenuListener() {

                public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                }

                public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                    String sValue = (String)m_Table.getValueAt(row, 1);
                    if(null != m_Table.getCellEditor()){ 
                        m_Table.getCellEditor().stopCellEditing();
                    }
                    m_Table.setValueAt(sValue, row, 1);
                }

                public void popupMenuCanceled(PopupMenuEvent e) {   
                }

            };
            comboBox.addPopupMenuListener(popMenuEvent);

            return comboBox;

        }

        else  if(row==1)  // fileChooser for Second row
        {
            JFileChooser fileChooser;
            fileChooser = new JFileChooser("c:\\");
            fileChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
            fileChooser.setVisible(true);
            int returnVal = fileChooser.showOpenDialog(null);

            JTextField textField = (JTextField)super.getTableCellEditorComponent(table, value, isSelected, row, column);
            textField.setBackground(Color.yellow);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File m_fFirmware= fileChooser.getSelectedFile();

                textField.setText(m_fFirmware.getPath());
                return textField;

            }else
            {
                return textField; 

            }
        }
                                // for any other rows
        JTextField textField = (JTextField)super.getTableCellEditorComponent(table, value, isSelected, row, column);
        return textField;

    }

    public static void main(String[] a) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        String[] columnTitles = { "Name", "Value"};
        Object[][] dataEntries = {
                { "Movie Type:", "3D" }, {"Folder:","C:"}, {"# of Movies requested:","5"}};
        TableModel model = new EditableTableModel(columnTitles, dataEntries);
        JTable table = new JTable(model);
        table.createDefaultColumnsFromModel();
        table.setDefaultEditor(Object.class, new CCellEditor(frame, table));
        frame.add(new JScrollPane(table));
        frame.setSize(300, 200);
        frame.setVisible(true);
    }

}

EditableTableModelクラスは次のとおりです。

import javax.swing.table.AbstractTableModel;


class EditableTableModel extends AbstractTableModel {
  String[] columnTitles;

  Object[][] dataEntries;

  int rowCount;

  public EditableTableModel(String[] columnTitles, Object[][] dataEntries) {
    this.columnTitles = columnTitles;
    this.dataEntries = dataEntries;
  }

  public int getRowCount() {
    return dataEntries.length;
  }

  public int getColumnCount() {
    return columnTitles.length;
  }

  public Object getValueAt(int row, int column) {
    return dataEntries[row][column];
  }

  public String getColumnName(int column) {
    return columnTitles[column];
  }

  public Class getColumnClass(int column) {
    return getValueAt(0, column).getClass();
  }

  public boolean isCellEditable(int row, int column) {
    return true;
  }

  public void setValueAt(Object value, int row, int column) {
    dataEntries[row][column] = value;
  }



}
4

2 に答える 2

3

予備調査では、モデルに変更のリスニングビューを通知させることを提案しています。

public void setValueAt(Object value, int row, int column) {
    dataEntries[row][column] = value;
    fireTableCellUpdated(row, column);
}

初期スレッドも参照して、これらのデフォルトディレクトリの1つを検討してください。

fileChooser = new JFileChooser(System.getProperty("user.dir"));
fileChooser = new JFileChooser(System.getProperty("user.home"));
于 2012-06-14T23:55:03.967 に答える
3

しばらく時間がかかったことを認めなければなりませんが、問題を見つけました。DefaultCellEditor.getCellEditorValue()実装にとって重要な関数をオーバーライドしていません。この関数は、編集中のセルがフォーカスを失ったとき、またはその他の理由で編集が完了したときに呼び出されます。とにかく、あなたの場合は、最後のデフォルトのTableCellEditor(DefaultCellEditorから)から最終的な値を取得するだけです。これが、最初の行が最後に編集されたセル値に置き換えられ続ける理由です。

問題を解決する方法は次のとおりです。

  1. へのグローバル参照を作成しますcomboBox
  2. 最後に編集されたアイテムが2行目だった場合は、オーバーライドgetCellEditorValue()して返します。comboBox.getSelectedItem()それ以外の場合は、を返しsuper.getCellEditorValue()ます。

これで現在の問題は修正されますが、コードで多くの改善が行われる可能性があります。

于 2012-06-15T01:23:11.443 に答える