【问题标题】:Using a JPanel extension class to set a background使用 JPanel 扩展类设置背景
【发布时间】:2014-07-17 15:39:24
【问题描述】:

在我的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 获得了一个框架,但是我的自定义 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 Form。

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

【问题讨论】:

  • 这是一个 Swing 应用程序,所以使用 JFrame 而不是 Frame。
  • 希望这个answer 和这个answer 可以帮助你:-)
  • @gesualdo:请编辑您的问题(不要在评论中添加东西,这里很难阅读),以及您尝试访问图像的方式。关于项目目录结构的一些想法也会有所帮助。
  • 你的代码中ImageIO在哪里使用?
  • 点击read more也可以找到项目结构。

标签: java swing jpanel drawimage


【解决方案1】:

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

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

输出:

响应编辑

正如编辑中提到的,您使用一些Integrated Development Environment - IDE 来创建应用程序。因为,每个IDE 都以不同的方式工作。请查看这篇关于如何add images to Java Project 的帖子是否对您有所帮助。

为 NetBeans 编辑

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

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

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

摇摆测试

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

图片步骤

这里是loyalperson.jpg的链接

编辑 2:

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

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

【讨论】:

  • @peeskillet:哈哈,谢谢你,保持微笑 :-) 刚刚下载了NetBeans 来回答这个问题,否则我会远离IDEs,但如果需要,我会使用EclipseIntelliJ IDEA :-)
  • 我喜欢 Netbeans,因为一切都如此“以香草为中心”。对纯 Java EE 的大力支持。我只使用 Eclipse 来支持它的 Spring
  • @gesualdo:我不确定你是如何创建 JFrame 的,首先。虽然如果您先将组件添加到 JPanel,然后添加到 FramePrincipale JFrame,那么我想您只需覆盖 JPanelgetPreferredSize()paintComponent(...),否则你可能不得不再次重建它,看起来像:(
  • 这是我在 StackOverflow 上遇到的最明确的答案之一。非常感谢
  • @DenisOluka:很高兴答案在某种程度上对您有所帮助 :-) 非常感谢并保持微笑 :-)
【解决方案2】:

如果扩展 JPanel 为什么不覆盖 JPanel 中的绘制方法,然后玩图形 例如:g.drawImage(img, x, y, width, height, ImageObserver)?

【讨论】:

  • 对不起,我没看懂第二部分:我玩什么?我必须改变 g.drawImage(img,0,0,null); ??
  • 我的意思是你必须用图形绘制图像,例如 BufferedImage img = ImageIO.read(new File("image.png")); g.drawImage(img, xPosition, yPosition, width, height, imageObserver);
  • -1 why not Override paint method in JPanel 自定义绘画是通过在使用 Swing 时覆盖 paintComponent() 方法来完成的。
  • @A48:请看Performing Custom Painting,尤其是Solving Common Painting Problems的第一个问题。这将说明为什么paint() 方法不适合此任务,以及为什么应该覆盖paintComponent()。仅在想要更改图形对象的状态并希望子组件响应该更改的情况下才覆盖 paint() 方法,否则:-)
猜你喜欢
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
相关资源
最近更新 更多