Java Swing的图形故障与透明和图像处理 [英] Java Swing Graphical Glitches Dealing with Transparency and Images

查看:203
本文介绍了Java Swing的图形故障与透明和图像处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这样的登录表单,我有一个用户的照片。我试图让这个当你将鼠标悬停在照片区,配有彩色背景透明的标签会出现(给的选择图片的效果)。它看起来是这样的:

而一旦你移动鼠标关闭它,它可以追溯到是取消。

现在我的问题是,如果你将鼠标悬停在登录按钮然后先移动你的鼠标在照片上,会出现一个鬼登录按钮。它看起来是这样的:

我不知道为什么会这样。有人能帮忙吗?下面是相关code:

 包com.stats;公共类统计扩展JFrame的实现Serializable {    私人JLabel的推杆;    公开统计(){    尝试{
        形象画像= ImageIO.read(新文件(System.getenv(APPDATA)
                                   +\\\\ \\\\统计Renekton_Cleave.png));
        JLabel的labelUserPhoto =新的JLabel(新ImageIcon的(图片));
        推子=新的JLabel();
        fader.setBounds(97,44,100,100);
        fader.setOpaque(真);
        fader.setBackground(新的色彩(0,0,0,0));
        labelUserPhoto.setBounds(97,44,100,100);
        PicHandler ph值=新PicHandler();
        contentPane.add(推子);
        contentPane.add(labelUserPhoto);
        fader.addMouseMotionListener(PH);
    }赶上(例外五){
        e.printStackTrace();
    }
}私有类PicHandler实现的MouseMotionListener {
    公共无效的mouseDragged(的MouseEvent E){}
    公共无效的mouseMoved(的MouseEvent E){
        INT X = e.getX();
        INT Y = e.getY();        的System.out.println(×+ X +,Y:+ y)基        如果((X> 16和;&放大器; X&下; 80)及及(Y'GT; 16和;&放大器; Y&下; 80)){
            如果(!fader.isOpaque()){
                fader.setOpaque(真);
                fader.setBackground(新的色彩(0,0,0,40));
                fader.repaint();
            }
        }其他{
            如果(fader.isOpaque()){
                fader.setOpaque(假);
                fader.repaint();
            }
        }
    }
}


解决方案

我可以看到一些与你的榜样的问题,但最显著是alpha值使用的颜色。

  fader.setBackground(新颜色(0,0,0,40));

摇摆不呈现与基于阿尔法颜色好(此范围内)组件。通过使成分不透明,然后设置背景颜色使用alpha值,你告诉摇摆它并不需要担心画什么是你的组件,这是不正确的......下面

图形背景也是一个共享的资源,这意味着什么,是你的组件之前画仍然是涂,你需要清除图形油漆前环境。

此示例使用相当恶劣的手段来得到它的完成工作。因为所有的绘画UI委托范围内发生,如果我们只是让默认的油漆链继续下去,我们将无法呈现图标下方。相反,我们接手的脏的细节控制和油漆代表背景的家长。

这是更简单的实现了从东西,如果我们简单的延伸,就像的JP​​anel 和彩绘的形象自己

 进口java.awt.AlphaComposite中;
进口java.awt.Color中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.GridBagLayout中;
进口java.awt.event.MouseAdapter;
进口java.awt.event.MouseEvent中;
进口java.awt.image.BufferedImage中;
进口的java.io.File;
进口java.io.IOException异常;
进口javax.imageio.ImageIO中;
进口javax.swing.Icon;
进口javax.swing.ImageIcon中;
进口javax.swing.JFrame中;
进口javax.swing.JLabel中;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;公共类FadingIcon {  公共静态无效的主要(字串[] args){
    新FadingIcon();
  }  公共FadingIcon(){
    startUI();
  }  公共无效startUI(){
    EventQueue.invokeLater(新的Runnable(){
      @覆盖
      公共无效的run(){
        尝试{
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
          ex.printStackTrace();
        }        IMG的BufferedImage = NULL;
        尝试{
          IMG = ImageIO.read(新文件(C:\\\\ \\\\用户\\\\ swhitehead文件\\\\我的Dropbox的\\\\ \\\\小马SmallPony.png));
        }赶上(IOException异常前){
          ex.printStackTrace();
        }        JFrame的帧=新的JFrame(测试);
        frame.setLayout(新的GridBagLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(新FadingLabel(新的ImageIcon(IMG)));
        frame.pack();
        frame.setLocationRelativeTo(NULL);
        frame.setVisible(真);
      }
    });
  }  公共类FadingLabel扩展JLabel {    私人布尔mouseIn = FALSE;
    私人MouseHandler mouseHandler;    公共FadingLabel(ICON图标){
      超(图标);
      的setBackground(Color.RED);
      super.setOpaque(假)(
    }    @覆盖
    公共无效setOpaque(布尔不透明){
    }    @覆盖
    公共最后布尔isOpaque(){
        返回false;
    }    保护MouseHandler getMouseHandler(){
      如果(mouseHandler == NULL){
        mouseHandler =新MouseHandler();
      }
      返回mouseHandler;
    }    @覆盖
    公共无效信息addNotify(){
      super.addNotify();
      addMouseListener将(getMouseHandler());
    }    @覆盖
    公共无效的removeNotify(){
      removeMouseListener(getMouseHandler());
      super.removeNotify();
    }    @覆盖
    保护无效paintComponent(图形G){
      如果(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()漆(克,这一点);
    }    公共类MouseHandler扩展MouseAdapter {      @覆盖
      公共无效的mouseEntered(的MouseEvent E){
        mouseIn =真;
        重绘();
      }      @覆盖
      公共无效的mouseExited(的MouseEvent E){
        mouseIn = FALSE;
        重绘();
      }    }  }}

我也建议你花时间去学习如何使用适当的布局管理器的时候,他们会为您节省大量的头发拉后

查看href=\"http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html\" rel=\"nofollow\">的可视指导布局管理器和布放组件内的容器

So I have this login form and I have a "user photo." I'm trying to make it so that when you hover the mouse over the photo area, a transparent label with a colored background will appear (to give the effect of "selecting the photo"). It looks like this:

And once you move your mouse off it, it goes back to being "deselected."

Now my problem is, if you hover your mouse over the login button first then move your mouse over the photo, a "ghost login button" appears. It looks like this:

I don't know why this is happening. Can someone help? Here is the relevant code:

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

解决方案

I can see a number of issues with your example, but the most significant is the use of a color with an alpha value.

fader.setBackground(new Color(0, 0, 0, 40));

Swing doesn't render components with alpha based colors well (within this context). By making component opaque and then setting the background color to use an alpha value, you are telling Swing that it doesn't need to worry about painting what's underneath your component, which isn't true...

The Graphics context is also a shared resource, meaning that anything that was painted before your component is still "painted", you need to clear the Graphics context before painting.

This example uses a rather nasty trick to get it's work done. Because all the painting occurs within the UI delegate, if we were simply to allow the default paint chain to continue, we wouldn't be able to render underneath the icon. Instead, we take over control of the "dirty" details and paint the background on the behalf the parent.

This would be simpler to achieve if we simple extended from something like JPanel and painted the image ourselves

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

    }

  }

}

I would also recommend that you take the time to learn how to use appropriate layout managers, they will save you a lot of hair pulling later

Check out A Visual Guide to Layout Managers and Laying Out Components Within a Container

这篇关于Java Swing的图形故障与透明和图像处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