所以我有这个登录表单,我有一张“用户照片”。我正在尝试这样做,以便当您将鼠标悬停在照片区域上时,将出现带有彩色背景的透明标签(以提供“选择照片”的效果)。它看起来像这样:
一旦你将鼠标移开,它就会重新被“取消选择。”
现在问题是,如果您先将鼠标悬停在登录按钮上,然后将鼠标移到照片上,则会出现“幽灵登录按钮”。它看起来像这样:
我不知道为什么会这样。有人可以帮忙吗?以下是相关代码:
package com.stats;
public class Stats extends JFrame implements Serializable {
private JLabel fader;
public Stats() {
try {
Image image = ImageIO.read(new File(System.getenv("APPDATA")
+ "\\Stats\\Renekton_Cleave.png"));
JLabel labelUserPhoto = new JLabel(new ImageIcon(image));
fader = new JLabel();
fader.setBounds(97, 44, 100, 100);
fader.setOpaque(true);
fader.setBackground(new Color(0, 0, 0, 0));
labelUserPhoto.setBounds(97, 44, 100, 100);
PicHandler ph = new PicHandler();
contentPane.add(fader);
contentPane.add(labelUserPhoto);
fader.addMouseMotionListener(ph);
} catch(Exception e) {
e.printStackTrace();
}
}
private class PicHandler implements MouseMotionListener {
public void mouseDragged(MouseEvent e) { }
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("x: " + x + ", y: " + y);
if ((x > 16 && x < 80) && (y > 16 && y < 80)) {
if (!fader.isOpaque()) {
fader.setOpaque(true);
fader.setBackground(new Color(0, 0, 0, 40));
fader.repaint();
}
} else {
if (fader.isOpaque()) {
fader.setOpaque(false);
fader.repaint();
}
}
}
}
答案 0 :(得分:2)
我可以看到你的例子有很多问题,但最重要的是使用带有alpha值的颜色。
fader.setBackground(new Color(0, 0, 0, 40));
Swing不会很好地渲染具有基于alpha颜色的组件(在此上下文中)。通过使组件不透明,然后将背景颜色设置为使用alpha值,您告诉Swing它不需要担心绘制组件下面的内容,这不是真的......
Graphics
上下文也是一个共享资源,这意味着在组件之前绘制的任何内容仍然是“绘制”的,您需要在绘制之前清除Graphics
上下文。
这个例子使用了一个相当讨厌的技巧来完成它的工作。因为所有绘画都发生在UI委托中,如果我们只是允许默认的绘画链继续,我们就无法在图标下面渲染。相反,我们接管“脏”细节的控制并代表父母绘制背景。
如果我们从JPanel
这样的简单扩展并自己绘制图像
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FadingIcon {
public static void main(String[] args) {
new FadingIcon();
}
public FadingIcon() {
startUI();
}
public void startUI() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
BufferedImage img = null;
try {
img = ImageIO.read(new File("C:\\Users\\swhitehead\\Documents\\My Dropbox\\Ponies\\SmallPony.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setLayout(new GridBagLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FadingLabel(new ImageIcon(img)));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class FadingLabel extends JLabel {
private boolean mouseIn = false;
private MouseHandler mouseHandler;
public FadingLabel(Icon icon) {
super(icon);
setBackground(Color.RED);
super.setOpaque(false)(
}
@Override
public void setOpaque(boolean opaque) {
}
@Override
public final boolean isOpaque() {
return false;
}
protected MouseHandler getMouseHandler() {
if (mouseHandler == null) {
mouseHandler = new MouseHandler();
}
return mouseHandler;
}
@Override
public void addNotify() {
super.addNotify();
addMouseListener(getMouseHandler());
}
@Override
public void removeNotify() {
removeMouseListener(getMouseHandler());
super.removeNotify();
}
@Override
protected void paintComponent(Graphics g) {
if (mouseIn) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
}
getUI().paint(g, this);
}
public class MouseHandler extends MouseAdapter {
@Override
public void mouseEntered(MouseEvent e) {
mouseIn = true;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
mouseIn = false;
repaint();
}
}
}
}
我还建议你花点时间学习如何使用合适的布局管理器,它们会为你节省大量的时间。
结帐A Visual Guide to Layout Managers和Laying Out Components Within a Container
答案 1 :(得分:0)
由于我无法发表评论,我必须将此作为答案:
正如trashgod所提到的,这个问题可能是由于缺少super.paintComponent(g)调用引起的,但是你似乎根本没有覆盖paintComponent方法(至少你没有在这里显示它)。如果你覆盖了JFrame或任何JPanels的paintComponent方法,你需要:
public void paintComponent(Graphics g) {
super.paintComponent(g);
//rest of your drawing code....
}
但如果您根本没有使用过,那么问题可能是由其他原因造成的。
答案 2 :(得分:0)
由于jdk7有一种新的机制来应用视觉装饰(以及监听子组件的事件):那就是JLayer / LayerUI对。
在您的情况下,自定义layerUI
下面是一个示例,类似于教程中的WallPaperUI:
// usage: create the component and decorate it with the custom ui
JLabel label = new JLabel(myIcon);
content.add(new JLayer(label, new RolloverUI()));
// custom layerUI
public static class RolloverUI extends LayerUI<JComponent> {
private Point lastMousePoint;
private JLayer layer;
/**
* Implemented to install the layer and enable mouse/motion events.
*/
@Override
public void installUI(JComponent c) {
super.installUI(c);
this.layer = (JLayer) c;
layer.setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK
| AWTEvent.MOUSE_EVENT_MASK);
}
@Override
protected void processMouseMotionEvent(MouseEvent e,
JLayer<? extends JComponent> l) {
updateLastMousePoint(e.getPoint());
}
@Override
protected void processMouseEvent(MouseEvent e,
JLayer<? extends JComponent> l) {
if (e.getID() == MouseEvent.MOUSE_EXITED) {
updateLastMousePoint(null);
} else if (e.getID() == MouseEvent.MOUSE_ENTERED) {
updateLastMousePoint(e.getPoint());
}
}
/**
* Updates the internals and calls repaint.
*/
protected void updateLastMousePoint(Point e) {
lastMousePoint = e;
layer.repaint();
}
/**
* Implemented to apply painting decoration below the component.
*/
@Override
public void paint(Graphics g, JComponent c) {
if (inside()) {
Graphics2D g2 = (Graphics2D) g.create();
int w = c.getWidth();
int h = c.getHeight();
g2.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, .5f));
g2.setPaint(new GradientPaint(0, 0, Color.yellow, 0, h,
Color.red));
g2.fillRect(0, 0, w, h);
g2.dispose();
}
super.paint(g, c);
}
protected boolean inside() {
if (lastMousePoint == null || lastMousePoint.x < 0
|| lastMousePoint.y < 0)
return false;
Rectangle r = layer.getView().getBounds();
r.grow(-r.width / 10, -r.height / 10);
return r.contains(lastMousePoint);
}
}
答案 3 :(得分:0)
在移动或调整大小后,我对幻影图像有类似的问题。 @MadProgrammer有一些非常好的点,但最后,它们对我不起作用(可能是因为我有多个层使用0.0 alpha值颜色,其中一些也有图像,所以我无法设置复合整个组件的价值)。最后,修正它的是对
的简单调用<contentpane>.repaint()
执行完所有绘制命令后。