【问题标题】:Adding JCombobox in Jtable and Getting that Row and Column in Swing java在 Jtable 中添加 JCombobox 并在 Swing java 中获取该行和列
【发布时间】:2014-06-18 18:32:43
【问题描述】:

我有一个 Jtable,我在其中添加了这样的 JComobox。

TableColumn sportColumn = jTable1.getColumnModel().getColumn(2);
        comboBox = new JComboBox();
        comboBox.addItem("Snowboarding");
        comboBox.addItem("Rowing");
        comboBox.addItem("Chasing toddlers");
        comboBox.addItem("Speed reading");
        comboBox.addItem("Teaching high school");
        comboBox.addItem("None");
        sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

我已经像这样添加了一个 jtable 的鼠标事件。

private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {                                     
        // TODO add your handling code here:
        try {
            int row = jTable1.rowAtPoint(evt.getPoint());
            int col = jTable1.columnAtPoint(evt.getPoint());

            System.out.println("Row" + row + "Column" + col);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

我正在正确输出行和列。

但是当我单击添加 Jcombobox 的单元格时,它并没有放弃该行和列。我仍然在组合框单击事件中调用了表的 clickevent,但它给出了所有时间行 0 甚至列 0 屏幕截图。

那么我该如何解决它,以便我可以拥有该行和列?

【问题讨论】:

  • 那么你为什么要尝试获取列/行信息?
  • @MadProgrammer M 试图获取该列/行,但我得到的是我没有添加组合框的地方。但是当我点击组合框时,它没有给出。那
  • 当 getTableCellEditorComponent 被调用时,组合框会被告知它正在编辑的单元格。请记住,鼠标点击与它们所在的组件相关
  • 当组合框可见时,表格无法接收鼠标事件,因为组合框阻止了它们
  • 好的,所以你有两个选择。将TableModelListener 添加到表并监视表模型的更改,或将CellEditorListener 添加到组合框单元格编辑器并监视editingStopped 事件。这可能更省钱,因为用户可能会在完成单元格编辑之前改变主意...

标签: java swing jtable jcombobox tablecelleditor


【解决方案1】:

在我看来,您有三个基本选择...

你可以...

CellEditorListener 附加到DefaultCellEditor 并监视editingStopped 事件...

editor.addCellEditorListener(new CellEditorListener() {
    @Override
    public void editingStopped(ChangeEvent e) {
        System.out.println("Editing stopped");
        TableCellEditor editor = (TableCellEditor) e.getSource();
        Object value = editor.getCellEditorValue();
        System.out.println("Selected value = " + value);
    }

    @Override
    public void editingCanceled(ChangeEvent e) {
    }
});

问题在于,实际上无法确定已编辑的单元格。即使引用了JTable,当您收到此事件时,表格已不再处于编辑模式...所以您只知道编辑器的值...

你可以...

TableModelListener 附加到TableModel...

model.addTableModelListener(new TableModelListener() {
    @Override
    public void tableChanged(TableModelEvent e) {
        int type = e.getType();
        switch (type) {
            case TableModelEvent.UPDATE:
                if (e.getFirstRow() - e.getLastRow() == 0) {
                    TableModel model = (TableModel) e.getSource();
                    int row = e.getFirstRow();
                    int col = e.getColumn();
                    System.out.println("Update " + row + "x" + col + " = " + model.getValueAt(row, col));
                }
                break;
        }
    }
});

这将让您知道单元格的值何时发生变化(以及许多其他事情,但这是我们感兴趣的),它不会告诉您什么是它发生变化的原因。

这种方法很好,因为它提供了您需要知道的所有信息,以便找到值和单元格。

你可以...

只需覆盖TableModelsetValueAt 方法并提供您自己的某种通知...

虽然这有点重复 TableModelListener 的功能,但您可以设计事件信息,以便它提供更多相关信息,因为 TableModelEvent 涵盖了很多用户案例...

示例

以下是采用TableRenderDemo 并修改以演示前两个概念的示例

import java.awt.BorderLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;

/**
 * TableRenderDemo is just like TableDemo, except that it explicitly initializes
 * column sizes and it uses a combo box as an editor for the Sport column.
 */
public class TableRenderDemo extends JPanel {

    public TableRenderDemo() {
        super(new BorderLayout());

        JTable table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);

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

        //Set up column sizes.
        initColumnSizes(table);

        //Fiddle with the Sport column's cell editors/renderers.
        setUpSportColumn(table, table.getColumnModel().getColumn(2));

        //Add the scroll pane to this panel.
        add(scrollPane);
    }

    /*
     * This method picks good column sizes.
     * If all column heads are wider than the column's cells'
     * contents, then you can just use column.sizeWidthToFit().
     */
    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel) table.getModel();
        model.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                int type = e.getType();
                switch (type) {
                    case TableModelEvent.UPDATE:
                        if (e.getFirstRow() - e.getLastRow() == 0) {
                            TableModel model = (TableModel) e.getSource();
                            int row = e.getFirstRow();
                            int col = e.getColumn();
                            System.out.println("Update " + row + "x" + col + " = " + model.getValueAt(row, col));
                        }
                        break;
                }
            }
        });
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer
                        = table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < 5; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                            null, column.getHeaderValue(),
                            false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                            getTableCellRendererComponent(
                                            table, longValues[i],
                                            false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    public void setUpSportColumn(final JTable table,
                    TableColumn sportColumn) {
        //Set up the editor for the sport cells.
        JComboBox comboBox = new JComboBox();
        comboBox.addItem("Snowboarding");
        comboBox.addItem("Rowing");
        comboBox.addItem("Knitting");
        comboBox.addItem("Speed reading");
        comboBox.addItem("Pool");
        comboBox.addItem("None of the above");
        TableCellEditor editor = new DefaultCellEditor(comboBox);
        editor.addCellEditorListener(new CellEditorListener() {

            @Override
            public void editingStopped(ChangeEvent e) {
                System.out.println("Editing stopped");
                TableCellEditor editor = (TableCellEditor) e.getSource();
                Object value = editor.getCellEditorValue();
                System.out.println("Selected value = " + value);
            }

            @Override
            public void editingCanceled(ChangeEvent e) {
            }
        });
        sportColumn.setCellEditor(editor);

        //Set up tool tips for the sport cells.
        DefaultTableCellRenderer renderer
                        = new DefaultTableCellRenderer();
        renderer.setToolTipText("Click for combo box");
        sportColumn.setCellRenderer(renderer);
    }

    class MyTableModel extends AbstractTableModel {

        private String[] columnNames = {"First Name",
            "Last Name",
            "Sport",
            "# of Years",
            "Vegetarian"};
        private Object[][] data = {
            {"Kathy", "Smith",
                "Snowboarding", new Integer(5), new Boolean(false)},
            {"John", "Doe",
                "Rowing", new Integer(3), new Boolean(true)},
            {"Sue", "Black",
                "Knitting", new Integer(2), new Boolean(false)},
            {"Jane", "White",
                "Speed reading", new Integer(20), new Boolean(true)},
            {"Joe", "Brown",
                "Pool", new Integer(10), new Boolean(false)}
        };

        public final Object[] longValues = {"Jane", "Kathy",
            "None of the above",
            new Integer(20), Boolean.TRUE};

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return data.length;
        }

        @Override
        public String getColumnName(int col) {
            return columnNames[col];
        }

        @Override
        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        /*
         * JTable uses this method to determine the default renderer/
         * editor for each cell.  If we didn't implement this method,
         * then the last column would contain text ("true"/"false"),
         * rather than a check box.
         */
        @Override
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        /*
         * Don't need to implement this method unless your table's
         * editable.
         */
        @Override
        public boolean isCellEditable(int row, int col) {
            //Note that the data/cell address is constant,
            //no matter where the cell appears onscreen.
            if (col < 2) {
                return false;
            } else {
                return true;
            }
        }

        /*
         * Don't need to implement this method unless your table's
         * data can change.
         */
        @Override
        public void setValueAt(Object value, int row, int col) {
            data[row][col] = value;
            fireTableCellUpdated(row, col);
        }
    }

    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TableRenderDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TableRenderDemo newContentPane = new TableRenderDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

【讨论】:

  • 雅完美的例子@MadProgrammer。
  • @Krishna 费了点力气,但我们还是把它拖到一边,一边踢一边尖叫;)
  • 完美答案。救生员。
【解决方案2】:

使用下面的代码,您可以获得所选行和列的值。

table.addMouseListener(new MouseAdapter() 
      {
        @Override
        public void mouseClicked(MouseEvent e) 
        {
            try {
                int rowss = table.rowAtPoint(e.getPoint());
                System.out.println("rowss" + rowss);
                printDebugData(table);
            } catch (ParseException ex) {
                Logger.getLogger(ShowEmployee.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        private void printDebugData(JTable jTable1) throws ParseException
        {
              String selectedData = null;

            int numRows = jTable1.getRowCount();
            int numCols = jTable1.getColumnCount();
            int[] selectedRow = jTable1.getSelectedRows();
            int[] selectedColumns = jTable1.getSelectedColumns();
            javax.swing.table.TableModel model = jTable1.getModel();
            for (int i = 0; i < selectedRow.length; i++)
            {
                for (int j = 0; j < selectedColumns.length; j++) 
                {
                    selectedData = (String) jTable1.getValueAt(selectedRow[i], selectedColumns[j]);
                }
                System.out.println("Selected: " + selectedData);
            }
        }
        });

  }

用你的 jtbale 与 mouselistner 核对。

更新: 在调用 printdebugdata() 之前添加这两行。

  int rowss = table.rowAtPoint(e.getPoint());
  System.out.println("rowss" + rowss);

我得到了行号检查我的输出。

输出:

rowss0
Selected: Smith
rowss0
Selected: Smith
rowss1
Selected: Snowboarding
rowss1
Selected: Rowing
rowss1
Selected: Rowing
rowss1
Selected: Rowing
rowss2
Selected: Snowboarding
rowss2
Selected: Snowboarding
rowss2
Selected: Snowboarding
rowss2
Selected: Snowboarding

谢谢..

【讨论】:

  • M 正在尝试。我会让你知道的。
  • m 没有得到行号和列号
  • 对不起,兄弟在我使用 Conbobox 事件时无法正常工作
  • @Krishna:我的最新更新没用。无需使用组合框事件。
  • @krishna:我使用相同的代码得到了输出。我的控制台也在那里..然后检查你的身边..哪里出错了?
【解决方案3】:

好吧,这对我来说有点奇怪,但我确实解决了它,但我认为这不是正确的答案,但我解决了它。我打了电话。组合按钮 Action Performed 事件并在其中调用了 jtable 的鼠标单击。使用 null 而不是事件。看看吧。

 comboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                jTable1MouseClicked(null);
            }
        });


 private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {                                     
        // TODO add your handling code here:
        try {
            //evt.getPoint();
            System.out.println("row" + jTable1.getSelectedRow());
            System.out.println("col" + jTable1.getSelectedColumn());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }                                    

可能不是正确的方法,但我解决了这个问题。它的工作。

最好的解决办法是

jTable1.getModel().addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                System.out.println("Changed Column"+e.getColumn());
                System.out.println("first row"+e.getFirstRow());
            }
        });

    }

【讨论】:

  • 这将导致null 指针异常,因为您要使用MouseEvent 信息...只是说...
  • @MadProgrammer 但我没有根据我的要求得到异常。雅它给我计数。我知道你是对的,它不是正确的解决方案。但请给我推荐另一个好东西。
  • jTable1MouseClicked方法里做evt.getPoint()怎么可能不给你NullPointerException
  • @MadProgrammer 兄弟我没有调用那个方法。看我已经更新了那个方法。
  • @MadProgrammer 和你是对的,如果我们使用 e.getPoint(); 它会给出空指针; :)
猜你喜欢
  • 1970-01-01
  • 2011-09-09
  • 2014-09-25
  • 2023-03-30
  • 2015-09-11
  • 1970-01-01
  • 2010-12-01
  • 2011-10-19
  • 1970-01-01
相关资源
最近更新 更多