JTable中定制JPanel的奇怪行为

时间:2015-12-01 08:46:37

标签: java jtable

我是JTable的新手。

我使用JPanel制作了自己的自定义渲染器和编辑器。但是,每当我尝试编辑CustomJPanel时,表格单元格都会变为空白。

第二件事是,底部的按钮用于显示第二行的控件(JPanel内的滑块和按钮)。但事实证明它显示了所有JPanel的控件。

我的完整代码如下:

CustomJTableTest.java

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class CustomJTableTest extends JPanel
{

  TableModel customRendererEditorTableModel = new TableModel();
  JTable table;

  public CustomJTableTest()
  {
    setLayout(new BorderLayout());

    table = new JTable(customRendererEditorTableModel);
    table.setRowSelectionAllowed(false);
    table.setRowHeight(300);
    table.getColumnModel().getColumn(1).setCellRenderer(new CustomJPanelRendererEditor());
    table.getColumnModel().getColumn(1).setCellEditor(new CustomJPanelRendererEditor());

    JScrollPane scrollPane = new JScrollPane(table);
    add(scrollPane);

    JButton showControl = new JButton("Show Second Row Controls");
    showControl.addActionListener(new ActionListener()
    {
      @Override
      public void actionPerformed(ActionEvent e)
      {
    TableCellRenderer tableCellRenderer = (CustomJPanelRendererEditor) table.getCellRenderer(1, 1);
    java.awt.Component component = table.prepareRenderer(tableCellRenderer, 1, 1);
    if (component instanceof CustomJPanel)
    {
      CustomJPanel customJPanel = (CustomJPanel) component;
      customJPanel.setControlsVisible(true);
    }
      }
    });
    add(new JScrollPane(showControl), BorderLayout.SOUTH);
  }

  private static void createAndShowGUI()
  {
    JFrame frame = new JFrame("Custom JPanel");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JComponent newContentPane = new CustomJTableTest();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    javax.swing.SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
    createAndShowGUI();
      }
    });
  }
}

CustomJPanel.java

import java.awt.*;
import javax.swing.*;
import java.awt.Color;

public class CustomJPanel extends JPanel
{
  JPanel colorPanel = new JPanel(new BorderLayout());
  JButton jButton = new JButton("Button inside CustomPanel");
  JSlider jSlider = new JSlider(JSlider.VERTICAL);

  public CustomJPanel()
  {
    setLayout(new BorderLayout());
    setSize(new Dimension(5, 300));
    setBackground(Color.BLACK);
    add(colorPanel, BorderLayout.CENTER);
    add(jButton, BorderLayout.SOUTH);
    add(jSlider, BorderLayout.EAST);

    jSlider.setVisible(false);
    jButton.setVisible(false);
  }

  public void setControlsVisible(boolean visible)
  {
    jSlider.setVisible(visible);
    jButton.setVisible(visible);

    repaint();
    revalidate();
  }
}

CustomerJPanelRendererEditor.java

import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class CustomJPanelRendererEditor extends AbstractCellEditor implements TableCellRenderer, TableCellEditor
  {
    CustomJPanel customJPanel = new CustomJPanel();

    @Override
    public java.awt.Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) 
    {
      return customJPanel;
    }

    @Override
    public java.awt.Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
    {
      return customJPanel;
    }

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

TableModel.java

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel
{

  private String[] columnNames =
  {
    "First Column",
    "Custom JPanel",
  };
  private Object[][] data =
  {
    {"Foo", new CustomJPanel()},
    {"Bar", new CustomJPanel()}
  };

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

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

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

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

  public Class getColumnClass(int c)
  {
    return getValueAt(0, c).getClass();
  }

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

  public void setValueAt(Object value, int row, int col)
  {
    data[row][col] = value;
    fireTableCellUpdated(row, col);
  }

}

任何人都知道出了什么问题?

谢谢。抱歉我的英文。

更新:

我很蠢。我改变了

TableCellRenderer tableCellRenderer = (CustomJPanelRendererEditor) table.getCellRenderer(1, 1);
java.awt.Component component = table.prepareRenderer(tableCellRenderer, 1, 1);

TableCellEditor tableCellEditor = (CustomJPanelRendererEditor) table.getCellEditor(1, 1);
java.awt.Component component = table.prepareEditor(tableCellEditor, 1, 1);
CustomJTableTest.java 中的

。滑块和按钮现在正在工作。见GIF。 现在我的问题是,当我点击该单元格时,CustomJPanel才会显示。如何仅为特定单元打开按钮和滑块的可见性?

谢谢。

1 个答案:

答案 0 :(得分:0)

不知怎的,我设法解决了它。感谢@Oliver Watkins的帮助。

