java - 使用 JPanel 扩展类设置背景

标签 java swing jpanel drawimage

在我的 Main 中,我想创建一个 JFrame,然后我想创建一个 BackgroundPanel,并将其添加到 JFrame 中。

这是主要类:

public class Main {

    public static void main(String args[]) {
        Frame frame = new Frame();
        BackgroundPanel back = new BackgroundPanel();
        frame.getContentPane().add(back);
        frame.setSize(400, 287);
        frame.setVisible(true);
    }
}

这是BackgroundPanel类:

import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BackgroundPanel extends JPanel {

    private Image img;

    public BackgroundPanel() {
        img = Toolkit.getDefaultToolkit().createImage(getClass().getResource("sfondo.png"));
        loadImage(img);
    }

    private void loadImage(Image img) {
        try {
            MediaTracker track = new MediaTracker(this);
            track.addImage(img, 0);
            track.waitForID(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        setOpaque(false);
        g.drawImage(img, 0, 0, null);
    }
}

并且 JFrame 是一个普通的 JFrame 类。

当我执行它时,没有错误,只是输出了一个没有背景的正常 JFrame 。 请帮助我!

@nIcEcOw 我使用第一个答案中的代码在 JPanel 上打印我的图像。但是当我执行它时,输出出现错误。

这是错误:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(ImageIO.java:1388)
    at paintingexample.CustomPanel.<init>(PaintingExample.java:82)
    at paintingexample.PaintingExample.displayGUI(PaintingExample.java:28)
    at paintingexample.PaintingExample.access$000(PaintingExample.java:19)
    at paintingexample.PaintingExample$1.run(PaintingExample.java:42)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
BUILD SUCCESSFUL (total time: 1 second)

我对项目的结构感到困惑。 我注意到我无法将包文件夹放在 bin 目录中;这在我的想法中造成了冲突。 我不明白如何将 java 文件放在 src 中并将包文件夹放在 bin 目录中。 我的 java 文件位于包文件夹中..我该怎么做?

我正在使用 NetBeans IDE 8.0

我红色了 NetBean 的图像导入教程,其中还提示我创建另一个包来导入图像。 现在我的代码是:

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;

public class PaintingExample {

    private ImagePanel imagePanel;

    public void displayGUI() {
        JFrame frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        imagePanel = new ImagePanel();      
        contentPane.add(imagePanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new PaintingExample().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}


class ImagePanel extends JPanel {

    private ImageIcon imageIcon;

    public ImagePanel() {
        imageIcon = new javax.swing.ImageIcon(getClass().getResource("/org/me/myimageapp/newpackage/Schema elettrico divella rev 2014-Model.jpg"));
    }

    @Override
    public Dimension getPreferredSize() {
        return (imageIcon == null ? new Dimension(100, 100): new Dimension(
                                                   imageIcon.getIconWidth(), imageIcon.getIconHeight()));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(imageIcon.getImage(), 0, 0, this);
    }
}

我改变了:

imageIcon = new ImageIcon(ImageIO.read(ImagePanel.class.getResource(
                                                    "/images/aeroplaneright.jpeg")));

imageIcon = new javax.swing.ImageIcon(getClass().getResource("/org/me/myimageapp/newpackage/aeroplaneright.jpg"));

@nIcEcOw,你是我的英雄! :D 现在一切正常。 但还有一件事:

现在我正在一个更大的项目中使用您的 ImagePanel 类。 我还在项目的 Main 类中使用 SwingTest 代码的一部分来创建具有 ImagePanel 背景的自定义 jframe 类 (FramePrincipale) 的框架。当我执行时,我获得了一个带有 bakcground 的框架,但是没有其他 swing 元素(标签、文本字段..)是我的自定义 jframe 的一部分。 我该如何解决这个问题?

这是Principale类(主要项目类):

import java.awt.EventQueue;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JPanel;


public class Principale {


    private ImagePanel imagePanel;
    private static FramePrincipale frame = new FramePrincipale();

    private void displayGUI() throws IOException {





        JPanel contentPane = new JPanel();
        imagePanel = new ImagePanel();      
        contentPane.add(imagePanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }



    public static void main(String[] args) {



        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    new Principale().displayGUI();
                } catch (IOException ex) {
                    Logger.getLogger(Principale.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        EventQueue.invokeLater(runnable);

  while (true) {


      frame.scriviLabel();


    }     

    }

}

FramePrincipale 是同一项目中的 JFrame 表单。

@nIcEcOw:现在可以了!谢谢你所有的人! :-)

最佳答案

考虑到项目的目录结构如下所示:

 Since Images are Application Resources,
 it's always best to access them in the
 form of a URL, instead of File, as you are doing.
 Uncomment this below line and watch this answer
 of mine, as to HOW TO ADD IMAGES TO THE PROJECT
 https://stackoverflow.com/a/9866659/1057230
 In order to access images with getClass().getResource(path)
 here your Directory structure has to be like this
                 Project
                    |
         ------------------------
         |                      |
        bin                    src
         |                      |
     ---------             .java files             
     |       |                   
  package   images(folder)
  ( or              |
   .class        404error.jpg
   files, if
   no package
   exists.)

绘画示例

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

public class PaintingExample {

    private ImagePanel imagePanel;

    private void displayGUI() {
        JFrame frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        imagePanel = new ImagePanel();      
        contentPane.add(imagePanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new PaintingExample().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

class ImagePanel extends JPanel {

    private ImageIcon imageIcon;

    public ImagePanel() {
        try {
            imageIcon = new ImageIcon(ImageIO.read(ImagePanel.class.getResource(
                                                    "/images/aeroplaneright.jpeg")));
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return (imageIcon == null ? new Dimension(100, 100): new Dimension(
                                                   imageIcon.getIconWidth(), imageIcon.getIconHeight()));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(imageIcon.getImage(), 0, 0, this);
    }
}

输出:

PAINTINGEXAMPLE

响应编辑

正如编辑中提到的,您使用一些集成开发环境 - IDE 来创建应用程序。因为,每个 IDE 的工作方式都略有不同。请参阅这篇文章,了解如何add images to Java Project ,帮助您朝这个方向发展。

编辑 NetBeans

  1. 创建 Java 项目
  2. 提供任何项目名称。就我而言,我使用 SwingTest,如 如图所示
  3. 提供包名称。就我而言,我使用 swingtest,如 如图所示
  4. 右键单击源包新建 -> Java 包。在下面 新建 Java 包窗口,提供包名称,在我的例子中,我使用图像
  5. 文件系统复制图像并移回 NetBeans IDE,右键单击如此创建的images包并粘贴图像(在 NetBeans IDE 内)
  6. 通过右键单击 swingtest 包创建两个类,新建 -> Java类,其内容如下所示

就是这样,你现在就完成了。运行项目,您就可以看到图像了。请注意使用 getClass().getResource(...) 东西:

imageIcon = new ImageIcon(ImageIO.read(ImagePanel.class.getResource(
                                                    "/images/loyalperson.jpg")));

Swing 测试

package swingtest;

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

public class SwingTest {

    private ImagePanel imagePanel;

    private void displayGUI() {
        JFrame frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        imagePanel = new ImagePanel();      
        contentPane.add(imagePanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new SwingTest().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

图像面板

package swingtest;

import java.awt.Dimension;
import java.awt.Graphics;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class ImagePanel extends JPanel {

    private ImageIcon imageIcon;

    public ImagePanel() {
        try {
            imageIcon = new ImageIcon(ImageIO.read(
                         ImagePanel.class.getResource("/images/loyalperson.jpg")));
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return (imageIcon == null ? new Dimension(100, 100): new Dimension(
                         imageIcon.getIconWidth(),imageIcon.getIconHeight()));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(imageIcon.getImage(), 0, 0, this);
    }
}

带有图像的步骤

ProjectImages

这里是loyalperson.jpg的链接

编辑2:

要添加自定义组件,请执行以下操作:

  1. 转至工具 -> 面板 -> Swing/AWT 组件
  2. 点击新类别。在新调色板类别窗口中, 提供新类别名称
  3. 点击确定并关闭调色板管理器窗口
  4. 在编辑器中打开ImagePanel,现在选择Source View,现在 选择工具 -> 添加到调色板并选择刚刚的类别 由您创建。
  5. 我想,可以。现在该组件可以在 Palette 窗口,位于之前选择的Category 下,可以将其拖放到 JFrame/JComponent 上。

关于java - 使用 JPanel 扩展类设置背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24807952/

相关文章:

java - 防止子元素被选择 JSoup

java - 如何在java中将文本字段中的值插入数据库

java - 调整 LayeredPane Swing 的大小

java - 为什么 BoxLayout 不允许我更改 JButton 的宽度但让我更改高度?

java - 如何在数组中创建 JPanel 并向其中添加 Jlabel?

java - 我无法从 REST API URL 获取 JSON 对象

java - play2 调用子模块中的 Controller 、模型、 View

Scala 中的 Java protobuf

java - ImageIcon 的 2D 数组在 JPanel 中显示不一致且仅部分显示

java - 将 JLabel 定位在角落