Jtable jcombobox和细胞编辑

时间:2014-05-23 07:51:42

标签: java swing combobox jtable

我想要一个包含4列的jtable。 一列必须是组合框。 其他列是字符串。

当我在单元格上单击一次时,我希望单元格可以使用闪烁的插入符号/光标进行编辑。此外,如果我单击组合框,我希望combox设置弹出窗口可见。

我已经阅读并测试了教程“如何使用表格”,如果我只在单元格中单击组合框,它就会打开。我的第一个问题是,当我们实现抽象表模型而不是使用DefaultTableModel时,我不明白为什么教程中的代码有效。

我的代码是:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public class JtabletestOK {

    public static void main(String[] args) {

        JtabletestOK test = new JtabletestOK();
        test.go();
    }

    public void go() {

        //create the frame
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



        //create a table and add it to a scroll pane in a new tab
        JTable jTable1 = new JTable()
        {
            //  Place cell in edit mode when it 'gains focus'

            public void changeSelection(
                    int row, int column, boolean toggle, boolean extend)
            {
                super.changeSelection(row, column, toggle, extend);

                if (editCellAt(row, column))
                {
                    Component editor = getEditorComponent();
                    editor.requestFocusInWindow();
                    // System.out.println("ffin focus gagne");
                    if (editor instanceof JTextField) {

                        JTextField jf = (JTextField) editor;
                        jf.select(0, jf.toString().length());
                    }}
            }
        };


        jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
        jTable1.setFillsViewportHeight(true);

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(jTable1);

        Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4"  };
        DefaultTableModel model = new DefaultTableModel(columnNames, 0);

        Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
        model.addRow(rowData);
        jTable1.setModel(model);


        String[] comboBoxArray = {"proem1","veitem2","atem3"};
        JComboBox jcb = new JComboBox(comboBoxArray);
        jcb.setEditable(true);


        TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
        colCombo.setCellEditor(new DefaultCellEditor(jcb));

        jcb.setEditable(true);



        frame.getContentPane().add(scrollPane);
        frame.pack();
        frame.setVisible(true);

    }

抽象模型的来源在这里: http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java

找到问题:在评论语句时jcb.setEditable(true);如果我在comboxcell上单击它就会打开单元格。 但我不知道为什么它会更好。另外,我希望combox可以编辑。

我如何为其他单元格拥有相同的行为。

您好,我已更新代码以便拥有 - 如果我通过覆盖方法在单元格上单击一次,则单元格变为可编辑 - 如果我通过覆盖方法

在单元格上单击一次,组合框就变得可编辑

我把新代码放在这里,它可能有助于其他代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.InputMap;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.text.JTextComponent;

public class JtabletestOK {

    public static void main(String[] args) {

        JtabletestOK test = new JtabletestOK();
        test.go();
    }

    public void go() {

        //create the frame
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



        //create a table and add it to a scroll pane in a new tab
        JTable jTable1 = new JTable()

        {
            //  Place cell in edit mode when it 'gains focus'

            public void changeSelection(
                    int row, int column, boolean toggle, boolean extend)
            {
                super.changeSelection(row, column, toggle, extend);

                if (column > 0)
                {

                    if (editCellAt(row, column))
                    {
                        Component editor = getEditorComponent();
                        editor.requestFocusInWindow();
                        // System.out.println("ffin focus gagne");
                        if (editor instanceof JTextField) {

                            JTextField jf = (JTextField) editor;
                            jf.select(0, jf.toString().length());
                        }}
                }
            }
        };



        jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
        jTable1.setFillsViewportHeight(true);
        replaceTabByEnter(jTable1);

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(jTable1);

        Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4"  };
        DefaultTableModel model = new DefaultTableModel(columnNames, 0);

        Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
        model.addRow(rowData);
        jTable1.setModel(model);


        String[] comboBoxArray = {"proem1","veitem2","atem3"};
        JComboBox jca = new JComboBox(comboBoxArray);
        jca.setSelectedItem("");
        JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent();

        jca.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                JComponent ja = (JComponent) e.getSource();
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                JComponent ja = (JComponent) e.getSource();
                JTable jtb = (JTable) ja.getParent();
                jtb.changeSelection(0,1,false,false);
            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
            }
        });



        editor.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Not mouseClicked yet.");
            }

            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("Not mousePressed yet.");
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                JComponent ja = (JComponent) e.getSource();
                JComponent jcbloc = (JComponent) ja.getParent();
                JComboBox jcb = (JComboBox) jcbloc;
                jcb.setPopupVisible(true);
                System.out.println("Not mouseReleased yet.");

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.println("Not mouseEntered yet.");
            }

            @Override
            public void mouseExited(MouseEvent e) {
                System.out.println("Not mouseExited yet.");
            }
        });

        autocompletecombo jcb =new autocompletecombo(jca);
        TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
        jca.setEditable(true);
        comboboxEditor cbe = new comboboxEditor(jca);
        colCombo.setCellEditor(cbe);

        frame.getContentPane().add(scrollPane);
        frame.pack();
        frame.setVisible(true);

    }


    public void replaceTabByEnter(JTable  jtane) {

        KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
        KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        InputMap im = jtane.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        im.put(enter, im.get(tab));
    }


    class comboboxEditor extends AbstractCellEditor implements TableCellEditor{

        JComboBox comboBox;
        JTextField jtf;

        S11InitialSelection sjcb;
        @Override
        public Object getCellEditorValue() {
            return comboBox.getSelectedItem();
        }

        public comboboxEditor(JComboBox jcb) {

            comboBox = jcb;
            jtf.selectAll();
        }

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

            comboBox.setSelectedItem(value);
            return comboBox;
        }

        public boolean stopCellEditing() {


            fireEditingStopped();
            //     jt.EditNextCell();
            return true;

        }


    }










}
  • 当我点击组合框时,我想通过选择它来突出显示文本。 我不记得如何从jcombobox获取文本字段以使用selectAll()方法或类似的东西。

