Показать несколько изображений JPane на одном JFrame - PullRequest
0 голосов
/ 30 марта 2020

Прежде всего, я новичок в JFrame и во всех связанных классах, поэтому я все еще учусь, как это делать. Моя текущая цель - нарисовать несколько изображений на одном JFrame. Пока я могу нарисовать test2.png, но не test1.png. Любые предложения или помощь в понимании JFrame приветствуется. Это мой основной класс:

package com.osj.oneshotjava;

import java.awt.Dimension;
import javax.swing.JFrame;

/**
 *
 * @author BCG04
 */
public class actorTest {
   public static void main(String []args){
      JFrame jFrame = new JFrame("OSJ actor test");
      jFrame.setPreferredSize(new Dimension(640, 480));                    // sets window size
      jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Actor2 Background = new Actor2(jFrame, "test1.png");
      Actor2 testActor = new Actor2(jFrame, "test2.png");
      jFrame.pack();                                                     // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
      jFrame.setVisible(true);
   }
}

А это Actor2:

package com.osj.oneshotjava;

import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 *
 * @author BCG04
 */
public class Actor2 {                     //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
    private BufferedImage image = null;
private JLabel jLabel = null;
   public Actor2(JFrame jFrame, String filename){
      try                                                                      
        {                                                                       // try to load a image 'filename' into 'image'
          image = ImageIO.read(new File(filename));                              
        }                                                                       
        catch (Exception e)                                                      
        {                                                                       
          e.printStackTrace();                                                  // if loading fails, print the error
          System.exit(1);                                                       // then exit with an error code 1 'unsuccessful exit'
        }
        ImageIcon imageIcon = new ImageIcon(image);                             // create a new ImageIcon that contains 'image'
        JPanel jPanel = new JPanel();
        jLabel = new JLabel();
        jLabel.setIcon(imageIcon);                                              // set JLabel 'jLabel' to contain 'imageIcon'
        jPanel.add(jLabel);
        jFrame.getContentPane().add(jPanel, BorderLayout.CENTER);               // makes window visible?

   }

   public JLabel getJLabel(){
      return jLabel;
   }
}

Редактировать: -removed Thread.sleep(1000); и setLocation(90, 90);, поскольку они не имеют отношения к вопросу или проблема, и у меня изначально были их, чтобы проверить, могу ли я перемещать изображения.

-removed jLabel.setBounds, поскольку он, похоже, ничего не делал.

+ добавил комментарий, разъясняющий цель Actor2.

Я бы хотел уточнить конечную цель, я хотел бы создать простую 2d игру, в которой используется Java.

1 Ответ

0 голосов
/ 31 марта 2020

Вот полный, самостоятельный пример, близкий к тому, что вы ищете. Это демонстрирует использование менеджера компоновки.

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

public class DuelingJLabels{

    public static void startGui(){
        JFrame frame = new JFrame();
        JPanel scene = new JPanel();
        Actor red = new Actor(Color.RED);
        Actor blue = new Actor(Color.BLUE);
        //scene.setLayout( null );
        scene.add(red.image);
        scene.add(blue.image);
        //scene.setPreferredSize( new Dimension(512, 512) );

        frame.add(scene, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    static class Actor{
        int x, y;
        JLabel image;
        public Actor(Color c){
            BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
            Graphics g = a.getGraphics();
            g.setColor(c);
            g.fillOval(0, 0, 64, 64);
            image = new JLabel();
            image.setIcon(new ImageIcon(a));
            image.setLocation( x, y );
            image.setSize( 64, 64);
            image.addMouseListener( new MouseAdapter(){
                @Override
                public void mouseClicked(MouseEvent evt){
                    x = x+64;
                    if(x>=448){
                        x = 0;
                        y += 64;
                    }
                    image.setLocation(x, y);
                }
            });
        }
    }

    public static void main(String[] args){
        EventQueue.invokeLater( DuelingJLabels::startGui );
    }
}

Обратите внимание на строку scene.setLayout(null); Если вы запустите пример с закомментированной строкой, то вы увидите два круга рядом. Это потому, что мы позволяем Swing управлять макетом. scene - это JPanel с FlowLayout по умолчанию.

Теперь, когда вы нажимаете на кружки, ничего не происходит *, потому что мы сообщаем новую позицию, но менеджер компоновки сбрасывает позицию. * На самом деле они иногда перемещаются, но если вы инициируете повторную проверку, диспетчер макета перемещает их.

Так что теперь удалите комментарий к scene.setLayout(null); и обратите внимание на разницу.

  1. Рамка крошечная, и мы должны вручную изменить ее размер, чтобы увидеть нашу сцену.
  2. Есть только один круг.
  3. Если вы нажмете на круг, он начнет двигаться.

Это потому, что мы сказали Swing не использовать менеджер макетов для сцены JPanel. Это означает, что он не будет перемещать компоненты в сцене для нас, и он также не будет корректировать размеры для нас.

Другая закомментированная строка setPreferredSize заставляет сцену сообщать родительскому компоненту размер, по которому она будет нравится быть в. Если вы раскомментируете эту строку, то JFrame не станет невероятно маленьким. Вы должны использовать это только с пользовательскими компонентами, в противном случае вы можете столкнуться с конфликтом с менеджером макета.

Другой инструмент, который я нашел полезным, это JLayeredPane , потому что он дает вам некоторую глубину. Я также думаю, что пример хорош.

Наконец, еще один метод произвольного размещения произвольной графики - это @Override paintComponent. Таким образом, вы можете нарисовать что угодно и где угодно на вашем компоненте.

...