JTable TableCellRenderer不适用于新行

时间:2013-08-16 20:22:38

标签: java swing jtable

我正在尝试使用以下教程代码将按钮添加到JTable的最后一列:

http://www.java2s.com/Code/Java/Swing-Components/ButtonTableExample.htm

它适用于具有“静态”数据的表,但是当我尝试动态添加新行时,我无法使其工作。 有办法吗?这是代码:

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


public class TestTableButton extends JFrame
{
    PlayersTableModel tableModel = new PlayersTableModel();
    JTable table = new JTable(tableModel);

    public TestTableButton()
    {
        ButtonColumn bc = new ButtonColumn(table, new AbstractAction(){

            public void actionPerformed(ActionEvent e){ 
                JTable table = (JTable)e.getSource();
                int modelRow = Integer.valueOf(e.getActionCommand());
                System.out.println("you clicked row: " + modelRow);
            }
        }, 2);

        fillTable();

        getContentPane().setLayout(new GridLayout(2, 1, 0, 0));
        getContentPane().add(table);
        JButton addPlayer = new JButton("Add row");
        addPlayer.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent event)
            {
                fillTable();
            }
        });

        getContentPane().add(addPlayer);
    }

    // add some items
    private void fillTable()
    {
        tableModel.players.add(new Player("John Doe", 75.50f));
        tableModel.fireTableStructureChanged();
    }

    public static void main (String[] args)
    {

        SwingUtilities.invokeLater(new Runnable() {

            public void run(){

                final JFrame frame = new TestTableButton();
                frame.pack();
                frame.setBounds(200, 300, 500, 500);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

/****** Model ********/
class Player
{
    String nickname;
    float winRate;

    public Player(String nick, float rt)
    {nickname = nick; winRate = rt;}
}

/****** Table model ******/
class PlayersTableModel extends AbstractTableModel
{
    protected ArrayList<Player> players = new ArrayList<Player>();

  private String[] getColNames()
  {
    return new String[]{"Player", "% Wins", "Challenge"};
  }

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

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

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

  public Class getColumnClass(int c) {
    if (c == 2)
       return ButtonColumn.class;

    return getValueAt(0, c).getClass();
  }

  public Object getValueAt(int row, int col) {

   Player player = players.get(row);
   Object val = null;

   if (col == 0)
     val = player.nickname;
   else if(col == 1)
     val = new Float(player.winRate);
   else 
     val = "Accept";

   return val;
 }

 public boolean isCellEditable(int row, int col) {
   return col == 2;
 }

}

这是自定义渲染器

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

public class ButtonColumn extends AbstractCellEditor
    implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener
{
    private JTable table;
    private Action action;
    private int mnemonic;
    private Border originalBorder;
    private Border focusBorder;

    private JButton renderButton;
    private JButton editButton;
    private Object editorValue;
    private boolean isButtonColumnEditor;

    /**
     *  Create the ButtonColumn to be used as a renderer and editor. The
     *  renderer and editor will automatically be installed on the TableColumn
     *  of the specified column.
     *
     *  @param table the table containing the button renderer/editor
     *  @param action the Action to be invoked when the button is invoked
     *  @param column the column to which the button renderer/editor is added
     */
    public ButtonColumn(JTable table, Action action, int column)
    {
        this.table = table;
        this.action = action;

        renderButton = new JButton();

        editButton = new JButton();
        editButton.setFocusPainted( false );
        editButton.addActionListener( this );
        originalBorder = editButton.getBorder();
        setFocusBorder( new LineBorder(Color.BLUE) );

        TableColumnModel columnModel = table.getColumnModel();
        columnModel.getColumn(column).setCellRenderer( this );
        columnModel.getColumn(column).setCellEditor( this );
        table.addMouseListener( this );
    }


    /**
     *  Get foreground color of the button when the cell has focus
     *
     *  @return the foreground color
     */
    public Border getFocusBorder()
    {
        return focusBorder;
    }

    /**
     *  The foreground color of the button when the cell has focus
     *
     *  @param focusBorder the foreground color
     */
    public void setFocusBorder(Border focusBorder)
    {
        this.focusBorder = focusBorder;
        editButton.setBorder( focusBorder );
    }

    public int getMnemonic()
    {
        return mnemonic;
    }

    /**
     *  The mnemonic to activate the button when the cell has focus
     *
     *  @param mnemonic the mnemonic
     */
    public void setMnemonic(int mnemonic)
    {
        this.mnemonic = mnemonic;
        renderButton.setMnemonic(mnemonic);
        editButton.setMnemonic(mnemonic);
    }

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

        System.out.println("value");

        if (value == null)
        {
            editButton.setText( "" );
            editButton.setIcon( null );
        }
        else if (value instanceof Icon)
        {
            editButton.setText( "" );
            editButton.setIcon( (Icon)value );
        }
        else
        {
            editButton.setText( value.toString() );
            editButton.setIcon( null );
        }

        this.editorValue = value;
        return editButton;
    }

    @Override
    public Object getCellEditorValue()
    {
        return editorValue;
    }

//
//  Implement TableCellRenderer interface
//
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        if (isSelected)
        {
            renderButton.setForeground(table.getSelectionForeground());
            renderButton.setBackground(table.getSelectionBackground());
        }
        else
        {
            renderButton.setForeground(table.getForeground());
            renderButton.setBackground(UIManager.getColor("Button.background"));
        }

        if (hasFocus)
        {
            renderButton.setBorder( focusBorder );
        }
        else
        {
            renderButton.setBorder( originalBorder );
        }

//      renderButton.setText( (value == null) ? "" : value.toString() );
        if (value == null)
        {
            renderButton.setText( "" );
            renderButton.setIcon( null );
        }
        else if (value instanceof Icon)
        {
            renderButton.setText( "" );
            renderButton.setIcon( (Icon)value );
        }
        else
        {
            renderButton.setText( value.toString() );
            renderButton.setIcon( null );
        }

        return renderButton;
    }

//
//  Implement ActionListener interface
//
    /*
     *  The button has been pressed. Stop editing and invoke the custom Action
     */
    public void actionPerformed(ActionEvent e)
    {
        int row = table.convertRowIndexToModel( table.getEditingRow() );
        fireEditingStopped();

        //  Invoke the Action

        ActionEvent event = new ActionEvent(
            table,
            ActionEvent.ACTION_PERFORMED,
            "" + row);
        action.actionPerformed(event);
    }

//
//  Implement MouseListener interface
//
    /*
     *  When the mouse is pressed the editor is invoked. If you then then drag
     *  the mouse to another cell before releasing it, the editor is still
     *  active. Make sure editing is stopped when the mouse is released.
     */
    public void mousePressed(MouseEvent e)
    {
        if (table.isEditing()
        &&  table.getCellEditor() == this)
            isButtonColumnEditor = true;
    }

    public void mouseReleased(MouseEvent e)
    {
        if (isButtonColumnEditor
        &&  table.isEditing())
            table.getCellEditor().stopCellEditing();

        isButtonColumnEditor = false;
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

1 个答案:

答案 0 :(得分:1)

正如评论中指出的,我正在解雇错误的事件。

/* move this to the model */
private void fillTable()
{
    tableModel.players.add(new Player("John Doe", 75.50f));
    int row = tableModel.players.size() - 1;
    tableModel.fireTableRowsInserted(n, n);
}