我找到了解决方案:

            public void mouseReleased(MouseEvent e) {
                JComponent ja = (JComponent) e.getSource();
                JComponent jcbloc = (JComponent) ja.getParent();
                JComboBox jcb = (JComboBox) jcbloc;
                jcb.setPopupVisible(true);
                JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent();
                editor.setSelectionStart(0);
                editor.setSelectionEnd(editor.getText().length());
                System.out.println("Not mouseReleased yet.");

            }

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

我终于找到了解决所有问题的方法。我发布了所有代码。 我希望它会帮助别人。如果您找到更好的方法来解决问题,我就会打开。

它仍然是两件奇怪的事情,但它可以按照我想要的方式工作,所以如果有人作为一个想法:

  • 如果我移动代码

            if(e.getKeyChar() == KeyEvent.VK_ENTER){
                JComponent ja = (JComponent) e.getSource();
                JComboBox jcbloc = (JComboBox) ja.getParent();
                JTable jtb = (JTable) jcbloc.getParent();
                jtb.changeSelection(0,1,false,false);
            }
    

在keyReleased而不是keyPressed中,它不起作用。

  • 当我按下基本单元格文本时,程序将单独转到下一个单元格。我不明白如何通过输入密钥单独进入下一个单元格。

这里的所有代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.InputMap;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicTextUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.text.JTextComponent;


public class JtabletestOKStackOver {

public static void main(String[] args) {

    JtabletestOKStackOver test = new JtabletestOKStackOver();
    test.go();
}

public void go() {

    //create the frame
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //create a table and add it to a scroll pane in a new tab
    JTable jTable1 = new JTable()

    {
        //  Place cell in edit mode when it 'gains focus'

        public void changeSelection(
                int row, int column, boolean toggle, boolean extend)
        {
            super.changeSelection(row, column, toggle, extend);


            if (column > -1)
            {

                if (editCellAt(row, column))
                {
                    Component editor = getEditorComponent();
                    editor.requestFocusInWindow();
                    if (editor instanceof JTextField) {

                        JTextField jf = (JTextField) editor;
                        jf.select(0, jf.toString().length());
                    }
                    if (editor instanceof JComboBox) {
                        JComboBox jcb = (JComboBox) editor;
                        jcb.setPopupVisible(true);
                        JTextComponent editorCombo = (JTextComponent) jcb.getEditor().getEditorComponent();
                        editorCombo.setSelectionStart(0);
                        editorCombo.setSelectionEnd(editorCombo.getText().length());
                    }



                }
            }
        }
    };





    jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
    jTable1.setFillsViewportHeight(true);
    jTable1.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

    //Create the scroll pane and add the table to it.
    JScrollPane scrollPane = new JScrollPane(jTable1);

    Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4"  };
    DefaultTableModel model = new DefaultTableModel(columnNames, 0);

    Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
    model.addRow(rowData);
    jTable1.setModel(model);


    String[] comboBoxArray = {"proem1","veitem2","atem3"};
    JComboBox jca = new JComboBox(comboBoxArray);
    jca.setSelectedItem("");
    JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent();

    editor.addKeyListener(new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) {
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyChar() == KeyEvent.VK_ENTER){
                JComponent ja = (JComponent) e.getSource();
                JComboBox jcbloc = (JComboBox) ja.getParent();
                JTable jtb = (JTable) jcbloc.getParent();
                jtb.changeSelection(0,1,false,false);
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {

        }
    });


