java setOpaque(false)使得悬停缓慢

时间:2018-04-02 16:38:26

标签: java swing button graphics jpanel

我通过扩展JPanel并使用OverlayLayout在彼此的顶部添加2个JLabel来创建一个按钮。其中一个JLabel是图标,它只是一个字体很棒的图标。另一个是悬停文本。我希望JPanel的背景是透明的,因此它没有白色边框。我使用这个AlphaContainer方法做到了这一点:

https://www.programcreek.com/java-api-examples/index.php?source_dir=cismet-gui-commons-master/src/main/java/de/cismet/tools/gui/AlphaContainer.java

这就是我所说的慢速悬停:

enter image description here

我现在只将setOpaque(false)属性添加到图标的下半部分。 这就是它的样子: enter image description here

这里我添加了6个按钮:

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        HoverButtonTest forum = new HoverButtonTest("\uf086", "Forum", Settings.iconSize);
        add(forum);

        HoverButtonTest hs = new HoverButtonTest("\uf080", "Highscores", Settings.iconSize);
        add(hs);

        HoverButtonTest shop = new HoverButtonTest("\uf07a", "Store", Settings.iconSize);
        add(shop);

        HoverButtonTest vote = new HoverButtonTest("\uf046", "Vote for Us", Settings.iconSize);
        vote.setOpaque(false);
        add(vote);

        HoverButtonTest discord = new HoverButtonTest("\uf392", "Discord", Settings.iconSize, HoverButtonTest.Type.BRAND);
        discord.setOpaque(false);
        add(discord);

        HoverButtonTest web = new HoverButtonTest("\uf0ac", "Web", Settings.iconSize, HoverButtonTest.Type.SOLID);
        web.setOpaque(false);
        add(web);

这是我正在使用的按钮类:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

/**
 * @author Ruud.
 */
public class HoverButtonTest extends JPanel implements MouseListener {

    public enum Type {
        NORMAL("Font Awesome.ttf"),
        REGULAR("Font Awesome Regular.ttf"),
        SOLID("Font Awesome Solid.ttf"),
        BRAND("Font Awesome Brands.ttf");

        String font;

        Type(String font) {
            this.font = font;
        }

        String getFont() {
            return font;
        }

    }

    private JLabel icon;
    private JLabel text;

    public HoverButtonTest(String icon, String text, int size) {
        this(icon, text, size, Type.NORMAL);
    }

    public HoverButtonTest(String icon, String text, int size, Type type) {
        setLayout(new OverlayLayout(this));
        addMouseListener(this);
        setOpaque(false);

        this.text = new JLabel(text);
        this.text.setForeground(Color.WHITE);
        this.text.setAlignmentX(0.5f);
        this.text.setAlignmentY(0.5f);
        Utils.setFont(this.text, "OpenSans-Light.ttf", 13);
        this.text.setVisible(false);
        add(this.text);

        this.icon = new JLabel(icon);
        this.icon.setForeground(Settings.primaryColor);
        this.icon.setAlignmentX(0.5f);
        this.icon.setAlignmentY(0.5f);
        Utils.setFont(this.icon, type.getFont(), size);
        add(this.icon);
    }

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(new Color(0, 0, 0, 0));
    }


    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        text.setVisible(true);
        icon.setForeground(Settings.primaryColor.darker().darker().darker().darker());
    }

    @Override
    public void mouseExited(MouseEvent e) {
        text.setVisible(false);
        icon.setForeground(Settings.primaryColor);
    }
}

我已经编辑了RadioDef的代码,以满足我的需求,奇怪的是它并没有出现在这段代码中

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;