作为我的修复的总结,我补充说 getTableCellRendererComponent() getTableCellEditorComponent()

rendererJPanel = (CustomJPanel) value;

完成代码:

<强> CustomJTableTest.java

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class CustomJTableTest extends JPanel
{

  TableModel customRendererEditorTableModel = new TableModel();
  JTable table;

  public CustomJTableTest()
  {
    setLayout(new BorderLayout());

    table = new JTable(customRendererEditorTableModel);
    table.setPreferredScrollableViewportSize(new Dimension(500, 600));
    table.setRowSelectionAllowed(false);
    table.setRowHeight(300);
    table.getColumn("Custom JPanel").setCellRenderer(new CustomJPanelRenderer());
    table.getColumn("Custom JPanel").setCellEditor(new CustomJPanelEditor());

    JScrollPane scrollPane = new JScrollPane(table);
    add(scrollPane);

    JButton showControl = new JButton("Show Controls");
    showControl.addActionListener(new ActionListener()
    {
      @Override
      public void actionPerformed(ActionEvent e)
      { 
    // row 2
    TableCellEditor tableCellEditor = table.getColumnModel().getColumn(1).getCellEditor();
    java.awt.Component component = table.prepareEditor(tableCellEditor, 1, 1);
    if (component instanceof CustomJPanel)
    {
      CustomJPanel customJPanel = (CustomJPanel) component;
      customJPanel.setControlsVisible(true);
    }

    // row 1
    java.awt.Component component2 = table.prepareEditor(tableCellEditor, 0, 1);
    if (component2 instanceof CustomJPanel)
    {
      CustomJPanel customJPanel = (CustomJPanel) component2;
      customJPanel.setControlsVisible(true);
    }

    customRendererEditorTableModel.fireTableDataChanged();
      }
    });
    add(new JScrollPane(showControl), BorderLayout.SOUTH);
  }

  private static void createAndShowGUI()
  {
    JFrame frame = new JFrame("Custom JPanel");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JComponent newContentPane = new CustomJTableTest();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    javax.swing.SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
    createAndShowGUI();
      }
    });
  }
}

<强> CustomJPanel.java

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;

public class CustomJPanel extends JPanel
{

  JPanel colorPanel = new JPanel(new BorderLayout());
  JButton jButton = new JButton("Change Color");
  JSlider jSlider = new JSlider(JSlider.VERTICAL);

  public CustomJPanel()
  {
    jButton.setOpaque(true);
    jButton.addActionListener(new ActionListener()
    {

      @Override
      public void actionPerformed(ActionEvent e)
      {
    Random randomGenerator = new Random();
    int randomInt = randomGenerator.nextInt(4);

    switch (randomInt)
    {
      case (0):
        colorPanel.setBackground(Color.BLUE);
        break;
      case (1):
        colorPanel.setBackground(Color.BLACK);
        break;
      case (2):
        colorPanel.setBackground(Color.CYAN);
        break;
      default:
        colorPanel.setBackground(Color.GREEN);
        break;
    }
      }
    });
    jSlider.setOpaque(true);
    setLayout(new BorderLayout());
    add(colorPanel, BorderLayout.CENTER);
    add(jButton, BorderLayout.SOUTH);
    add(jSlider, BorderLayout.EAST);

    jSlider.setVisible(false);
    jButton.setVisible(false);
  }

  public void setControlsVisible(boolean visible)
  {
    jSlider.setVisible(visible);
    jButton.setVisible(visible);
  }
}

<强> CustomerJPanelRenderer

import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class CustomJPanelRenderer implements TableCellRenderer
  {

    CustomJPanel rendererJPanel;

  public CustomJPanelRenderer()
  {
    rendererJPanel = new CustomJPanel();
  }


    @Override
    public java.awt.Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) 
    {
      rendererJPanel = (CustomJPanel) value;
      return rendererJPanel;
    }
  }

<强> CustomJPanelEditor.java

import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class CustomJPanelEditor extends AbstractCellEditor implements TableCellEditor
{
  CustomJPanel customJPanel;

  public CustomJPanelEditor()
  {
    customJPanel = new CustomJPanel();
  }

  @Override
  public java.awt.Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
  {
    customJPanel = (CustomJPanel) value;
    return customJPanel;
  }

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

<强> TableModel.java

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel
{

  private String[] columnNames =
  {
    "First Column",
    "Custom JPanel",
  };
  private Object[][] data =
  {
    {"Foo", new CustomJPanel()},
    {"Bar", new CustomJPanel()}
  };

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

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

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

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

  public Class getColumnClass(int c)
  {
    return getValueAt(0, c).getClass();
  }

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

  public void setValueAt(Object value, int row, int col)
  {
    data[row][col] = value;
    fireTableCellUpdated(row, col);
  }

}
相关问题