简体   繁体   中英

drawImage() on JPanel OR add Image on top of GridLayout

I have a 100 by 100 grid of labels. I've got a method which creates and populates an array of Strings. The next method creates an array of labels and then adds the String (created from previous method) to the labels using the setText() method. Some of the labels contain images too. Method after that takes those JLabels and adds them to a JPanel of Grid Layout(lets call this x1). Then I've added the JPanel to a JScrollPane(x2), the JScrollPane gets added to another JPanel(x3) with an empty border and this final JPanel(x3) gets added to the JFrame. So that's how I've created the grid and I'm happy with that, I don't want to change it.

I would like to add an image to x1 - the JPanel with Grid Layout. For this I would have to add the paintComponent method and use the drawImage() method. My question is how will Eclipse know which panel to add the image to? I's prefer not to create a separate class for x1, I did that before and it just didn't work out right and I rather not go down that incredibly frustrating road again, I'm sorry!

I have considered using a Glass Pane however I would no longer be able to see the images of the JLabels - which is really important.

I think adding the image to the background of the JPanel will be best because I also want to have a button which shows/hides the grid lines - the borders of the JLabels.

I hope I'm making sense.

Below is the code. I understand it's a lot of code in one class. I did have it in two separate classes but it just didn't work me. I find this much easier. I hope you don't mind

package roverMars;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

public class MenuPanel extends JPanel {

    private static final long serialVersionUID = -3928152660110599311L;

    public JPanel frame, textfield, buttons, cpPanel;
    public JTextField Commands;
    public JButton Plot, Submit, Undo;
    public JLabel Position, cpLabel;
    public Border loweredetched;
    public JCheckBox gridLines;

    public SubmitButton sub;

    static final int rows = 100, columns = 100;

    // ******IMAGES******
    static BufferedImage North, South, West, East;

    public void ImageLoader() {

        try {
            North = ImageIO.read(this.getClass().getResource("North.png"));
            South = ImageIO.read(this.getClass().getResource("South.png"));
            West = ImageIO.read(this.getClass().getResource("West.png"));
            East = ImageIO.read(this.getClass().getResource("East.png"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("Error occured: " + e);
            e.printStackTrace();
        }
    }

    // ******IMAGES******

    public void createMenu(JPanel p) {


        // Text Field Panel
        Commands = new JTextField(20);
        textfield = new JPanel();
        textfield.setPreferredSize(new Dimension(150, 50));
        textfield.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        textfield.setBackground(new Color(204, 153, 255));
        textfield.add(Commands);

        // Have a button next to the Text Field to clear contents.
        // Might need to give the JPanel a new Flow Layout.


        // Buttons Panel
        buttons = new JPanel();
        buttons.setPreferredSize(new Dimension(150, 250));
        buttons.setLayout(new BoxLayout(buttons, BoxLayout.Y_AXIS));
        buttons.setBackground(new Color(170, 051, 170));

        // Create and Add buttons to the Buttons Panel
        buttons.add(Box.createRigidArea(new Dimension(30, 10)));
        Plot = new JButton("Plot");
        Plot.setAlignmentX(Component.CENTER_ALIGNMENT);
        Plot.setAlignmentY(Component.CENTER_ALIGNMENT);

        buttons.add(Plot);
        buttons.add(Box.createRigidArea(new Dimension(30, 10)));
        Submit = new JButton("Submit");
        Submit.setAlignmentX(Component.CENTER_ALIGNMENT);
        Submit.setAlignmentY(Component.CENTER_ALIGNMENT);

        Submit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                sub = new SubmitButton();
                sub.Submit(Commands);
                cpLabel.setText("*****SET CURRENT POSITION*****");
                labels[2][2].setIcon(new ImageIcon(North));

                // I will be able to move the rover from here using for loops
                // and if statements.

            }
        });

        buttons.add(Submit);
        buttons.add(Box.createRigidArea(new Dimension(30, 10)));
        Undo = new JButton("Undo");
        Undo.setAlignmentX(Component.CENTER_ALIGNMENT);
        Undo.setAlignmentY(Component.CENTER_ALIGNMENT);
        buttons.add(Undo);
        buttons.add(Box.createRigidArea(new Dimension(30, 10)));

        gridLines = new JCheckBox();
        gridLines.setText("Show gridlines");
        gridLines.setAlignmentX(Component.CENTER_ALIGNMENT);
        gridLines.setAlignmentY(Component.CENTER_ALIGNMENT);

