具有多种类型 JComponent (Swing) 的 JPanel 的 JTable
JTable for JPanel with multiple type JComponent (Swing)
这是一道很长的题,但需要所有代码(我想的是一道基础题,没有共同的组成部分)。
我需要构建一个 JTable,其中包含多个自定义类型 JPanel
的多个列(使用 JSlider
+ JComboBox
+ JTextField
)一栏。
我正在阅读:http://pekalicious.com/blog/custom-jpanel-cell-with-jbuttons-in-jtable/
在这个问题中,我将使用一个列,其中只有一个自定义 JPanel
,名称为 PanelSpinnerRadioButton
。
自定义面板:PanelSpinnerRadioButton.java
public class PanelSpinnerRadioButton extends JPanel {
private final JRadioButton jrbOption01= new JRadioButton("01");
private final JRadioButton jrbOption02 = new JRadioButton("12");
private final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel jpPanelSpinnerRadioButton = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
jpPanelSpinnerRadioButton.setLayout(new BoxLayout(jpPanelSpinnerRadioButton, BoxLayout.LINE_AXIS));
jpPanelSpinnerRadioButton.add(jrbOption01);
jpPanelSpinnerRadioButton.add(jrbOption02);
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(new JSeparator(JSeparator.VERTICAL));
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(jspnValues);
//Change States of RadioButtons (will be readOnly, ButtonGroup is not needed)
jrbOption02.setSelected(data.getOption());
jrbOption01.setSelected(!data.getOption());
//Change States of Spinner
((SpinnerNumberModel)jspnValues.getModel()).setValue(data.getFrom());
((SpinnerNumberModel)jspnValues.getModel()).setMaximum(data.getSize());
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelSpinnerRadioButton);
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getValue(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getMaximum()
);
}
}
这里是自定义JPanel之前的Image Result
自定义面板的数据类型:PanelSpinnerRadioButtonData.java
public class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() { return opt02; }
public Integer getFrom() { return from; }
public Integer getSize() { return size; }
}
现在编码来处理我的自定义 JPanel(带有内部 JComponents)
Table型号:PSRBTableModel.java
public class PSRBTableModel extends AbstractTableModel {
private final Object[][] data;
private final Object[] columns;
public PSRBTableModel(Object[][] data, Object[] columns) {
// super();
this.data = data;
this.columns = columns;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[rowIndex][columnIndex] instanceof PanelSpinnerRadioButton) {
return (PanelSpinnerRadioButton)data[rowIndex][columnIndex];
}
return data[rowIndex][columnIndex];
}
}
return null;
}
public int getColumnCount() {
return ((columns == null) ? 0: columns.length);
}
public int getRowCount() {
return ((data == null) ? 0: data.length);
}
public Class getColumnClass(int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
return data[0][columnIndex].getClass();
}
}
return null;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
//PanelSpinnerRadioButton Is not Editable
return false;
}
}
}
return true;
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public String getColumnName(int columnIndex) {
return (String)columns[columnIndex];
}
}
渲染器:PSRBTableCellRenderer.java
public class PSRBTableCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Object output = null;
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
return (Component)output;
}
}
和 EditorCell:PSRBTableCellEditor.java
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
protected Object output;
PSRBTableCellEditor() {
}
public Object getCellEditorValue() {
//Returns the value contained in the editor.
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
return null;
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//Sets an initial value for the editor.
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
return null;
}
}
测试之前的代码(我正在使用 JFrame)
String[] hdrsObjects = new String[]{"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButton();
objectMatrix[1][0] = new PanelSpinnerRadioButton();
objectMatrix[2][0] = new PanelSpinnerRadioButton();
JTable jtbl = new JTable(new PSRBTableModel(objectMatrix, hdrsObjects));
//jtbl.setDefaultRenderer(PanelSpinnerRadioButton.class, new PSRBTableCellRenderer());
//jtbl.setDefaultEditor(PanelSpinnerRadioButton.class, new PSRBTableCellEditor());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellRenderer(new PSRBTableCellRenderer());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellEditor(new PSRBTableCellEditor());
add(new JScrollPane(jtbl));
但是我看不到 JTable 有(3 行自定义 JPanel 'PanelSpinnerRadioButton')
我有这个例外...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
at javax.swing.JComponent.paintComponent(JComponent.java:780)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:306)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent.paint(JComponent.java:1042)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
at java.awt.Container.paint(Container.java:1975)
at java.awt.Window.paint(Window.java:3912)
at javax.swing.RepaintManager.run(RepaintManager.java:842)
at javax.swing.RepaintManager.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access00(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
问题
- 怎么了?
- 为什么我看不到JTable和3
PanelSpinnerRadioButton
?
版本
请考虑这种情况(由相同的 TableCellRenderer
PSRBTableCellRenderer 和 TableCellEditor
PSRBTableCellEditor 处理的另一个自定义 JPanel)
class PanelButton extends JPanel {
private final JPanel jpPanelButton = new JPanel();
// the ActionListener does not matter now
JButton jbtAction = new JButton("Action");
PanelButton() {
this(new PanelButtonEmpty());
}
PanelButton(PanelButtonEmpty data) {
super();
jpPanelButton.setLayout(new BoxLayout(jpPanelButton, BoxLayout.LINE_AXIS));
jpPanelButton.add(jbtAction);
/*Overridable method call in constructor*/
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelButton);
}
public PanelButtonEmpty getData() {
return new PanelButtonEmpty();
}
public void setData(PanelButtonEmpty data) {
}
}
我在想一个完全空的 class(将值转换为 TableCellRenderer
PSRBTableCellEditor)
class PanelButtonEmpty {
PanelButtonEmpty() { }
//public boolean getLazy() { return true; }
//public void setLazy(boolean b) {}
}
在这种情况下,我有两种类型的自定义 JPanel,因此我有
用于 TableCellEditor
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private Object output;
@Override public Object getCellEditorValue() {
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
if (output instanceof PanelButton) {
return ((PanelButton)output).getData();
}
return null;
}
@Override public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
return (PanelButton)output;
}
return null;
}
}
对于TableCellRenderer
public class PSRBTableCellRenderer implements TableCellRenderer {
private Object output = null;
@Override public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
}
return (Component)output;
}
}
问题
如何避免第二次警告(在新场景中)?
TableCellRenderer#getTableCellRendererComponent(...)
. 每次创建一个组件是一种浪费
如何处理与此处描述不同的对象?
PD:
我不确定将第二部分问题放在另一个具有相同源代码的 post 中...
objectMatrix[0][0] = new PanelSpinnerRadioButton();
- 应设置
PanelSpinnerRadioButtonData
为 TableModel
,而不是 PanelSpinnerRadioButton
. 等组件
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
TableCellRenderer#getTableCellRendererComponent(...)
. 每次都创建一个组件很浪费
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableTest {
public JComponent makeUI() {
String[] hdrsObjects = {"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButtonData(false, 10, 40);
objectMatrix[1][0] = new PanelSpinnerRadioButtonData(true, 20, 40);
objectMatrix[2][0] = new PanelSpinnerRadioButtonData(false, 30, 40);
JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects));
table.setRowHeight(30);
TableColumn tc = table.getColumn("PanelSpinnerRadioButton Class Column");
tc.setCellRenderer(new PSRBTableCellRenderer());
tc.setCellEditor(new PSRBTableCellEditor());
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
try {
for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableTest().makeUI());
f.setSize(240, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() {
return opt02;
}
public Integer getFrom() {
return from;
}
public Integer getSize() {
return size;
}
}
class PanelSpinnerRadioButton extends JPanel {
public final JRadioButton jrbOption01 = new JRadioButton("01");
public final JRadioButton jrbOption02 = new JRadioButton("12");
public final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel panel = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(jrbOption01);
panel.add(jrbOption02);
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(new JSeparator(JSeparator.VERTICAL));
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(jspnValues);
ButtonGroup bg = new ButtonGroup();
bg.add(jrbOption01);
bg.add(jrbOption02);
((SpinnerNumberModel) jspnValues.getModel()).setMaximum(data.getSize());
setData(data);
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0));
add(panel);
}
public void setData(PanelSpinnerRadioButtonData data) {
if (data.getOption()) {
jrbOption02.setSelected(true);
} else {
jrbOption01.setSelected(true);
}
((SpinnerNumberModel) jspnValues.getModel()).setValue(data.getFrom());
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getValue(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getMaximum());
}
}
class PSRBTableCellRenderer implements TableCellRenderer {
private final PanelSpinnerRadioButton renderer = new PanelSpinnerRadioButton();
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
renderer.setData((PanelSpinnerRadioButtonData) value);
}
return renderer;
}
}
class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private final PanelSpinnerRadioButton editor = new PanelSpinnerRadioButton();
@Override public Object getCellEditorValue() {
return editor.getData();
}
@Override public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
editor.setData((PanelSpinnerRadioButtonData) value);
}
return editor;
}
}
第二部分
我有这个源代码...
public class PSRBTableCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private Object output = null;
private final PanelSpinnerRadioButton psrb = new PanelSpinnerRadioButton();
private final PanelButton pb = new PanelButton();
@Override
public Object getCellEditorValue() {
if (output instanceof PanelSpinnerRadioButton) {
return psrb.getData();
}
if (output instanceof PanelButton) {
return pb.getData();
}
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
psrb.setData((PanelSpinnerRadioButtonData) value);
output = psrb;
return psrb;
}
if (value instanceof PanelButtonEmpty) {
pb.setData((PanelButtonEmpty) value);
output = pb;
return pb;
}
return null;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
psrb.setData((PanelSpinnerRadioButtonData)value);
output = psrb;
return psrb;
}
if (value instanceof PanelButtonEmpty) {
pb.setData((PanelButtonEmpty)value);
output = pb;
return pb;
}
return null;
}
}
这是一道很长的题,但需要所有代码(我想的是一道基础题,没有共同的组成部分)。
我需要构建一个 JTable,其中包含多个自定义类型 JPanel
的多个列(使用 JSlider
+ JComboBox
+ JTextField
)一栏。
我正在阅读:http://pekalicious.com/blog/custom-jpanel-cell-with-jbuttons-in-jtable/
在这个问题中,我将使用一个列,其中只有一个自定义 JPanel
,名称为 PanelSpinnerRadioButton
。
自定义面板:PanelSpinnerRadioButton.java
public class PanelSpinnerRadioButton extends JPanel {
private final JRadioButton jrbOption01= new JRadioButton("01");
private final JRadioButton jrbOption02 = new JRadioButton("12");
private final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel jpPanelSpinnerRadioButton = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
jpPanelSpinnerRadioButton.setLayout(new BoxLayout(jpPanelSpinnerRadioButton, BoxLayout.LINE_AXIS));
jpPanelSpinnerRadioButton.add(jrbOption01);
jpPanelSpinnerRadioButton.add(jrbOption02);
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(new JSeparator(JSeparator.VERTICAL));
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(jspnValues);
//Change States of RadioButtons (will be readOnly, ButtonGroup is not needed)
jrbOption02.setSelected(data.getOption());
jrbOption01.setSelected(!data.getOption());
//Change States of Spinner
((SpinnerNumberModel)jspnValues.getModel()).setValue(data.getFrom());
((SpinnerNumberModel)jspnValues.getModel()).setMaximum(data.getSize());
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelSpinnerRadioButton);
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getValue(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getMaximum()
);
}
}
这里是自定义JPanel之前的Image Result
自定义面板的数据类型:PanelSpinnerRadioButtonData.java
public class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() { return opt02; }
public Integer getFrom() { return from; }
public Integer getSize() { return size; }
}
现在编码来处理我的自定义 JPanel(带有内部 JComponents)
Table型号:PSRBTableModel.java
public class PSRBTableModel extends AbstractTableModel {
private final Object[][] data;
private final Object[] columns;
public PSRBTableModel(Object[][] data, Object[] columns) {
// super();
this.data = data;
this.columns = columns;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[rowIndex][columnIndex] instanceof PanelSpinnerRadioButton) {
return (PanelSpinnerRadioButton)data[rowIndex][columnIndex];
}
return data[rowIndex][columnIndex];
}
}
return null;
}
public int getColumnCount() {
return ((columns == null) ? 0: columns.length);
}
public int getRowCount() {
return ((data == null) ? 0: data.length);
}
public Class getColumnClass(int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
return data[0][columnIndex].getClass();
}
}
return null;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
//PanelSpinnerRadioButton Is not Editable
return false;
}
}
}
return true;
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public String getColumnName(int columnIndex) {
return (String)columns[columnIndex];
}
}
渲染器:PSRBTableCellRenderer.java
public class PSRBTableCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Object output = null;
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
return (Component)output;
}
}
和 EditorCell:PSRBTableCellEditor.java
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
protected Object output;
PSRBTableCellEditor() {
}
public Object getCellEditorValue() {
//Returns the value contained in the editor.
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
return null;
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//Sets an initial value for the editor.
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
return null;
}
}
测试之前的代码(我正在使用 JFrame)
String[] hdrsObjects = new String[]{"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButton();
objectMatrix[1][0] = new PanelSpinnerRadioButton();
objectMatrix[2][0] = new PanelSpinnerRadioButton();
JTable jtbl = new JTable(new PSRBTableModel(objectMatrix, hdrsObjects));
//jtbl.setDefaultRenderer(PanelSpinnerRadioButton.class, new PSRBTableCellRenderer());
//jtbl.setDefaultEditor(PanelSpinnerRadioButton.class, new PSRBTableCellEditor());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellRenderer(new PSRBTableCellRenderer());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellEditor(new PSRBTableCellEditor());
add(new JScrollPane(jtbl));
但是我看不到 JTable 有(3 行自定义 JPanel 'PanelSpinnerRadioButton')
我有这个例外...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
at javax.swing.JComponent.paintComponent(JComponent.java:780)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:306)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent.paint(JComponent.java:1042)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
at java.awt.Container.paint(Container.java:1975)
at java.awt.Window.paint(Window.java:3912)
at javax.swing.RepaintManager.run(RepaintManager.java:842)
at javax.swing.RepaintManager.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access00(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
问题
- 怎么了?
- 为什么我看不到JTable和3
PanelSpinnerRadioButton
?
版本
请考虑这种情况(由相同的 TableCellRenderer
PSRBTableCellRenderer 和 TableCellEditor
PSRBTableCellEditor 处理的另一个自定义 JPanel)
class PanelButton extends JPanel {
private final JPanel jpPanelButton = new JPanel();
// the ActionListener does not matter now
JButton jbtAction = new JButton("Action");
PanelButton() {
this(new PanelButtonEmpty());
}
PanelButton(PanelButtonEmpty data) {
super();
jpPanelButton.setLayout(new BoxLayout(jpPanelButton, BoxLayout.LINE_AXIS));
jpPanelButton.add(jbtAction);
/*Overridable method call in constructor*/
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelButton);
}
public PanelButtonEmpty getData() {
return new PanelButtonEmpty();
}
public void setData(PanelButtonEmpty data) {
}
}
我在想一个完全空的 class(将值转换为 TableCellRenderer
PSRBTableCellEditor)
class PanelButtonEmpty {
PanelButtonEmpty() { }
//public boolean getLazy() { return true; }
//public void setLazy(boolean b) {}
}
在这种情况下,我有两种类型的自定义 JPanel,因此我有
用于 TableCellEditor
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private Object output;
@Override public Object getCellEditorValue() {
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
if (output instanceof PanelButton) {
return ((PanelButton)output).getData();
}
return null;
}
@Override public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
return (PanelButton)output;
}
return null;
}
}
对于TableCellRenderer
public class PSRBTableCellRenderer implements TableCellRenderer {
private Object output = null;
@Override public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
}
return (Component)output;
}
}
问题
如何避免第二次警告(在新场景中)?
TableCellRenderer#getTableCellRendererComponent(...)
. 每次创建一个组件是一种浪费
如何处理与此处描述不同的对象?
PD:
我不确定将第二部分问题放在另一个具有相同源代码的 post 中...
objectMatrix[0][0] = new PanelSpinnerRadioButton();
- 应设置
PanelSpinnerRadioButtonData
为TableModel
,而不是PanelSpinnerRadioButton
. 等组件
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
TableCellRenderer#getTableCellRendererComponent(...)
. 每次都创建一个组件很浪费
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableTest {
public JComponent makeUI() {
String[] hdrsObjects = {"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButtonData(false, 10, 40);
objectMatrix[1][0] = new PanelSpinnerRadioButtonData(true, 20, 40);
objectMatrix[2][0] = new PanelSpinnerRadioButtonData(false, 30, 40);
JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects));
table.setRowHeight(30);
TableColumn tc = table.getColumn("PanelSpinnerRadioButton Class Column");
tc.setCellRenderer(new PSRBTableCellRenderer());
tc.setCellEditor(new PSRBTableCellEditor());
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
try {
for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableTest().makeUI());
f.setSize(240, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() {
return opt02;
}
public Integer getFrom() {
return from;
}
public Integer getSize() {
return size;
}
}
class PanelSpinnerRadioButton extends JPanel {
public final JRadioButton jrbOption01 = new JRadioButton("01");
public final JRadioButton jrbOption02 = new JRadioButton("12");
public final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel panel = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(jrbOption01);
panel.add(jrbOption02);
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(new JSeparator(JSeparator.VERTICAL));
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(jspnValues);
ButtonGroup bg = new ButtonGroup();
bg.add(jrbOption01);
bg.add(jrbOption02);
((SpinnerNumberModel) jspnValues.getModel()).setMaximum(data.getSize());
setData(data);
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0));
add(panel);
}
public void setData(PanelSpinnerRadioButtonData data) {
if (data.getOption()) {
jrbOption02.setSelected(true);
} else {
jrbOption01.setSelected(true);
}
((SpinnerNumberModel) jspnValues.getModel()).setValue(data.getFrom());
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getValue(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getMaximum());
}
}
class PSRBTableCellRenderer implements TableCellRenderer {
private final PanelSpinnerRadioButton renderer = new PanelSpinnerRadioButton();
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
renderer.setData((PanelSpinnerRadioButtonData) value);
}
return renderer;
}
}
class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private final PanelSpinnerRadioButton editor = new PanelSpinnerRadioButton();
@Override public Object getCellEditorValue() {
return editor.getData();
}
@Override public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
editor.setData((PanelSpinnerRadioButtonData) value);
}
return editor;
}
}
第二部分
我有这个源代码...
public class PSRBTableCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private Object output = null;
private final PanelSpinnerRadioButton psrb = new PanelSpinnerRadioButton();
private final PanelButton pb = new PanelButton();
@Override
public Object getCellEditorValue() {
if (output instanceof PanelSpinnerRadioButton) {
return psrb.getData();
}
if (output instanceof PanelButton) {
return pb.getData();
}
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
psrb.setData((PanelSpinnerRadioButtonData) value);
output = psrb;
return psrb;
}
if (value instanceof PanelButtonEmpty) {
pb.setData((PanelButtonEmpty) value);
output = pb;
return pb;
}
return null;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
psrb.setData((PanelSpinnerRadioButtonData)value);
output = psrb;
return psrb;
}
if (value instanceof PanelButtonEmpty) {
pb.setData((PanelButtonEmpty)value);
output = pb;
return pb;
}
return null;
}
}