Установить фоновое изображение для JPanel в Java Breakout Game

Хорошо, это кажется очень простой задачей, но я не могу ее понять. Все, что я хочу, это иметь изображение (jpg) в качестве фона для моей игры прорыва. Вот мой код:

Основной класс:

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class Breakout extends JFrame {

    public Breakout()
    {             
        add(new BreakBoard());
        setTitle("Breakout");
        setSize(BreakCommons.WIDTH, BreakCommons.HEIGTH);
        setLocationRelativeTo(null);
        setIgnoreRepaint(true);
        setResizable(false);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Breakout();
    }
}

Класс доски:

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class BreakBoard extends JPanel implements BreakCommons {

    ImageIcon icon = new ImageIcon("../pacpix/love.jpg"); 
    Timer timer;
    String message = "Game Over";
    BreakBall ball;
    BreakPaddle paddle;
    BreakBrick bricks[];
    boolean ingame = true;
    int timerId;


    public BreakBoard() {
        setOpaque(false);
        addKeyListener(new TAdapter());
        setFocusable(true);
        //setBackground(Color.white);
        bricks = new BreakBrick[30];
        setDoubleBuffered(true);
        timer = new Timer();
        timer.scheduleAtFixedRate(new ScheduleTask(), 1000, 10);
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(icon.getImage(), 10, 10, this);

        if (ingame) {
            g.drawImage(ball.getImage(), ball.getX(), ball.getY(),
                        ball.getWidth(), ball.getHeight(), this);
            g.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(),
                        paddle.getWidth(), paddle.getHeight(), this);

            for (int i = 0; i < 30; i++) {
                if (!bricks[i].isDestroyed())
                    g.drawImage(bricks[i].getImage(), bricks[i].getX(),
                                bricks[i].getY(), bricks[i].getWidth(),
                                bricks[i].getHeight(), this);
            }
        } else {

            Font font = new Font("Verdana", Font.BOLD, 18);
            FontMetrics metr = this.getFontMetrics(font);

            g.setColor(Color.BLACK);
            g.setFont(font);
            g.drawString(message,
                         (BreakCommons.WIDTH - metr.stringWidth(message)) / 2,
                         BreakCommons.WIDTH / 2);
        }


        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }

Таким образом, изображение хранится в переменной icon и находится в моих исходных файлах (вместе с моими классами), поэтому я знаю, что путь правильный. Я попытался установить рамку и панель на setOpaque(false), но это просто изменило фон на серый по умолчанию. Я могу легко установить цвет фона с помощью setBackground(Color.white);, но как установить изображение?

Я попытался поместить изображение в JLabel, а затем добавить его в JPanel, но это не дало никаких результатов. Буду признателен за любую помощь, и заранее спасибо! Я могу предоставить дополнительную информацию по мере необходимости.


person CodeAddict    schedule 18.03.2013    source источник


Ответы (4)


простой способ сначала создать отдельный класс для jpane

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class JPanelDemo extends JPanel {
    /**
     * 
     */
     private static final long serialVersionUID = 1L;
     private static final Color BACKGROUND      = Color.black;
     private static final Color BACKGROUND_2    = Color.WHITE;
     String path="/img/background.jpg";

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D graphics = (Graphics2D) g.create();        
        int midY = 100;
        Paint topPaint = new GradientPaint(0, 0, BACKGROUND,0, midY, BACKGROUND_2);
        graphics.setPaint(topPaint);
        graphics.fillRect(0, 0, getWidth(), midY);        
        Paint bottomPaint = new GradientPaint(0, midY + 1, BACKGROUND_2,0, getHeight(), BACKGROUND);
        graphics.setPaint(bottomPaint);
        graphics.fillRect(0, midY, getWidth(), getHeight());
        Image img = new ImageIcon(getClass().getResource(path)).getImage();
        int imgX = img.getWidth(null);
        int imgY = img.getHeight(null);
        graphics.drawImage(img, (getWidth() - imgX) / 2, (getHeight() - imgY) / 2, imgX, imgY, null);
      //  graphics.dispose();
    }
}

как это использовать