        gridLines.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // Set the colour of the JLabels array from here.
                System.out.println("clicked");

            }
        });

        buttons.add(gridLines);
        buttons.add(Box.createRigidArea(new Dimension(30, 20)));


        loweredetched = BorderFactory
                .createEtchedBorder(EtchedBorder.RAISED);

        cpLabel = new JLabel("Current position: ", JLabel.CENTER);

        cpPanel = new JPanel();
        cpPanel.setBackground(new Color(153, 153, 204));
        cpPanel.add(cpLabel);
        cpPanel.setBorder(loweredetched);


        // Panel for the main window
        JPanel frame = new JPanel();
        frame.setPreferredSize(new Dimension(150, 350));
        frame.setLayout(new BorderLayout());
        frame.add(textfield, BorderLayout.NORTH);
        frame.add(buttons, BorderLayout.CENTER);


        // This Main Panel
        p.setPreferredSize(new Dimension(350, 700));
        p.setBackground(new Color(153, 153, 204));
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setBorder(BorderFactory.createEmptyBorder(10, 50, 10, 25));
        p.add(Box.createRigidArea(new Dimension(100, 100)));
        p.add(frame);
        p.add(Box.createRigidArea(new Dimension(15, 15)));
        p.add(cpPanel);
        p.add(Box.createRigidArea(new Dimension(100, 300)));
    }


    // From line 142 to 202 is everything to do with creating the Grid
    public void StringArray(String[][] labelText) {
        int x = 1; // increment rows

        for (int i = 0; i < labelText.length; i++) { // x
            for (int j = 0; j < labelText.length; j++) { // y
                labelText[i][j] = Integer.toString(x); // populate string
                x++;
            }
        }
    }

    public void JLabelArray(JLabel[][] label, String[][] labelText) {

        for (int i = 0; i < label.length; i++) { // x
            for (int j = 0; j < label.length; j++) { // y
                label[i][j] = new JLabel();
                label[i][j].setText(labelText[i][j]);
                label[i][j].setOpaque(false);
                label[i][j].setBorder(BorderFactory.createLineBorder(new Color(
                        0, 155, 200), 1));
                // label[i][j].setBackground(Color.WHITE);

            }
        }
    }

    public void populateGrid(JPanel Grid, JLabel[][] label) { // Add Labels to
                                                                // Panel,

        String x1[][] = new String[rows][columns];
        StringArray(x1);
        JLabelArray(label, x1);

        Grid.setBackground(Color.RED);

        int gHeight = label.length, gWidth = label.length;
        Grid.setLayout(new GridLayout(gWidth, gHeight));

        for (int i = 0; i < label.length; i++) { // x
            for (int j = 0; j < label.length; j++) { // y
                Grid.add(label[i][j]);

            }
        }
    }

    public void createGrid(JPanel finalPanel, JPanel Grid) {

        // Add Grid to Scroll Pane
        JScrollPane x4 = new JScrollPane(Grid);
        x4.setPreferredSize(new Dimension(600, 600)); // DO NOT DELETE THIS.
        x4.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        x4.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        // Add Scroll Pane to another Panel with the Border
        finalPanel.setBackground(new Color(153, 153, 204));
        finalPanel.setBorder(BorderFactory.createEmptyBorder(50, 25, 50, 50));
        finalPanel.add(x4);

    }

    // Variables for creaeteGUI method.
    static MenuPanel t = new MenuPanel();
    static JPanel menu = new JPanel();
    static JPanel finalPanel = new JPanel();
    static JPanel gridPanel = new JPanel();
    static JLabel labels[][] = new JLabel[rows][columns];

    public static void createGUI() {


        t.createMenu(menu);
        t.populateGrid(gridPanel, labels);
        t.createGrid(finalPanel, gridPanel);

        JFrame f = new JFrame();
        f.setTitle("Project Testing");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setLocation(100, 100);
        f.setAlwaysOnTop(true);
        f.setSize(500, 500);

        f.add(finalPanel, BorderLayout.CENTER);
        f.add(menu, BorderLayout.WEST);

        f.pack();

    }

    public static void main(String args[]) {

        createGUI();

        t.ImageLoader();
        labels[2][2].setIcon(new ImageIcon(West));


    }

}

Thank you so much! I really appreciate any help or suggestions :D

As you said what you need to do is to override the paintComponent method of the JPanel and put a drawImage(...) in there. So:

@Override
public void paintComponent(Graphics g)
{
    //super.paintComponent(g);
   g.drawImage(image, 0, 0, null);
}

Where image is an instance of the class Image that you loaded previously in the initialization code (don't load it in the paintComponent, that would be too slow and you only want to load it once).

There are 2 ways to accomplish that:

  • Make your own class extending JPanel and put that code there. You probably will want to create also a method setBackgroundImage(Image) that you can call from you main class to pass the image that you loaded from the disk.

  • Make an anonymous class , that is doing something similar but without explicitely defining a new class. To do so instead of creating the panel like this:

     JPanel gridPanel = new JPanel(); 

    do it like this:

     JPanel gridPanel = new JPanel() { @Override public void paintComponent(Graphics g) { //super.paintComponent(g); g.drawImage(image, 0, 0, null); } }; 

Of course you must do this in the actual code (not as an static initialization) since you want to make sure that you load the image before.

Finally a couple of suggestions:

  • Variable names start in lower case by convention (as opposite to class names that start in upper case). You don't do this for example in the JPanel Grid argument and Comands field.

  • You are violating Swing's single threading rule. That is, you must call invokeLater in your main wrapping your GUI initializing code. For example look at Swing's Hello World . You can find a detailed explanation of this here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM