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

あなたの例には多くの問題がありますが、最も重要なのはアルファ値を持つ色の使用です。

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

Swing は、(このコンテキスト内で) アルファ ベースの色を持つコンポーネントを適切にレンダリングしません。コンポーネントを不透明にし、アルファ値を使用するように背景色を設定することで、コンポーネントの下にあるものをペイントすることを心配する必要がないことを 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

コメントできないので、これを答えにする必要があります:

Trushgod が述べたように、この問題は super.paintComponent(g) 呼び出しの欠落が原因である可能性がありますが、paintComponent メソッドをまったくオーバーライドしていないようです (少なくともここでは表示されませんでした)。JFrame または任意の JPanels の paintComponent メソッドをオーバーライドする場合は、次のものが必要です。

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

しかし、まったく使用していない場合、問題は別の原因である可能性があります。

于 2013-08-06T01:53:24.863 に答える