Java swing jtable setvalueAt doesn't work

2019-09-06 19:21发布

问题:

i searched in differet questions from others. But i didn't succeed. I want to make my table editable. But i dont know how, to call "setValueAt()".

I have the following files:

MovieManager.java

import java.util.*;

public class MovieManager 
{
    private static List<Movie> movieList = new ArrayList<Movie>(); 

    public static void main(String args[])
    {
        final Director david = new Director("David", "Finch", Gender.MALE);
        final Movie film1 = new Movie("Fightclub", 140, "Amerika", "Best Movie ever!", david);
        final Movie film2 = new Movie("Panic Room", 115, "Amerika", "Good Movie", david);
        final Movie film3 = new Movie("Seven", 120, "Amerika", "Headless", david);

        movieList.add(film1);
        movieList.add(film2);
        movieList.add(film3);

        // start GUI
        new MovieUI();
    }

    public static List<Movie> getMovieList() 
    {
            return movieList;
    }

    public static void setMovieList(List<Movie> movieList) 
    {
        MovieManager.movieList = movieList;
    }
}

MovieUI.java

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MovieUI extends JPanel 
{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public MovieUI() 
    {
        //Create and set up the window.
        final JFrame frame = new JFrame("Movie Manager");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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

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

Table.java

import javax.swing.JPanel;
import javax.swing.JTable;
import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.table.JTableHeader;
import javax.swing.table.TableRowSorter;

public class Table extends JPanel
{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public Table() 
    {
        super(new GridLayout(1,0));
        final MovieTableModel model = new MovieTableModel();
        final JTable table = new JTable(model);

        final TableRowSorter<MovieTableModel> sorter = new TableRowSorter<MovieTableModel>();
        table.setRowSorter(sorter);
        sorter.setModel(model); 

        final JTableHeader header = table.getTableHeader();
        setLayout(new BorderLayout());
        add(header, BorderLayout.PAGE_START);
        add(table, BorderLayout.CENTER);      
     }
}

and MovieTableModel.java

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

class MovieTableModel extends AbstractTableModel 
{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private final List<String[]> daten = new ArrayList<String[]>();
    private final List<Movie> datenMov = new ArrayList<Movie>();
    private final String[] columnNames = {"Id", "Name", "Time", "Language", "Description", "Place"};

    public MovieTableModel()
    {
        for (Movie movie: MovieManager.getMovieList()) 
        { 
            String[] list = {String.valueOf(movie.getNumber()), movie.getTitle(), String.valueOf(movie.getTime()), "DE", movie.getDescription(), movie.getPlace()};
            datenMov.add(movie);
            daten.add(list);
        }
    }

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

    public int getRowCount() 
    {
        return daten.size();
    }

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

    public Object getValueAt(int row, int col) 
    {
        return daten.get(row)[col];
    }

    public boolean isCellEditable(int row, int col) 
    {
        if (col < 1) 
        {
            return false;
        } 
        else 
        {
            return true;
        }
    }

    public void setValueAt(String value, int row, int col) 
    {
        System.out.println("Ich werde aufgerufen");
        String[] list = daten.get(row);
        list[col] = value;
        daten.set(row, list);
        System.out.println(daten.get(row)[col]);

        List<Movie> movieliste = MovieManager.getMovieList();

        Movie mov = (Movie) movieliste.get(row);
        switch( col )
        {
            case 1: 
                mov.setTitle(value);
                break;
            case 2: 
                int foo = Integer.parseInt(value);
                mov.setTime(foo);
                break;
            case 4: 
                mov.setDescription(value);
                break;
            case 5: 
                mov.setPlace(value);
                break;
        }

        movieliste.set(row, mov);
        MovieManager.setMovieList(movieliste);
    }

}

回答1:

You TableModel is too complex. All you need to do is store a List of Movies. Then you getValueAt() and setValueAt() method should access the List.

Your constructor should simply be:

public MovieTableModel(List movies)
{
    datenMov = movies;
}

The getValueAt() should be something like:

public Object getValueAt(int row, int column)
{
    Movie movie = datenMov.get(row);

    switch(column)
    {
        case 0: return movie.getNumber();
        case 1: return movie.getTitle();
        ...
        default: return null;
    }
}

and the setValueAt() method something like:

@Override
public void setValueAt(Object value, int row, int column)
{
    Movie movie = get(row);

    switch (column)
    {
        case 0: movie.setNumber((String)value); break;
        case 1: movie.setTitle((String)value); break;
        ...
    }
}

Edit:

Also, in the setValueAt() method you need to invoke:

fireTableCellUpdated(row, column);


回答2:

I encountered similar situation, and I finally solved it.

I found that, when we double click on a cell, it go to:

JTable.getDefaultEditor(Class<?> columnClass) function.

In my case, it go to the line :

return getDefaultEditor(columnClass.getSuperclass());

Since I returned int.class when overriding the getColumnClass() in my Table Model, so it returned null for the editor.

In short, the solution is,
Don't return any Primitive Data Types when overriding getColumnClass() in your table model !