    editor.addFocusListener(new FocusListener() {

        @Override
        public void focusGained(FocusEvent e) {
            JComponent ja = (JComponent) e.getSource();
            JComponent jcbloc = (JComponent) ja.getParent();
            JComboBox jcb = (JComboBox) jcbloc;
            jcb.setPopupVisible(true);
            JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent();
            editor.setSelectionStart(0);
            editor.setSelectionEnd(editor.getText().length());
        }

        @Override
        public void focusLost(FocusEvent e) {
        }
    });





    TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
    jca.setEditable(true);
    comboboxEditor cbe = new comboboxEditor(jca);
    colCombo.setCellEditor(cbe);


    TableColumn colAutre = jTable1.getColumnModel().getColumn(1);
    TableColumn colAutre2 = jTable1.getColumnModel().getColumn(2);
    TableColumn colAutre3 = jTable1.getColumnModel().getColumn(3);
    textCellEditor dce = new textCellEditor(new JTextField());

    colAutre.setCellEditor(dce);
    colAutre2.setCellEditor(dce);
    colAutre3.setCellEditor(dce);



    frame.getContentPane().add(scrollPane);
    frame.pack();
    frame.setVisible(true);

}







class comboboxEditor extends AbstractCellEditor implements TableCellEditor{

    JComboBox comboBox;



    public comboboxEditor(JComboBox jcb) {

        comboBox = jcb;
    }


    public Object getCellEditorValue() {
        return comboBox.getSelectedItem();
    }


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

        comboBox.setSelectedItem(value);
        return comboBox;
    }

    public boolean stopCellEditing() {
        fireEditingStopped();
        return true;

    }


}

class textCellEditor extends AbstractCellEditor implements TableCellEditor{
    JTextField jtextfield;

    public textCellEditor(JTextField jtf) {
        jtextfield = jtf;
    }


    public Object getCellEditorValue() {
        return jtextfield.getText();
    }


    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        if (isSelected) {
            // cell (and perhaps other cells) are selected
        }
        if (value== null)
        {
            value="";
        }
        value = value.toString();
        if (value instanceof Integer) {
            value = value.toString();
        }
        jtextfield.setText((String) value);

        // Return the configured component
        return jtextfield;
    }

    public boolean stopCellEditing() {
        fireEditingStopped();
        return true;

    }

}



}

感谢您的帮助。

答案 1 :(得分:0)

不要在组合框上使用ActionListener。 " popup"当您单击单元格时,编辑器将显示它。

  

我的第一个问题是,当我们实现抽象表模型而不是使用DefaultTableModel时,我不明白为什么教程中的代码有效。

编辑由TableModel的isCellEditable(...)方法控制。当您单击可编辑的单元格时,JTable将使用适当的编辑器。如果编辑器是组合框,则单击单元格时将显示弹出窗口。

  

找到问题:在评论语句时jcb.setEditable(true);如果我在comboxcell上单击它就会打开单元格。但我不知道为什么它会更好用

当您单击一个单元格时,我相信MouseEvent会转发到编辑器(即组合框)。由于组合框是可编辑的,因此MouseEvent将转到文本字段,因此焦点仍然是文本字段,并且不显示弹出窗口。尝试使用普通的组合框,而不是在JTable中显示,所以看到相同的行为。

答案 2 :(得分:-1)

我不知道为什么使用AbstractTableModel的代码有效(因为我看不到它)。但我可以帮助你让你的榜样有效。

    jcb.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            System.out.println("test");
            final JComboBox j= (JComboBox)evt.getSource();
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    if (j.isDisplayable()) j.setPopupVisible(true);
                }
            });

        }});