【问题标题】:drawImage() on JPanel OR add Image on top of GridLayoutJPanel 上的 drawImage() 或在 GridLayout 顶部添加图像
【发布时间】:2014-05-18 12:49:01
【问题描述】:

我有一个 100 x 100 的标签网格。我有一个创建和填充字符串数组的方法。下一个方法创建一个标签数组,然后使用 setText() 方法将字符串(从上一个方法创建)添加到标签中。一些标签也包含图像。之后的方法采用这些 JLabels 并将它们添加到网格布局的 JPanel(让我们称之为 x1)。然后我将 JPanel 添加到 JScrollPane(x2),JScrollPane 被添加到另一个具有空边框的 JPanel(x3),最后的 JPanel(x3) 被添加到 JFrame。这就是我创建网格的方式,对此我很满意,我不想更改它。

我想将图像添加到 x1 - 带有网格布局的 JPanel。 为此,我必须添加 paintComponent 方法并使用 drawImage() 方法。我的问题是 Eclipse 如何知道将图像添加到哪个面板?我不想为 x1 创建一个单独的类,我以前做过,但效果不好,我不想再走那条令人难以置信的令人沮丧的道路,对不起!

我曾考虑使用 Glass Pane,但是我将无法再看到 JLabels 的图像 - 这非常重要。

我认为将图像添加到 JPanel 的背景将是最好的,因为我还想要一个显示/隐藏网格线的按钮 - JLabels 的边框。

我希望我说得通。

下面是代码。我知道一个类中有很多代码。我确实在两个单独的课程中拥有它,但它对我不起作用。我觉得这更容易。希望你不要介意

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));


    }

}

非常感谢!我非常感谢任何帮助或建议:D

【问题讨论】:

    标签: java image swing jpanel grid-layout


    【解决方案1】:

    正如你所说,你需要做的是覆盖 JPanel 的 paintComponent 方法并在那里放置一个 drawImage(...) 。所以:

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

    其中image 是您之前在初始化代码中加载的类Image 的一个实例(不要在paintComponent 中加载它,那样会太慢而且您只想加载一次)。

    有两种方法可以做到这一点:

    • 创建您自己的扩展JPanel 的类并将该代码放在那里。您可能还需要创建一个方法 setBackgroundImage(Image),您可以从主类调用该方法来传递您从磁盘加载的图像。

    • 创建一个anonymous class,它正在做类似的事情,但没有明确定义一个新类。这样做而不是像这样创建面板:

      JPanel gridPanel = new JPanel();
      

      这样做:

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

    当然,您必须在实际代码中执行此操作(而不是作为静态初始化),因为您要确保之前加载图像。

    最后几点建议:

    • 按照约定,变量名以小写字母开头(与以大写字母开头的类名相反)。例如,您不会在 JPanel Grid 参数和 Comands 字段中执行此操作。

    • 您违反了 Swing 的单线程规则。也就是说,您必须在主包装 GUI 初始化代码时调用 invokeLater。例如查看 Swing 的Hello World。你可以找到这个here的详细解释。

    【讨论】:

    • 非常感谢,效果很好 :D 也是的,我知道小写/大写约定,我只有几个大写字母,因为我更容易找到它们在所有这些代码行之间。最后,我根据 Swing 的规则修改了我的主要方法。再次感谢!!
    • @user3649285 很高兴我能帮上忙!无论如何,您必须对创建多个类感到满意,这并不难,而是让您的代码更加清晰和可扩展。
    • 我知道,你是对的!我同意你的看法,我同意,只是这个项目明天到期,仅此而已。否则,我最初从两个布局类开始。再次感谢:))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 2014-06-08
    • 1970-01-01
    相关资源
    最近更新 更多