Java 带有返回复杂数据类型的自定义编辑对话框的JTable

Java 带有返回复杂数据类型的自定义编辑对话框的JTable,java,swing,dialog,jtable,Java,Swing,Dialog,Jtable,在我的应用程序中,我有一个JTable,它允许修改数据。我的主要类型是绘画,可以有多个类别。所以Painting类有一个成员私有集合categoriesCategory是一个简单的POJO类,具有字符串名 我试图实现以下目标:在我的JTable中,我有一列用于输入类别。我想向用户显示类别名称列表。单击鼠标后,我想显示带有JList的对话框,该对话框将允许选择多个类别。 显示部分很容易-我提供了我的自定义表模型,并提供了getValueAt(int行,int列),它将Set转换为String 现在

在我的应用程序中,我有一个JTable,它允许修改数据。我的主要类型是
绘画
,可以有多个类别。所以
Painting
类有一个成员
私有集合categories
Category
是一个简单的POJO类,具有
字符串名


我试图实现以下目标:在我的JTable中,我有一列用于输入类别。我想向用户显示类别名称列表。单击鼠标后,我想显示带有JList的对话框,该对话框将允许选择多个类别。
显示部分很容易-我提供了我的自定义表模型,并提供了
getValueAt(int行,int列)
,它将
Set
转换为
String

现在我对自定义单元格编辑器有问题。我想从编辑器中接收
(选择已
绘制
所属的类别),并返回
,以便在正在编辑的
绘制
对象中替换它。
您能告诉我如何编写
getCellEditorValue
getTableCellEditorComponent
来满足我的需要吗?现在我很困惑他们应该提供什么作为回报


我还对
getTableCellEditorComponent
方法参数
对象值
感到困惑。为编辑器提供了什么价值?这与表model
getValueAt
method返回的值相同吗?或者它的值不同?

也许这个例子会有帮助:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

/*
 * The editor button that brings up the dialog.
 */
//public class TablePopupEditor extends AbstractCellEditor
public class TablePopupEditor extends DefaultCellEditor
    implements TableCellEditor
{
    private PopupDialog popup;
    private String currentText = "";
    private JButton editorComponent;

    public TablePopupEditor()
    {
        super(new JTextField());

        setClickCountToStart(1);

        //  Use a JButton as the editor component

        editorComponent = new JButton();
        editorComponent.setBackground(Color.white);
        editorComponent.setBorderPainted(false);
        editorComponent.setContentAreaFilled( false );

        // Make sure focus goes back to the table when the dialog is closed
        editorComponent.setFocusable( false );

        //  Set up the dialog where we do the actual editing

        popup = new PopupDialog();
    }

    public Object getCellEditorValue()
    {
        return currentText;
    }

    public Component getTableCellEditorComponent(
        JTable table, Object value, boolean isSelected, int row, int column)
    {

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                popup.setText( currentText );
//              popup.setLocationRelativeTo( editorComponent );
                Point p = editorComponent.getLocationOnScreen();
                popup.setLocation(p.x, p.y + editorComponent.getSize().height);
                popup.show();
                fireEditingStopped();
            }
        });

        currentText = value.toString();
        editorComponent.setText( currentText );
        return editorComponent;
    }

    /*
    *   Simple dialog containing the actual editing component
    */
    class PopupDialog extends JDialog implements ActionListener
    {
        private JTextArea textArea;

        public PopupDialog()
        {
            super((Frame)null, "Change Description", true);

            textArea = new JTextArea(5, 20);
            textArea.setLineWrap( true );
            textArea.setWrapStyleWord( true );
            KeyStroke keyStroke = KeyStroke.getKeyStroke("ENTER");
            textArea.getInputMap().put(keyStroke, "none");
            JScrollPane scrollPane = new JScrollPane( textArea );
            getContentPane().add( scrollPane );

            JButton cancel = new JButton("Cancel");
            cancel.addActionListener( this );
            JButton ok = new JButton("Ok");
            ok.setPreferredSize( cancel.getPreferredSize() );
            ok.addActionListener( this );

            JPanel buttons = new JPanel();
            buttons.add( ok );
            buttons.add( cancel );
            getContentPane().add(buttons, BorderLayout.SOUTH);
            pack();

            getRootPane().setDefaultButton( ok );
        }

        public void setText(String text)
        {
            textArea.setText( text );
        }

        /*
        *   Save the changed text before hiding the popup
        */
        public void actionPerformed(ActionEvent e)
        {
            if ("Ok".equals( e.getActionCommand() ) )
            {
                currentText = textArea.getText();
            }

            textArea.requestFocusInWindow();
            setVisible( false );
        }
    }

    private static void createAndShowUI()
    {
        String[] columnNames = {"Item", "Description"};
        Object[][] data =
        {
            {"Item 1", "Description of Item 1"},
            {"Item 2", "Description of Item 2"},
            {"Item 3", "Description of Item 3"}
        };

        JTable table = new JTable(data, columnNames);
        table.getColumnModel().getColumn(1).setPreferredWidth(300);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);

        // Use the popup editor on the second column

        TablePopupEditor popupEditor = new TablePopupEditor();
        table.getColumnModel().getColumn(1).setCellEditor( popupEditor );

        JFrame frame = new JFrame("Popup Editor Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JTextField(), BorderLayout.NORTH);
        frame.add( scrollPane );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

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

}

它显示一个弹出对话框。您需要自定义
getCellEditorValue()
方法以返回要存储在模型中的对象。

1。单击鼠标后,我想显示带有JList的对话框,该对话框将允许选择多个类别。==到目前为止,它不是关于TableCellEditor的,而是关于可以将值返回给XXXTableModel2的单独对象。使用setValueAt与getValueAt等效,并使用TableCellEditor执行相同的操作,3。您从未提到过关于XxxTableModel的内容,在大多数情况下并不重要,因为默认情况下会创建DefaultTableModel,但我建议为DefaultTableModel覆盖setValueAt,以便显示带有JList的对话框,该对话框将允许选择多个类别==简单易用的JComboBox(有列表,在紧急情况下,您可以覆盖AbstractListModel,甚至我建议使用MutableComboxModel)作为DefaultTableEditor(阅读Oracle教程了解工作代码示例)