由于 DefaultTableModel getColumnClass 覆盖,即使另外指定,JTable 也会变得不透明
JTable becomes opaque even if specified otherwise, because of DefaultTableModel getColumnClass overrides
我的项目要求将 table 绘制为透明以显示下面的图像。当我覆盖 DefaultTableModel
中的函数 getColumnClass
时,似乎 table.setOpaque(false)
不再执行任何操作。我需要每个单元格只在其中绘制图像,效果很好。这是 table 模型:
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
return ImageIcon.class;
}
};
table 的一小部分在滚动时可见,但当我四处移动或单击它时 table 更新的那一刻,它变得不透明。
我有一个简单的目标,我要在 table 下方的图像上方覆盖单元格中的半透明图像,就像选择一样。图像将关闭和打开,并在此鼠标适配器中处理:
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());//get mouse-selected row
int col = table.columnAtPoint(e.getPoint());//get mouse-selected col
String string = row+"|"+col;
if(selectedCells.contains(string)){
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
} else {
//cell was not selected
selectedCells.add(string);
table.setValueAt(PrimaryWindow.selection, row, col);
System.out.println("Added Cell " + string);
}
}
我通过覆盖 table 所在的面板在下面绘制图像,看起来像这样:
JPanel background = new JPanel( new BorderLayout() )
{
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(icon.getImage(), 0, 0, scale*32, scale*32, this);
}
};
然后在上面加上table:background.add(table);
我有这套:
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
而这组:
table.setOpaque(false);
Here is what the wrong, but current output looks like after clicking a bunch of places
Here is what it looks like if i remove the custom renderer
Here is what it should look like (i made it in paint)
只需单击鼠标,就会在我单击的单元格处的 table 内放置一个图像,这正是我想要的,并且在再次单击同一位置时将其删除。然而,直到我能看到下面的东西之前,它是无用的。我怎样才能让 table 透明,并在下面的面板上显示我的图像?
编辑:
这是一个完整显示问题的临时文件。替换
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
class Scratch {
static LinkedList<String> selectedCells = new LinkedList<>();
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(512,512);
//Make a red square
BufferedImage image = new BufferedImage(1,1, BufferedImage.TYPE_4BYTE_ABGR);
image.setRGB(0,0, Color.RED.getRGB());
//Scale it to the size of the window
ImageIcon icon = new ImageIcon(image.getScaledInstance(512, 512, 1));
image.setRGB(0,0, new Color(0x49000000, true).getRGB());
ImageIcon selection = new ImageIcon(image.getScaledInstance(16, 16, 1));
Object[][] data = new Object[32][32];
String[] names = new String[32];
DefaultTableModel model = new DefaultTableModel(data, names);
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
//Removing 'ImageIcon.class' and replacing it with 'Object.class' makes the table transparent, however does not display the image.
//Keeping this now allows us to put in images into the table, but removes the red square from the background and makes the table opaque
return ImageIcon.class;
}
};
//Set the entire table to transparent
table.setOpaque(false);
//Set the renderer to transparent also
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
MouseListener tableMouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
String string = row+"|"+col;
if(selectedCells.contains(string)){
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
}else{
//cell was not selected
selectedCells.add(string);
table.setValueAt(selection, row, col);
System.out.println("Added Cell " + string);
}
System.out.println(selectedCells);
}
};
table.addMouseListener(tableMouseListener);
table.setName("name");
JPanel background = new JPanel( new BorderLayout() )
{
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(icon.getImage(), 0, 0, 512, 512, this);
}
};
background.setSize(512,512);
frame.add(background);
background.add(table);
frame.setVisible(true);
}
}
在玩弄你的代码时,我在使用你的 JTable
扩展时遇到了问题...
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
//Removing 'ImageIcon.class' and replacing it with 'Object.class' makes the table transparent, however does not display the image.
//Keeping this now allows us to put in images into the table, but removes the red square from the background and makes the table opaque
return ImageIcon.class;
}
};
无论如何,这让我感到畏缩。
如果您想更改单元格的 class 类型,那么您确实应该从 TableModel
执行此操作,这是它的责任。
我个人也会提供自己的 TableCellRenderer
,这样我就可以直接完全控制它的功能
例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
Object[][] data = new Object[32][32];
String[] names = new String[32];
DefaultTableModel model = new DefaultTableModel(data, names) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Icon.class;
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model);
table.setOpaque(false);
table.setDefaultRenderer(Icon.class, new TransparentTableCellRenderer());
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
LinkedList<String> selectedCells = new LinkedList<>();
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, 100, 100);
g2d.dispose();
Icon icon = new ImageIcon(img);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
String string = row + "|" + col;
if (selectedCells.contains(string)) {
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
} else {
//cell was not selected
selectedCells.add(string);
table.setValueAt(icon, row, col);
System.out.println("Added Cell " + string);
}
}
});
JFrame frame = new JFrame();
// Supply your own back ground image
frame.setContentPane(new BackgroundPane(ImageIO.read(Main.class.getResource("/images/Mando01.jpeg"))));
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TransparentTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setOpaque(false);
if (value instanceof Icon) {
setIcon((Icon)value);
} else {
setIcon(null);
}
return this;
}
}
public class BackgroundPane extends JPanel {
private Image background;
public BackgroundPane(Image background) {
setLayout(new BorderLayout());
this.background = background;
}
@Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(this), background.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
}
我的项目要求将 table 绘制为透明以显示下面的图像。当我覆盖 DefaultTableModel
中的函数 getColumnClass
时,似乎 table.setOpaque(false)
不再执行任何操作。我需要每个单元格只在其中绘制图像,效果很好。这是 table 模型:
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
return ImageIcon.class;
}
};
table 的一小部分在滚动时可见,但当我四处移动或单击它时 table 更新的那一刻,它变得不透明。
我有一个简单的目标,我要在 table 下方的图像上方覆盖单元格中的半透明图像,就像选择一样。图像将关闭和打开,并在此鼠标适配器中处理:
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());//get mouse-selected row
int col = table.columnAtPoint(e.getPoint());//get mouse-selected col
String string = row+"|"+col;
if(selectedCells.contains(string)){
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
} else {
//cell was not selected
selectedCells.add(string);
table.setValueAt(PrimaryWindow.selection, row, col);
System.out.println("Added Cell " + string);
}
}
我通过覆盖 table 所在的面板在下面绘制图像,看起来像这样:
JPanel background = new JPanel( new BorderLayout() )
{
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(icon.getImage(), 0, 0, scale*32, scale*32, this);
}
};
然后在上面加上table:background.add(table);
我有这套:
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
而这组:
table.setOpaque(false);
Here is what the wrong, but current output looks like after clicking a bunch of places
Here is what it looks like if i remove the custom renderer
Here is what it should look like (i made it in paint)
只需单击鼠标,就会在我单击的单元格处的 table 内放置一个图像,这正是我想要的,并且在再次单击同一位置时将其删除。然而,直到我能看到下面的东西之前,它是无用的。我怎样才能让 table 透明,并在下面的面板上显示我的图像?
编辑: 这是一个完整显示问题的临时文件。替换
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
class Scratch {
static LinkedList<String> selectedCells = new LinkedList<>();
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(512,512);
//Make a red square
BufferedImage image = new BufferedImage(1,1, BufferedImage.TYPE_4BYTE_ABGR);
image.setRGB(0,0, Color.RED.getRGB());
//Scale it to the size of the window
ImageIcon icon = new ImageIcon(image.getScaledInstance(512, 512, 1));
image.setRGB(0,0, new Color(0x49000000, true).getRGB());
ImageIcon selection = new ImageIcon(image.getScaledInstance(16, 16, 1));
Object[][] data = new Object[32][32];
String[] names = new String[32];
DefaultTableModel model = new DefaultTableModel(data, names);
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
//Removing 'ImageIcon.class' and replacing it with 'Object.class' makes the table transparent, however does not display the image.
//Keeping this now allows us to put in images into the table, but removes the red square from the background and makes the table opaque
return ImageIcon.class;
}
};
//Set the entire table to transparent
table.setOpaque(false);
//Set the renderer to transparent also
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
MouseListener tableMouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
String string = row+"|"+col;
if(selectedCells.contains(string)){
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
}else{
//cell was not selected
selectedCells.add(string);
table.setValueAt(selection, row, col);
System.out.println("Added Cell " + string);
}
System.out.println(selectedCells);
}
};
table.addMouseListener(tableMouseListener);
table.setName("name");
JPanel background = new JPanel( new BorderLayout() )
{
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(icon.getImage(), 0, 0, 512, 512, this);
}
};
background.setSize(512,512);
frame.add(background);
background.add(table);
frame.setVisible(true);
}
}
在玩弄你的代码时,我在使用你的 JTable
扩展时遇到了问题...
JTable table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
@Override
public Class<?> getColumnClass(int column) {
//Removing 'ImageIcon.class' and replacing it with 'Object.class' makes the table transparent, however does not display the image.
//Keeping this now allows us to put in images into the table, but removes the red square from the background and makes the table opaque
return ImageIcon.class;
}
};
无论如何,这让我感到畏缩。
如果您想更改单元格的 class 类型,那么您确实应该从 TableModel
执行此操作,这是它的责任。
我个人也会提供自己的 TableCellRenderer
,这样我就可以直接完全控制它的功能
例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
Object[][] data = new Object[32][32];
String[] names = new String[32];
DefaultTableModel model = new DefaultTableModel(data, names) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Icon.class;
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model);
table.setOpaque(false);
table.setDefaultRenderer(Icon.class, new TransparentTableCellRenderer());
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
LinkedList<String> selectedCells = new LinkedList<>();
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, 100, 100);
g2d.dispose();
Icon icon = new ImageIcon(img);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
String string = row + "|" + col;
if (selectedCells.contains(string)) {
//cell was already selected, deselect it
selectedCells.remove(string);
table.setValueAt(null, row, col);
System.out.println("Removed Cell " + string);
} else {
//cell was not selected
selectedCells.add(string);
table.setValueAt(icon, row, col);
System.out.println("Added Cell " + string);
}
}
});
JFrame frame = new JFrame();
// Supply your own back ground image
frame.setContentPane(new BackgroundPane(ImageIO.read(Main.class.getResource("/images/Mando01.jpeg"))));
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TransparentTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setOpaque(false);
if (value instanceof Icon) {
setIcon((Icon)value);
} else {
setIcon(null);
}
return this;
}
}
public class BackgroundPane extends JPanel {
private Image background;
public BackgroundPane(Image background) {
setLayout(new BorderLayout());
this.background = background;
}
@Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(this), background.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
}