public class MouseoverPanels {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(MouseoverPanels::new);
    }

    public MouseoverPanels() {
        JFrame frame = new JFrame("Mouseover Panels");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JPanel background = new Background();

        JPanel buttons = new Buttons();
        //JPanel buttons = new JPanel();
        buttons.setOpaque(false);

        buttons.add(new MouseoverPanel("Queen", QUEEN_IMG, QUEEN_IMG_H));
        buttons.add(new MouseoverPanel("King", KING_IMG, KING_IMG_H));
        buttons.add(new MouseoverPanel("Rook", ROOK_IMG, ROOK_IMG_H));
        buttons.add(new MouseoverPanel("Knight", KNIGHT_IMG, KNIGHT_IMG_H));
        buttons.add(new MouseoverPanel("Pawn", PAWN_IMG, PAWN_IMG_H));

        background.add(buttons);

        frame.setContentPane(background);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class MouseoverPanel extends JPanel {
        JLabel button;
        JLabel hoverImage;
        JLabel icon;

        MouseoverPanel(String text, Image img, Image hImg) {
            setLayout(new OverlayLayout(this));
            setOpaque(false);

            button = new JLabel(text);
            button.setOpaque(false);
            button.setAlignmentX(0.5f);
            button.setAlignmentY(0.5f);
            button.setVisible(false);

            hoverImage = new JLabel(new ImageIcon(hImg));
            hoverImage.setOpaque(false);
            hoverImage.setAlignmentX(0.5f);
            hoverImage.setAlignmentY(0.5f);
            hoverImage.setVisible(false);

            icon = new JLabel(new ImageIcon(img));
            icon.setOpaque(false);
            icon.setAlignmentX(0.5f);
            icon.setAlignmentY(0.5f);

            add(button);
            add(hoverImage);
            add(icon);

            MouseoverListener ml = new MouseoverListener();

            addMouseListener(ml);
            button.addMouseListener(ml);
            icon.addMouseListener(ml);
        }

        class MouseoverListener extends MouseAdapter {
            @Override
            public void mouseEntered(MouseEvent e) {
                button.setVisible(true);
                hoverImage.setVisible(true);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                button.setVisible(false);
                hoverImage.setVisible(false);
            }
        }
    }

    class Buttons extends JPanel {
        public Buttons() {
            setOpaque(false);
            setBorder(new LineBorder(Color.BLACK));
        }
        @Override
        protected void paintComponent(Graphics g) {
            g.setColor(new Color(0, 0, 0, 100));
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }

    class Background extends JPanel {
        private BufferedImage sprite = null;

        public Background() {
            try {
                sprite = ImageIO.read(new URL("https://i.stack.imgur.com/XZ4V5.jpg"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Image scaledImage = sprite.getScaledInstance(getWidth(), getHeight(), Image.SCALE_REPLICATE);
            g.drawImage(scaledImage, getWidth() / 2 - scaledImage.getWidth(this) / 2, getHeight() / 2 - scaledImage.getHeight(this) / 2, this);
        }
    }

    static final Image QUEEN_IMG,
            QUEEN_IMG_H,
            KING_IMG,
            KING_IMG_H,
            ROOK_IMG,
            ROOK_IMG_H,
            KNIGHT_IMG,
            KNIGHT_IMG_H,
            PAWN_IMG,
            PAWN_IMG_H;

    static {
        try {
            // source for sprite sheet: https://stackoverflow.com/a/19209651/2891664
            BufferedImage sprites = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
            int n = 64;
            QUEEN_IMG = sprites.getSubimage(0 * n, 0, n, n);
            QUEEN_IMG_H = sprites.getSubimage(0 * n, 64, n, n);
            KING_IMG = sprites.getSubimage(1 * n, 0, n, n);
            KING_IMG_H = sprites.getSubimage(1 * n, 64, n, n);
            ROOK_IMG = sprites.getSubimage(2 * n, 0, n, n);
            ROOK_IMG_H = sprites.getSubimage(2 * n, 64, n, n);
            KNIGHT_IMG = sprites.getSubimage(3 * n, 0, n, n);
            KNIGHT_IMG_H = sprites.getSubimage(3 * n, 64, n, n);
            PAWN_IMG = sprites.getSubimage(4 * n, 0, n, n);
            PAWN_IMG_H = sprites.getSubimage(4 * n, 64, n, n);
        } catch (IOException x) {
            throw new UncheckedIOException(x);
        }
    }


}

我在悬停时制作的小项目:https://www.dropbox.com/s/wq4ggufbxrfcvb8/HoverButton.zip?dl=0

1 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法可能是使用已设置为良好行为的CardLayout

这是一个MCVE。

mouseover panels MCVE screenshot

package mcve;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;

public class MouseoverPanels {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(MouseoverPanels::new);
    }

    MouseoverPanels() {
        JFrame frame = new JFrame("Mouseover Panels");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel buttons = new JPanel();
        buttons.setBackground(Color.WHITE);

        buttons.add(new MouseoverPanel("Queen",  QUEEN_IMG));
        buttons.add(new MouseoverPanel("King",   KING_IMG));
        buttons.add(new MouseoverPanel("Rook",   ROOK_IMG));
        buttons.add(new MouseoverPanel("Knight", KNIGHT_IMG));
        buttons.add(new MouseoverPanel("Pawn",   PAWN_IMG));

        frame.setContentPane(buttons);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class MouseoverPanel extends JPanel {
        static final String BUTTON_KEY = "BUTTON";
        static final String ICON_KEY   = "ICON";

        final CardLayout layout = new CardLayout();

        MouseoverPanel(String text, Image img) {
            setLayout(layout);
            setOpaque(false);

            JButton button = new JButton(text);
            button.setBorderPainted(false);
            button.setOpaque(false);

            JLabel icon = new JLabel(new ImageIcon(img));
            icon.setOpaque(false);

            add(button, BUTTON_KEY);
            add(icon,   ICON_KEY);

            layout.show(this, ICON_KEY);

            MouseoverListener ml = new MouseoverListener();

            addMouseListener(ml);
            button.addMouseListener(ml);
            icon.addMouseListener(ml);
        }

        class MouseoverListener extends MouseAdapter {
            @Override
            public void mouseEntered(MouseEvent e) {
                recomputeView(e);
            }
            @Override
            public void mouseExited(MouseEvent e) {
                recomputeView(e);
            }
            void recomputeView(MouseEvent e) {
                Component comp = e.getComponent();
                Point     loc  = SwingUtilities.convertPoint(comp, e.getPoint(), MouseoverPanel.this);
                String    key  = contains(loc) ? BUTTON_KEY : ICON_KEY;
                layout.show(MouseoverPanel.this, key);
            }
        }
    }

    static final Image QUEEN_IMG,
                       KING_IMG,
                       ROOK_IMG,
                       KNIGHT_IMG,
                       PAWN_IMG;
    static {
        try {
            // source for sprite sheet: https://stackoverflow.com/a/19209651/2891664
            BufferedImage sprites = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
            int n = 64;
            QUEEN_IMG  = sprites.getSubimage(0 * n, 0, n, n);
            KING_IMG   = sprites.getSubimage(1 * n, 0, n, n);
            ROOK_IMG   = sprites.getSubimage(2 * n, 0, n, n);
            KNIGHT_IMG = sprites.getSubimage(3 * n, 0, n, n);
            PAWN_IMG   = sprites.getSubimage(4 * n, 0, n, n);
        } catch (IOException x) {
            throw new UncheckedIOException(x);
        }
    }
}

我认为您看到的性能可能可能,因为调用setVisible may cause revalidate to be called会调用布局管理器,但很难肯定,特别是没有合适的MCVE({ {3}})。

这是另一个通过自定义绘画实现此目的的示例。像这样的方法应该更容易动画。这可能通常不可行,除了我们在这里处理的唯一“真实”组件是文本本身。

see

package mcve;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class MouseoverPanels2 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(MouseoverPanels2::new);
    }

    MouseoverPanels2() {
        JFrame frame = new JFrame("Mouseover Panels");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel buttons = new JPanel();
        buttons.setBackground(Color.WHITE);

        buttons.add(new MouseoverLabel("Queen",  QUEEN_IMG,  QUEEN_IMG_H));
        buttons.add(new MouseoverLabel("King",   KING_IMG,   KING_IMG_H));
        buttons.add(new MouseoverLabel("Rook",   ROOK_IMG,   ROOK_IMG_H));
        buttons.add(new MouseoverLabel("Knight", KNIGHT_IMG, KNIGHT_IMG_H));
        buttons.add(new MouseoverLabel("Pawn",   PAWN_IMG,   PAWN_IMG_H));

        frame.setContentPane(buttons);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class MouseoverLabel extends JComponent {
        final JLabel label;
        final Image image, hover;

        final Dimension imageMaxSize;

        boolean isHovering = false;

        MouseoverLabel(String text, Image image, Image hover) {
            setLayout(new BorderLayout());
            setOpaque(false);

            this.image = Objects.requireNonNull(image);
            this.hover = Objects.requireNonNull(hover);

            imageMaxSize =
                new Dimension(Math.max(image.getWidth(this), hover.getWidth(this)),
                              Math.max(image.getHeight(this), hover.getHeight(this)));

            label = new JLabel(text);
            label.setForeground(Color.RED);
            label.setOpaque(false);
            label.setHorizontalAlignment(JLabel.CENTER);
            add(label, BorderLayout.CENTER);

            MouseoverListener ml = new MouseoverListener();

            addMouseListener(ml);
            label.addMouseListener(ml);
        }

        private Dimension getMax(Dimension size) {
            size.width = Math.max(size.width, imageMaxSize.width);
            size.height = Math.max(size.height, imageMaxSize.height);
            return size;
        }

        @Override
        public Dimension getPreferredSize() {
            return getMax(super.getPreferredSize());
        }
        @Override
        public Dimension getMinimumSize() {
            return getMax(super.getMinimumSize());
        }
        @Override
        public Dimension getMaximumSize() {
            return getMax(super.getMaximumSize());
        }

        @Override
        protected void paintChildren(Graphics g) {
            // Note that the label is always "visible",
            // so it will e.g. receive mouse events even
            // while we aren't painting it.
            // If the label needs to receive, say, mouse
            // clicks, then you need to check isHovering
            // in the mouse click listener.
            // If the label is a JButton, then you could
            // call button.setEnabled(isHovering) in the
            // MouseoverListener.
            if (isHovering) {
                paintImage(g, hover);
                super.paintChildren(g);
            } else {
                paintImage(g, image);
            }
        }

        private void paintImage(Graphics g, Image image) {
            int w = image.getWidth(this);
            int h = image.getHeight(this);
            int x = (getWidth() - w) / 2;
            int y = (getHeight() - h) / 2;
            g.drawImage(image, x, y, w, h, this);
        }

        class MouseoverListener extends MouseAdapter {
            @Override
            public void mouseEntered(MouseEvent e) {
                recomputeView(e);
            }
            @Override
            public void mouseExited(MouseEvent e) {
                recomputeView(e);
            }
            void recomputeView(MouseEvent e) {
                Component comp = e.getComponent();
                Point     loc  = SwingUtilities.convertPoint(comp, e.getPoint(), MouseoverLabel.this);
                isHovering     = contains(loc);
                repaint();
            }
        }
    }

    static final Image QUEEN_IMG,
                       QUEEN_IMG_H,
                       KING_IMG,
                       KING_IMG_H,
                       ROOK_IMG,
                       ROOK_IMG_H,
                       KNIGHT_IMG,
                       KNIGHT_IMG_H,
                       PAWN_IMG,
                       PAWN_IMG_H;
    static {
        try {
            // source for sprite sheet: https://stackoverflow.com/a/19209651/2891664
            BufferedImage sprites = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
            int n = 64;
            QUEEN_IMG    = sprites.getSubimage(0 * n, 0, n, n);
            QUEEN_IMG_H  = sprites.getSubimage(0 * n, n, n, n);
            KING_IMG     = sprites.getSubimage(1 * n, 0, n, n);
            KING_IMG_H   = sprites.getSubimage(1 * n, n, n, n);
            ROOK_IMG     = sprites.getSubimage(2 * n, 0, n, n);
            ROOK_IMG_H   = sprites.getSubimage(2 * n, n, n, n);
            KNIGHT_IMG   = sprites.getSubimage(3 * n, 0, n, n);
            KNIGHT_IMG_H = sprites.getSubimage(3 * n, n, n, n);
            PAWN_IMG     = sprites.getSubimage(4 * n, 0, n, n);
            PAWN_IMG_H   = sprites.getSubimage(4 * n, n, n, n);
        } catch (IOException x) {
            throw new UncheckedIOException(x);
        }
    }
}