Как сделать фон ImageIcon прозрачным в JLabel - PullRequest
0 голосов
/ 21 марта 2019

Я хочу поместить изображение на другое изображение, используя JLabels и ImageIcon. Все работает, но я не мог понять, как сделать фон изображения прозрачным. По сути, я хочу запрограммировать игру, но я не хочу, чтобы игрок был идеальным прямоугольником. Вот мой код, который работает до сих пор:

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Game {
    JFrame frame = new JFrame();
    JLabel label1 = new JLabel();
    JLabel label2 = new JLabel();

    public Game() {
        frame.setVisible(true);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setTitle("just a test");
        frame.setResizable(true);
        frame.getContentPane().setLayout(null);
        frame.setBounds(400, 200, 915, 600);

        label1.setBounds(0, -195, 900, 890);
        label2.setBounds(50, 200, 260, 240);

        frame.getContentPane().add(label2);
        frame.getContentPane().add(label1);

        ImageIcon icon1 = new ImageIcon("icons/landscape.png");
        ImageIcon icon2 = new ImageIcon("icons/mario1.png");

        label1.setIcon(icon1);
        label2.setIcon(icon2);
    }
    public static void main(String[] args) {
        Game game = new Game();

    }
}

Ответы [ 2 ]

1 голос
/ 22 марта 2019

JLabel по своей природе прозрачен - то есть его непрозрачное свойство по умолчанию равно false (в отличие от JPanel, который по умолчанию непрозрачен), и поэтому, если вы поместите прозрачное изображение в ImageIcon и сделаете его иконкой JLabel через .setIcon(...) и добавьте JLabel в контейнер, такой как JPanel, прозрачные области отображаемого значка останутся прозрачными, показывая фоновое изображение. Например, для этого изображения в виде спрайта отображается закрашенный круг с прозрачными пикселями вокруг него:

enter image description here

Таким образом, если к JLabel добавлен слушатель мыши, его можно перетаскивать вокруг контейнера.

например.,

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

@SuppressWarnings("serial")
public class SpriteOnBackground extends JPanel {
    // Image attribution:
    // By Adam Evans - M31, the Andromeda Galaxy (now with h-alpha)
    // Uploaded by NotFromUtrecht, CC BY 2.0, 
    // https://commons.wikimedia.org/w/index.php?curid=12654493
    public static final String ANDROMEDA_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
            + "thumb/9/98/Andromeda_Galaxy_%28with_h-alpha%29.jpg/"
            + "1280px-Andromeda_Galaxy_%28with_h-alpha%29.jpg";
    public static final String SPRITE_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
            + "thumb/a/a1/Glossy_3d_blue_blue2.png/"
            + "120px-Glossy_3d_blue_blue2.png";
    private Image background;
    private JLabel spriteLabel = new JLabel();

    public SpriteOnBackground(Image bg, Image spriteImg) {
        background = bg;
        spriteLabel.setIcon(new ImageIcon(spriteImg));
        spriteLabel.setSize(spriteLabel.getPreferredSize());
        setLayout(null);
        add(spriteLabel);

        MyMouse myMouse = new MyMouse();
        spriteLabel.addMouseListener(myMouse);
        spriteLabel.addMouseMotionListener(myMouse);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet() || background == null) {
            return super.getPreferredSize();
        }
        // make JPanel the size of the image
        int w = background.getWidth(this);
        int h = background.getHeight(this);
        return new Dimension(w, h);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // draw background image
        g.drawImage(background, 0, 0, this);
    }

    // mouse listener to drag the JLabel around the GUI
    private class MyMouse extends MouseAdapter {
        private Point p1;
        private Point pSprite;

        @Override
        public void mousePressed(MouseEvent e) {
            p1 = e.getLocationOnScreen();
            pSprite = spriteLabel.getLocation();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (p1 != null) {
                moveSprite(e);
            }
        }

        private void moveSprite(MouseEvent e) {
            Point p2 = e.getLocationOnScreen();
            int x = pSprite.x + p2.x - p1.x;
            int y = pSprite.y + p2.y - p1.y;
            Point newP = new Point(x, y);
            spriteLabel.setLocation(newP);
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (p1 != null) {
                moveSprite(e);
            }
            p1 = null;
        }
    }

    private static void createAndShowGui() {
        SpriteOnBackground mainPanel = null;
        try {
            URL backgroundUrl = new URL(ANDROMEDA_IMAGE);
            Image backGroundImg = ImageIO.read(backgroundUrl);

            URL spriteUrl = new URL(SPRITE_IMAGE);
            Image spriteImg = ImageIO.read(spriteUrl);
            mainPanel = new SpriteOnBackground(backGroundImg, spriteImg);
        } catch (IOException e) {
            e.printStackTrace();
        }

        JFrame frame = new JFrame("Sprite On Background");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}
1 голос
/ 21 марта 2019

Я рекомендую то же самое, что и Hovercraft Full Of Eels, хотя я объясню причины этого.В соответствии с вашей настройкой, ваша JLabel заполняет все прозрачные пиксели непрозрачным цветом.Неважно, имеет ли mario1.png прозрачный фон, поскольку JLabel, в котором он реализован, заполняет прозрачные пиксели цветом фона.Есть два возможных исправления этого.Используйте исключительную JLabel, как предлагает Hovercraft, или используйте вместо этого JComponent.Я бы порекомендовал использовать последнее, как если бы вы программировали игру, тогда вы бы не хотели, чтобы ваш спрайт Mario перемещался вместе с фоном, и у вас больше общего контроля с классом JComponent в ваших текущих обстоятельствах.

Вот документ Oracle для класса JComponent: https://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html

Я хотел бы дать вам упрощенный пример кода, если вы того пожелаете.

...