简体   繁体   English

Jtable Jcombobox和单元格编辑

[英]Jtable jcombobox and cell editing

I would like to have a jtable with 4 columns. 我想有一个4列的jtable。 One column must be a combobox. 一列必须是组合框。 Other columns are strings. 其他列是字符串。

When i click one time on a cell, i would like the cell become editable with blinking caret/cursor.Also, if i click on the combobox i would like the combox set popup visble. 当我在一个单元格上单击一次时,我希望该单元格可以变为闪烁的插入符号/光标。此外,如果我单击组合框,我希望combox设置弹出框可见。

I have read and tested tutorial "How to Use Tables", and if i make just one click on combobox in the cell, it opens. 我已经阅读并测试了教程“如何使用表格”,并且如果我只单击单元格中的组合框,它就会打开。 My first problem is that i don't understand why the code in the tutorial works when we implement abstract table model and not working DefaultTableModel. 我的第一个问题是,当我们实现抽象表模型而不使用DefaultTableModel时,我不理解本教程中的代码为何起作用。

My code is : 我的代码是:

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);

    }

The source with abstract model is here : http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java 带有抽象模型的源代码在这里: http : //docs.oracle.com/javase/tutorial/displayCode.html?code=http : //docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/ src / components / TableRenderDemo.java

Just find the problem : When commenting the statement jcb.setEditable(true); 只需查找问题即可:在评论语句jcb.setEditable(true);时 , if i do a single click on the comboxcell it opens the cell. ,如果我在comboxcell上单击,将打开该单元格。 But i don't know why it works better. 但是我不知道为什么它会更好。 Also, i would like the combox editable. 另外,我希望combox可编辑。

How i can have the same behavior for others cells. 我如何对其他单元格具有相同的行为。

Hello again, i have updated the code in order to have - cells become editable if i click one time on the cell by overriding the method - combobox become editable if i click one time on the cell by overriding the method 再次问好,我已经更新了代码,以使-如果我通过覆盖方法在单元格上单击一次,则单元格变为可编辑-如果我通过覆盖方法在单元格上单击一次,则组合框变为可编辑

I put my new code here, it may help other : 我把我的新代码放在这里,它可能对其他有帮助:

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;

        }


    }










}
  • When i click on the combobox i would like to highlight the text by selecting it. 当我单击组合框时,我想通过选择突出显示文本。 I don't remember how to get the textfield from the jcombobox in order to use selectAll() method or something like that. 我不记得如何从jcombobox获取文本字段,以使用selectAll()方法或类似方法。

I have find a solution for that : 我找到了一个解决方案:

            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.");

            }

Thanks for your help. 谢谢你的帮助。

I have finally find how to solve all my problems. 我终于找到了解决所有问题的方法。 I post all the code. 我发布了所有代码。 I hope it will help others. 我希望它会帮助其他人。 If you find better way to adress the problem, i'm open. 如果您找到解决问题的更好方法,我会开放的。

It remains two strange thing but it work as i want, so if somenone as an idea : 它仍然是两件奇怪的事情,但是它可以按我的意愿工作,所以如果没有人提出这样的想法:

  • If i move the code 如果我移动代码

      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); } 

in keyReleased instead of keyPressed, it doesn't work. 在keyReleased中而不是keyPressed中,它不起作用。

  • When i press enter on basic cell text, the program go to next cell alone. 当我在基本单元格文本上按Enter键时,程序将单独转到下一个单元格。 I don't understand how it goes alone to next cell on enter key. 我不知道如何单独进入Enter键的下一个单元格。

All the code here : 这里的所有代码:

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;

    }

}



}

Thanks for your help. 谢谢你的帮助。

Don't use an ActionListener on the combo box. 不要在组合框上使用ActionListener。 The "popup" will be displayed by the editor when you click on the cell. 单击单元格时,编辑器将显示“弹出窗口”。

My first problem is that i don't understand why the code in the tutorial works when we implement abstract table model and not working DefaultTableModel. 我的第一个问题是,当我们实现抽象表模型而不使用DefaultTableModel时,我不理解本教程中的代码为何起作用。

Editing is controlled by the isCellEditable(...) method of the TableModel. 编辑由TableModel的isCellEditable(...)方法控制。 When you click on a cell that is editable the JTable will use the appropriate editor. 当单击可编辑的单元格时,JTable将使用适当的编辑器。 If the editor is a combo box, then the popup will be displayed when the cell is clicked. 如果编辑器是一个组合框,则单击该单元格时将显示弹出窗口。

Just find the problem : When commenting the statement jcb.setEditable(true); 只需查找问题即可:在评论语句jcb.setEditable(true);时 , if i do a single click on the comboxcell it opens the cell. ,如果我在comboxcell上单击,将打开该单元格。 But i don't know why it works better 但我不知道为什么它会更好

When you click on a cell I believe the MouseEvent is forwarded to the editor (ie the combo box). 当您单击一个单元格时,我相信MouseEvent将转发到编辑器(即组合框)。 Since the combo box is editable the MouseEvent goes to the text field, so focus remains of the text field and the popup is not displayed. 由于组合框是可编辑的,因此MouseEvent转到文本字段,因此焦点仍保留在文本字段中,并且不显示弹出窗口。 Try this with a normal combo box, not displayed in a JTable so see the same behaviour. 使用普通的组合框(不显示在JTable中)尝试此操作,因此请参见相同的行为。

I don't know why your code with AbstractTableModel works (because I cannot see it). 我不知道您的AbstractTableModel代码为何有效(因为我看不到)。 But I can help you to make your example working. 但我可以帮助您使您的榜样行之有效。

    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);
                }
            });

        }});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM