Java 意外的jtable自定义呈现程序行为
我的目标是在JavaSwing中制作一个基本的像素艺术应用程序(我知道这远远不够理想,我们必须为一个类使用Swing做一些事情,我觉得这听起来很有趣) 其思想是将JTable中任何选定单元格的颜色更改为JComboBox中选定的颜色 以下是单击高亮显示的单元格(9,7)后的当前外观: 在其他地方单击(如图所示的(0,6))后,它倾向于填充两个空间之间的空间,以及行的其余部分 这当然不理想-每次单击只需一个单元格即可更改颜色。我是自定义JTable渲染的新手,因此我附加了必要的代码,希望有人能帮助我发现错误。当我在CustomModel类中创建JTable时,感兴趣的区域朝向底部Java 意外的jtable自定义呈现程序行为,java,swing,jtable,Java,Swing,Jtable,我的目标是在JavaSwing中制作一个基本的像素艺术应用程序(我知道这远远不够理想,我们必须为一个类使用Swing做一些事情,我觉得这听起来很有趣) 其思想是将JTable中任何选定单元格的颜色更改为JComboBox中选定的颜色 以下是单击高亮显示的单元格(9,7)后的当前外观: 在其他地方单击(如图所示的(0,6))后,它倾向于填充两个空间之间的空间,以及行的其余部分 这当然不理想-每次单击只需一个单元格即可更改颜色。我是自定义JTable渲染的新手,因此我附加了必要的代码,希望有人能
//Lots of importing
public class PixelArtistGUI extends JFrame {
String colors[] = { "Red", "Orange", "Yellow", "Green", "Blue", "Magenta", "Black", "White" };
JComboBox colorList = new JComboBox(colors);
public PixelArtistGUI() {
setTitle("PixelArtist");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
this.setPreferredSize(new Dimension(400, 450));
// Content Pane
JPanel contentPane = new JPanel();
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[] { 125, 125, 125 };
gbl_contentPane.rowHeights = new int[] {360, 15};
contentPane.setLayout(gbl_contentPane);
JLabel colorSelect = new JLabel("Select Color:");
colorSelect.setFont(new Font("Tahoma", Font.PLAIN, 18));
colorSelect.setHorizontalAlignment(SwingConstants.CENTER);
GridBagConstraints gbc_colorSelect = new GridBagConstraints();
gbc_colorSelect.insets = new Insets(5, 0, 0, 0);
gbc_colorSelect.gridx = 0;
gbc_colorSelect.anchor = GridBagConstraints.SOUTH;
gbc_colorSelect.fill = GridBagConstraints.BOTH;
gbc_colorSelect.gridy = 1;
contentPane.add(colorSelect, gbc_colorSelect);
GridBagConstraints gbc_colorList = new GridBagConstraints();
gbc_colorList.anchor = GridBagConstraints.SOUTH;
gbc_colorList.fill = GridBagConstraints.BOTH;
gbc_colorList.insets = new Insets(5, 0, 0, 0);
gbc_colorList.gridx = 1;
gbc_colorList.gridy = 1;
contentPane.add(colorList, gbc_colorList);
JButton screenshotButton = new JButton("Save Screenshot");
GridBagConstraints gbc_screenshotButton = new GridBagConstraints();
gbc_screenshotButton.anchor = GridBagConstraints.SOUTH;
gbc_screenshotButton.fill = GridBagConstraints.BOTH;
gbc_screenshotButton.insets = new Insets(5, 0, 0, 0);
gbc_screenshotButton.gridx = 2;
gbc_screenshotButton.gridy = 1;
contentPane.add(screenshotButton, gbc_screenshotButton);
String[] colHeadings = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" };
int numRows = 16;
PixelModel model = new PixelModel(numRows, colHeadings.length);
model.setColumnIdentifiers(colHeadings);
JTable table_1 = new JTable(model);
table_1.setBorder(new LineBorder(new Color(0, 0, 0)));
table_1.setRowSelectionAllowed(false);
table_1.setDefaultRenderer(Object.class, new CustomModel());
GridBagConstraints gbc_table_1 = new GridBagConstraints();
gbc_table_1.gridwidth = 3;
gbc_table_1.fill = GridBagConstraints.BOTH;
gbc_table_1.gridx = 0;
gbc_table_1.gridy = 0;
contentPane.add(table_1, gbc_table_1);
table_1.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table_1.setCellSelectionEnabled(true);
table_1.setRowHeight(23);
this.pack();
}
// Custom table renderer to change cell colors
public class CustomModel extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
column);
Color c;
try {
String cString = colorList.getSelectedItem().toString().toLowerCase();
Field field = Class.forName("java.awt.Color").getField(cString);
c = (Color) field.get(null);
} catch (Exception e) {
c = null;
}
if (isSelected)
label.setBackground(c);
return label;
}
}
// Custom table model to make the cells selectable but not editable
public class PixelModel extends DefaultTableModel {
PixelModel(int numRows, int numColumns) {
super(numRows, numColumns);
}
public boolean isCellEditable(int row, int column) {
return false;
}
}
我很感激任何提示,我一直在研究如何解决这个问题。请看一看,并了解有关渲染器和编辑器实际工作方式的更多详细信息
每次调用GetTableCellRenderComponent
时,您都需要根据单元格的值和状态完全配置渲染器。因此,基本上,您所做的只是设置一次背景色,并且永远不要为任何其他条件更改背景色,这意味着当绘制任何其他单元格时(无论出于何种原因),它仍然使用相同的背景色
相反,您应该使用存储在TableModel
中的值来决定单元格应该绘制什么。要实现这一点,您可能需要一个简单的CellEditor
,它可以简单地返回当前选择的颜色
也许像
现在,在有人跳到我身上之前。我会用
Color
s填充JComboBox
,并使用自定义的ListCellRenderer
来显示它。您应该将颜色值存储在TableModel中,然后您的渲染器应该渲染单元格的值。我看不出任何使用反射的理由。另外,我不明白间隔选择应该如何工作。当你点击一个单元格时,你希望其他哪些单元格是彩色的?如果我选择了“红色”,我只希望我点击的单元格变成红色,并一直保持红色,直到再次点击并选择另一种颜色为止。但是当我点击一个单元格时,它正在改变整行的颜色。你必须通过单元格渲染器来做吗?@user1803551我不知道你的意思,它对我来说似乎很好。我自己也被它绊倒了:{顺便说一句,你用什么来创建gif
?会派上用场:)哇,太漂亮了-非常感谢!
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.lang.reflect.Field;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
public class PixelArtistGUI extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
PixelArtistGUI frame = new PixelArtistGUI();
frame.setVisible(true);
}
});
}
String colors[] = {"Red", "Orange", "Yellow", "Green", "Blue", "Magenta", "Black", "White"};
JComboBox colorList = new JComboBox(colors);
public PixelArtistGUI() {
setTitle("PixelArtist");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
this.setPreferredSize(new Dimension(400, 450));
// Content Pane
JPanel contentPane = new JPanel();
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[]{125, 125, 125};
gbl_contentPane.rowHeights = new int[]{360, 15};
contentPane.setLayout(gbl_contentPane);
JLabel colorSelect = new JLabel("Select Color:");
colorSelect.setFont(new Font("Tahoma", Font.PLAIN, 18));
colorSelect.setHorizontalAlignment(SwingConstants.CENTER);
GridBagConstraints gbc_colorSelect = new GridBagConstraints();
gbc_colorSelect.insets = new Insets(5, 0, 0, 0);
gbc_colorSelect.gridx = 0;
gbc_colorSelect.anchor = GridBagConstraints.SOUTH;
gbc_colorSelect.fill = GridBagConstraints.BOTH;
gbc_colorSelect.gridy = 1;
contentPane.add(colorSelect, gbc_colorSelect);
GridBagConstraints gbc_colorList = new GridBagConstraints();
gbc_colorList.anchor = GridBagConstraints.SOUTH;
gbc_colorList.fill = GridBagConstraints.BOTH;
gbc_colorList.insets = new Insets(5, 0, 0, 0);
gbc_colorList.gridx = 1;
gbc_colorList.gridy = 1;
contentPane.add(colorList, gbc_colorList);
JButton screenshotButton = new JButton("Save Screenshot");
GridBagConstraints gbc_screenshotButton = new GridBagConstraints();
gbc_screenshotButton.anchor = GridBagConstraints.SOUTH;
gbc_screenshotButton.fill = GridBagConstraints.BOTH;
gbc_screenshotButton.insets = new Insets(5, 0, 0, 0);
gbc_screenshotButton.gridx = 2;
gbc_screenshotButton.gridy = 1;
contentPane.add(screenshotButton, gbc_screenshotButton);
String[] colHeadings = {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""};
int numRows = 16;
PixelModel model = new PixelModel(numRows, colHeadings.length);
model.setColumnIdentifiers(colHeadings);
JTable table_1 = new JTable(model);
table_1.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
TableCellEditor editor = table_1.getCellEditor();
if (editor != null) {
if (editor.stopCellEditing()) {
editor.cancelCellEditing();
}
}
}
});
table_1.setBorder(new LineBorder(new Color(0, 0, 0)));
table_1.setRowSelectionAllowed(false);
table_1.setDefaultRenderer(Object.class, new CustomRenderer());
table_1.setDefaultEditor(Object.class, new CustomEditor());
GridBagConstraints gbc_table_1 = new GridBagConstraints();
gbc_table_1.gridwidth = 3;
gbc_table_1.fill = GridBagConstraints.BOTH;
gbc_table_1.gridx = 0;
gbc_table_1.gridy = 0;
contentPane.add(table_1, gbc_table_1);
table_1.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table_1.setCellSelectionEnabled(true);
table_1.setRowHeight(23);
this.pack();
}
public class CustomRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, null, false, hasFocus, row, column);
if (value != null && value instanceof Color) {
setBackground((Color) value);
} else {
setBackground(null);
}
return this;
}
}
public class CustomEditor extends AbstractCellEditor implements TableCellEditor {
private JPanel panel;
public CustomEditor() {
this.panel = new JPanel();
}
@Override
public Object getCellEditorValue() {
Color c = null;
try {
String cString = colorList.getSelectedItem().toString().toLowerCase();
Field field = Class.forName("java.awt.Color").getField(cString);
c = (Color) field.get(null);
} catch (Exception e) {
c = null;
}
return c;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
panel.setBackground((Color) getCellEditorValue());
return panel;
}
@Override
public boolean isCellEditable(EventObject e) {
return true;
}
}
// Custom table model to make the cells selectable but not editable
public class PixelModel extends DefaultTableModel {
PixelModel(int numRows, int numColumns) {
super(numRows, numColumns);
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
}
}