JPanelDemo contentPane = new JPanelDemo();
person Adel    schedule 03.08.2013

Это JPanel с фоновым изображением. Используйте IPanel вместо JPanel в своем коде. Настройте по мере необходимости в соответствии с вашими потребностями.

public class IPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Image             imageOrg         = null;
private Image             image            = null;
{
    addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(final ComponentEvent e) {
            final int w = IPanel.this.getWidth();
            final int h = IPanel.this.getHeight();
            image = w > 0 && h > 0 ? imageOrg.getScaledInstance(w, h, Image.SCALE_SMOOTH) : imageOrg;
            IPanel.this.repaint();
        }
    });
}

public IPanel(final Image i) {
    imageOrg = i;
    image = i;
}

@Override
public void paintComponent(final Graphics g) {
    super.paintComponent(g);
    if (image != null)
        g.drawImage(image, 0, 0, null);
}
}

Пример:

    final JPanel j = new IPanel(image);
    j.setLayout(new FlowLayout());
    j.add(new JButton("YoYo"));
    j.add(new JButton("MaMa"));
    j.add(new JLabel(icon));

Производит:

введите здесь описание изображения

person Java42    schedule 18.03.2013
comment
не могли бы вы объяснить, что это делает/как это вписывается в мой код? - person CodeAddict; 18.03.2013
comment
Это JPanel с фоновым изображением. Используйте IPanel вместо JPanel в своем коде. Подправьте по мере необходимости. - person Java42; 18.03.2013
comment
это не работает. и я так запутался, куда бы я мог положить это? В моем коде действительно нет места для этого, что я вижу. Не могли бы вы объяснить логику вашего кода? - person CodeAddict; 18.03.2013
comment
@CodeAddict - Теперь я в замешательстве ... Вы говорите, что это не работает, но все же не знаете, где его использовать. Этот код представляет собой JPanel с фоновым изображением. Называется IPanel. Вместо стандартной JPanel используйте эту IPanel. Возможно, вам придется внести несколько изменений, например добавить CTOR с нулевым аргументом и setter() для изображения. Тогда, возможно, замените BreakBoard extends JPanel на BreakBoard extends IPanel. Смотрите пример в моем ответе. Поместите это в метод main() для тестирования. Надеюсь это поможет. - person Java42; 18.03.2013
comment
Ха-ха, я пытался поместить это в свой код, и это не сработало, вот почему. Так что используйте IPanel вместо JPanel. Работает ли IPanel так же, как JPanel? Я действительно думал, что это проще, максимум пять строк кода. Вау хД - person CodeAddict; 18.03.2013
comment
@CodeAddict - Да - это работает так же + немного больше - Когда вы видите, что открытый класс IPanel расширяет JPanel, это означает, что JPanel является суперклассом, а IPanel получает все (обычно) функциональные возможности (состояние и поведение) суперкласса. Лучше всего запустить только IPanel в main(), чтобы увидеть, как он работает, а затем адаптировать его или его функцию в вашей программе. - person Java42; 18.03.2013

Наконец-то я заработал!

public class BreakBoard extends JPanel implements BreakCommons {
    Image love;

    public BreakBoard() {
        ImageIcon icon = new ImageIcon(this.getClass().getResource("../pacpix/love.jpg"));
        love = icon.getImage();
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(love, 10, 10, null); 
    }
}

Для будущих поисков или тех, кому интересно, я использовал http://zetcode.com/tutorials/javagamestutorial/basics /. Отличный сайт для начинающих! (Или те, которые нужно отупить, чтобы понять)

person CodeAddict    schedule 18.03.2013
comment
Примите это как правильное решение, чтобы другие видели его при поиске :) - person JBuenoJr; 27.07.2013
comment
даже если кажется, что это работает - переопределение paint является неправильным подходом в Swing: вместо этого переопределяйте paintComponent - person kleopatra; 17.10.2013

person    schedule
comment
ничего нового по сравнению с предыдущими ответами, не так ли? То есть кроме того, что вы внесли как минимум две ошибки и сделали его менее универсальным... - person kleopatra; 20.01.2014