【问题标题】:Problems with transparent JFrame透明 JFrame 的问题
【发布时间】:2017-02-13 10:54:09
【问题描述】:

我已经创建了 JFrame,将透明颜色(new Color(0, 0, 0, 0))设置为背景并将 JPanel 放置在上面。我已经覆盖了 JPanel 的 paintComponent 方法并在其上绘制了一些带有 alpha 通道的图像。当用户右键单击我的 JPanel 时,我也会显示弹出菜单。

我面临这样一个事实,即弹出菜单的图像在它应该消失后仍保留在 JFrame 上(刚才 JPanel 的图片覆盖了它)。据我了解,在绘制新框架之前不会清除 JFrame。

示例

public class MainWindow extends JFrame {

    private MyPanel widget = new MyPanel();
    private Action quitAction = new AbstractAction("Quit") {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            setVisible(false);
            dispose();
        }
    };

    private MainWindow() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setUndecorated(true);
        setBackground(new Color(0, 0, 0, 0));
        widget.loadImage("image.png");
        setContentPane(widget);
        pack();
        setAlwaysOnTop(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(() -> {
            MainWindow window = new MainWindow();
            window.setVisible(true);
        });
    }

    class MyPanel extends JPanel implements MouseListener {
        BufferedImage image;

        MyPanel() {
            super();
            addMouseListener(this);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintCompontent(g);
            if (characterImage != null) {
                g.drawImage(characterImage, 0, 0, this);
            }
        }

        @Override
        public void mouseClicked(MouseEvent e) {
        }

        @Override
        public void mousePressed(MouseEvent e) {
            clickPos = e.getLocationOnScreen();
            if (SwingUtilities.isRightMouseButton(e)) {
                JPopupMenu popupMenu = new JPopupMenu();
                popupMenu.add(quitAction);
                popupMenu.show(this, e.getX(), e.getY());
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }

        boolean loadImage(String name) {
            BufferedImage backupImage = image;
            try {
                image = ImageIO.read(MainWindow.class.getResourceAsStream("/images/" + name));
                setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
            } catch (IOException ex) {
                image = backupImage;
                return false;
            }
            return true;
        }

    }

}

【问题讨论】:

  • 您还忘记提供runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个例子,它突出了您遇到的问题。这将导致更少的混乱和更好的响应
  • 我“猜想”你没有调用 super.paintComponent 和/或你使用基于 alpha 的颜色来设置面板的背景
  • “据我了解,在绘制新框架之前不会清除 JFrame。” - 仅当您尊重绘制链并确保何时覆盖任何绘制方法时,您正在调用他们的超级方法(并且您不会尝试将基于 alpha 的颜色应用于不透明面板)
  • 我添加了代码示例。不,我没有忘记调用父方法。
  • "...JFrame 在绘制之前没有被清除..." 你是对的。 “清除”通过 JFrame 再次调用paintBackground 进行。但是由于您的背景是半透明的,所以您的弹出菜单图形会留下

标签: java swing


【解决方案1】:

所以,根据你的代码,一旦我纠正它工作,我似乎没有任何问题

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

public class MainWindow extends JFrame {

    private MyPanel widget = new MyPanel();
    private Action quitAction = new AbstractAction("Quit") {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            setVisible(false);
            dispose();
        }
    };

    private MainWindow() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setUndecorated(true);
        setBackground(new Color(0, 0, 0, 0));
        widget.loadImage("MT.png");
        setContentPane(widget);
        pack();
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(() -> {
            MainWindow window = new MainWindow();
            window.setVisible(true);
        });
    }

    class MyPanel extends JPanel implements MouseListener {

        BufferedImage image;

        MyPanel() {
            super();
            addMouseListener(this);
            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
            if (image != null) {
                g.drawImage(image, 0, 0, this);
            }
        }

        @Override
        public void mouseClicked(MouseEvent e) {
        }

        @Override
        public void mousePressed(MouseEvent e) {
//            clickPos = e.getLocationOnScreen();
            if (SwingUtilities.isRightMouseButton(e)) {
                JPopupMenu popupMenu = new JPopupMenu();
                popupMenu.add(quitAction);
                popupMenu.show(this, e.getX(), e.getY());
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }

        boolean loadImage(String name) {
            BufferedImage backupImage = image;
            try {
                image = ImageIO.read(MainWindow.class.getResourceAsStream("/images/" + name));
                setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
            } catch (IOException ex) {
                image = backupImage;
                return false;
            }
            return true;
        }

    }

}

【讨论】:

  • 嗯...我在 Windows 10 下检查了我的代码,它工作正常。据我了解,您使用的是 Mac OS。似乎问题并不总是出现,而仅在某些条件下出现。就我而言,它是 Linux + Gnome 3。但我找到了解决方案。
【解决方案2】:

我在我的代码中发现了问题。为了让一切正常工作,我需要在使用 paintCompontent 中的 g.drawImage 进行图片绘制之前插入此代码。

if (g instanceof Graphics2D) {
    Graphics2D g2d = (Graphics2D)g;
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
}

此外,问题并非在所有情况下都会出现。例如,在 Windows 下它运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多