2

所以我有这个登录表单,我有一张“用户照片”。我正在尝试这样做,以便当您将鼠标悬停在照片区域上时,会出现一个带有彩色背景的透明标签(以产生“选择照片”的效果)。它看起来像这样:

图像1

一旦你将鼠标移开它,它就会回到“取消选择”状态。

现在我的问题是,如果您先将鼠标悬停在登录按钮上,然后将鼠标移到照片上,则会出现“幽灵登录按钮”。它看起来像这样:

图2

我不知道为什么会这样。有人可以帮忙吗?以下是相关代码:

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();
            }
        }
    }
}
4

4 回答 4

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();
      }

    }

  }

}

我还建议您花时间学习如何使用适当的布局管理器,它们会为您节省很多时间

查看布局管理器和容器内组件布局的可视化指南

于 2013-08-06T07:40:00.593 回答
0

由于我无法发表评论,因此我必须将其作为答案:

正如垃圾神所提到的,这个问题可能是由缺少 super.paintComponent(g) 调用引起的,但是您似乎根本没有覆盖 paintComponent 方法(至少您没有在此处显示它)。如果您确实覆盖了 JFrame 或任何 JPanel 的 paintComponent 方法,则需要:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    //rest of your drawing code....
}

但是,如果您根本没有使用过,那么问题可能是由其他原因引起的。

于 2013-08-06T01:53:24.863 回答
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);
    }
}
于 2013-08-06T09:29:10.520 回答
0

在移动或调整大小后,我遇到了类似的重影图像问题。@MadProgrammer 有一些非常好的观点,但最后,它们对我不起作用(可能是因为我有多个使用 0.0 alpha 值颜色的图层,其中一些也有图像,所以我无法设置合成整个组件的值)。最后,修复它的是一个简单的调用

<contentpane>.repaint()

在执行了所有绘图命令之后。

于 2017-09-15T22:40:15.740 回答