I'm developing a program for work (notice: I can not share complete code, as it is in large part protected work product, but I will share everything I can). In the application, I have JPanels that have background images applied to them. Some of these panels also have mouse listeners attached & my management wants there to be a visual clue that the panel can be clicked on to initiate an action. To that end, I've overlaid a transparent JPanel on top of the JPanel with the background image, and attached a MouseListener to that, keying off the mouseEntered/Exited events. When the mouse enters the image panel, the overlaid panel will switch from transparent to translucent, and back when the mouse exits.
Under Linux, this works perfectly. Under Windows... it's a good thing I'm bald so I can't tear my hair out. What appears to be happening is that some kind of image caching is occuring as I move the mouse around, and the mouseEnter event is causing whatever the mouse was over a second ago to be painted into the frame; i.e. if I place the mouse over a nearby button on the GUI & then mouse over the panel, I'll see the button appear in the panel, with the surrounding GUI.
The Image Panel is contained within a JInternalFrame that is opaque.
One other thing to note, if I do something in the application that would cause the image to change (e.g. making a new selection from a JComboBox), the image repaints as expected. Whatever the trouble is, it seems related to the highlighting and how the image is being repainted/redrawn.
What am I not doing for Windows that I should be?
Thanks in advance.
Here is a link to some images. Start.png is what it looks like in both OS's when the panel opens. GoodMouseEnter.png is what the mouseEnter event looks like under Linux. BadMouseEnter.png & badMouseExit.png are what it looks like under Windows.
This is the Class I am using to create the image panel (EDIT: This example is self contained):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageTest {
JFrame frm = null;
ImagePanel imgP = null;
public static void main(String[] args) throws MalformedURLException
{
ImageTest it = new ImageTest();
it.initialize();
}
public void initialize() throws MalformedURLException
{
String path = "file:/C:/CylinderTank.png";
URL imagePath = new URL(path);
System.out.println(imagePath.toString());
frm = new JFrame();
imgP = new ImagePanel(true);
int fW = 500;
int fH = 700;
int pW = 450;
int pH = 650;
frm.setLayout(null);
frm.setPreferredSize(new Dimension(fW,fH));
frm.setSize(fW,fH);
imgP.getFilterPanel().addMouseListener(new PanelListener());
imgP.useCustomSizing(pW, pH);
imgP.setImageURL(imagePath);
imgP.setBounds(0, 0, pW, pH);
frm.add(imgP);
frm.pack();
frm.setVisible(true);
}
private class PanelListener implements MouseListener {
public PanelListener() { }
@Override
public void mouseClicked(MouseEvent e) { }
@Override
public void mousePressed(MouseEvent e) { }
@Override
public void mouseReleased(MouseEvent e) { }
@Override
public void mouseEntered(MouseEvent e)
{
imgP.highlightImage(true);
imgP.repaint();
}
@Override
public void mouseExited(MouseEvent e)
{
imgP.highlightImage(false);
imgP.repaint();
}
}
}
@SuppressWarnings("serial")
class ImagePanel extends JPanel implements ImageObserver {
private final JPanel filterPanel;
private BufferedImage image;
private Dimension panelSize;
private final Toolkit kit;
private boolean highlight = false;
private URL imagePath;
private int imgW, imgH;
private final Color blueFilter = new Color(0, 0, 255, 38);
private final Color redFilter = new Color(255, 0, 0, 38);
private final Color greenFilter = new Color(0, 255, 0, 38);
private final Color clear = new Color(0, 0, 0, 0);
private final Color bgColor = new Color(116, 169, 255, 255);
private boolean customSize = false;
public ImagePanel(boolean opaque)
{
super();
this.kit = Toolkit.getDefaultToolkit();
setLayout(null);
setOpaque(opaque);
setBackground(bgColor);
filterPanel = new JPanel();
filterPanel.setBackground(clear);
}
public ImagePanel(URL imagePath, boolean opaque)
{
super();
this.imagePath = imagePath;
this.kit = Toolkit.getDefaultToolkit();
setLayout(null);
setOpaque(opaque);
setBackground(bgColor);
filterPanel = new JPanel();
filterPanel.setBackground(clear);
readImage();
}
@Override
protected void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
if (highlight)
filterPanel.setBackground(blueFilter);
else
filterPanel.setBackground(clear);
int X = 0, Y = 0;
if (image != null)
{
image.flush();
kit.prepareImage(image, -1, -1, this);
if (customSize)
{
X = (panelSize.width - imgW) / 2;
Y = (panelSize.height - imgH) / 2;
}
if (isOpaque())
g2D.drawImage(image, X, Y, bgColor, this);
else
g2D.drawImage(image, X, Y, this);
}
else
super.paintComponent(g2D);
}
public void highlightImage(boolean highlight)
{
this.highlight = highlight;
}
private void readImage()
{
try
{
image = ImageIO.read(imagePath);
imgW = image.getWidth();
imgH = image.getHeight();
if (customSize)
panelSize = getPreferredSize();
else
panelSize = new Dimension(imgW, imgH);
setPreferredSize(panelSize);
setMinimumSize(panelSize);
setMaximumSize(panelSize);
int X = (panelSize.width - imgW) / 2;
int Y = (panelSize.height - imgH) / 2;
filterPanel.setBounds(X, Y, imgW, imgH);
add(filterPanel);
}
catch (IOException ex)
{
Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setImageURL(URL img)
{
this.imagePath = img;
readImage();
}
public Dimension getDisplayedImageSize()
{
if (image == null)
return null;
return new Dimension(imgW, imgH);
}
public JPanel getFilterPanel()
{
return filterPanel;
}
public void useCustomSizing(int W, int H)
{
if (W < 0)
W = getPreferredSize().width;
if (H < 0)
H = getPreferredSize().height;
if ((W>0) || (H>0))
customSize = true;
Dimension cDim = new Dimension(W,H);
setPreferredSize(cDim);
setMinimumSize(cDim);
setMaximumSize(cDim);
repaint();
}
}//end class ImagePanel