My project requires that a table be drawn as transparent to reveal an image underneath. When I override the function getColumnClass
in DefaultTableModel
, it seems like table.setOpaque(false)
no longer does anything. I need each cell to only draw images within, which works fine. Here is the table model:
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;
}
};
There is a small portion of the table visible while scrolling, but the moment the table updates when I move it around or click on it, it becomes opaque.
I have a simple goal, where i am to overlay a translucent image in a cell, over an image underneath the table, as if like a selection. The image would toggle off and on and is handled in this mouse adapter:
@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);
}
}
I paint the image underneath by overriding the panel the table is in, which looks like this:
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);
}
};
And then add the table in above: background.add(table);
I do have this set:
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
And this set:
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)
Simply clicking the mouse does put an image inside the table at the cell I click, which is exactly what I want, as well as removing it upon clicking the same spot again. However, it is useless until I can see what is underneath. How can I have the table be transparent, and also display my images over the panel underneath?
EDIT: Here is a scratch file with the problem in full display. Replace the
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);
}
}