JTable cell returning null

怎甘沉沦 提交于 2020-01-03 02:57:10

问题


I am using JTextField inside JTable cells; I use a TabelModel which has the dynamic data of the JTable. Now, when I click a button, I am reading a cell value. Problem is the cell which has the present focus doesn't return the updated value. For example, consider this program:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class MyTable extends JFrame {

    DefaultTableModel tmodel = new DefaultTableModel(new Object[][]{
            {"some"}, {"any"}, {"even"}, {"text"}, {"and"}, {""}},
        new Object[]{"Column 1"});

    public MyTable() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTable table = new JTable(tmodel);
        table.setDefaultRenderer(Object.class, new MyRenderer());
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        getContentPane().setLayout(new GridLayout(2, 2));
        JButton jb = new JButton("click me"); //button to display last cell data
        jb.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                JOptionPane.showMessageDialog(
                    null, table.getModel().getValueAt(5, 0));
            }
        });
        getContentPane().add(jb);
    }

    public static void main(String arg[]) {
        new MyTable().setVisible(true);
    }
}

class MyRenderer implements TableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
        JTextField editor = new JTextField();
        if (value != null) {
            editor.setText(value.toString());
        }
        return editor;
    }
}

Here I am leaving the last field empty. When I read it by

table.getModel().getValueAt(5, 0)

I get null. Now I change the value at 5,0, and again click the button, but now again I get null. Now surprisingly, I edit some other cell, again click button; now I get the correct data at cell 5,0! Why is this? Is this a bug? I tried several possibilities!


回答1:


Incorporating @kleopatra's suggestion and @mKorble's helpful revisions, here are a few additional ideas based on your example. Note in particular the use of setDefaultButton() and Action in conjunction with Key Bindings.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;

/** @see https://stackoverflow.com/q/9874664/230513 */
public class MyTable extends JFrame {

    private static final String show = "Show";
    private DefaultTableModel tmodel = new DefaultTableModel(
        new Object[][]{
            {"edit"}, {"any"}, {"cell"}, {"text"}, {"and"}, {"edit me"}},
        new Object[]{
            "Column 1"});
    private JTable table = new JTable(tmodel);
    private Action showAction = new ShowAction(show);
    private JButton jb = new JButton(showAction);

    public MyTable() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);
        table.putClientProperty("terminateEditOnFocusLost", true);
        KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        table.getInputMap(JTable.WHEN_FOCUSED).put(enter, show);
        table.getActionMap().put(show, showAction);
        add(new JScrollPane(table), BorderLayout.CENTER);
        table.setPreferredScrollableViewportSize(new Dimension(400, 200));
        JPanel panel = new JPanel();
        panel.add(jb);
        getRootPane().setDefaultButton(jb);
        add(panel, BorderLayout.SOUTH);
        pack();
    }

    private class ShowAction extends AbstractAction {

        private ShowAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (table.isEditing()) {
                table.getCellEditor().stopCellEditing();
            }
            int row = table.getSelectedRow();
            if (row > -1) {
                JOptionPane.showMessageDialog(
                    MyTable.this, table.getModel().getValueAt(row, 0));
            }
        }
    }

    public static void main(String arg[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MyTable().setVisible(true);
            }
        });
    }
}



回答2:


There are several points to consider within your example:

First you should have a look in Java - Tutorials to learn about the concept of Renderer and Editor within JTables, because you kinda mix things up here. Within your Renderer you use a JTextField which doesn't make sense, because this object is just used to present the data within your tableModel. Normally a JLabel is used for presenting, since you wont ever edit a value within a Renderer.

Moreover your example (eventhough I haven't tried it yet) should work, since a JTable already has a DefaultEditor. Maybe you just forgot to commit the value with pressing enter before you clicked the button to check which value is in?

I really can just recommend for reading this tutorial and search for some examples on how this is handled normally. You should find a lot of working examples.




回答3:


I think that every type of Arrays start with 0 (zero), then output to the JoptionPane is correct (return empty String), little bit modified your original code, added most important Swing rulles

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

public class MyTable extends JFrame {

    private static final long serialVersionUID = 1L;
    private DefaultTableModel tmodel = new DefaultTableModel(new Object[][]{
                {"some"}, {"any"}, {"even"}, {"text"}, {"and"}, {"xxxxxxxxxxxxxxxxxxxxxxx"}},
            new Object[]{"Column 1"});

    public MyTable() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTable table = new JTable(tmodel);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        add(new JScrollPane(table), BorderLayout.CENTER);
        JButton jb = new JButton("click me"); //button to display last cell data
        jb.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                JOptionPane.showMessageDialog(null, table.getModel().getValueAt(5, 0));
            }
        });
        add(jb, BorderLayout.SOUTH);
        pack();
        setVisible(true);
    }

    public static void main(String arg[]) {
        EventQueue.invokeLater(new Runnable() {//added initial thread

            @Override
            public void run() {
                MyTable myTable = new MyTable();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/9874664/jtable-cell-returning-null

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!