How to add an image to a JPanel?

前端 未结 14 1545
陌清茗
陌清茗 2020-11-22 00:01

I have a JPanel to which I\'d like to add JPEG and PNG images that I generate on the fly.

All the examples I\'ve seen so far in the Swing Tutorials, specially in the

相关标签:
14条回答
  • 2020-11-22 00:33

    Here's how I do it (with a little more info on how to load an image):

    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.JPanel;
    
    public class ImagePanel extends JPanel{
    
        private BufferedImage image;
    
        public ImagePanel() {
           try {                
              image = ImageIO.read(new File("image name and path"));
           } catch (IOException ex) {
                // handle exception...
           }
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters            
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 00:35

    You can subclass JPanel - here is an extract from my ImagePanel, which puts an image in any one of 5 locations, top/left, top/right, middle/middle, bottom/left or bottom/right:

    protected void paintComponent(Graphics gc) {
        super.paintComponent(gc);
    
        Dimension                           cs=getSize();                           // component size
    
        gc=gc.create();
        gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
        if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2)       +mmHrzShift),(((cs.height-mmSize.height)/2)        +mmVrtShift),null); }
        if(tlImage!=null) { gc.drawImage(tlImage,(insets.left                       +tlHrzShift),(insets.top                           +tlVrtShift),null); }
        if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top                           +trVrtShift),null); }
        if(blImage!=null) { gc.drawImage(blImage,(insets.left                       +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
        if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
        }
    
    0 讨论(0)
  • 2020-11-22 00:38

    If you are using JPanels, then are probably working with Swing. Try this:

    BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
    JLabel picLabel = new JLabel(new ImageIcon(myPicture));
    add(picLabel);
    

    The image is now a swing component. It becomes subject to layout conditions like any other component.

    0 讨论(0)
  • 2020-11-22 00:39
    1. There shouldn't be any problem (other than any general problems you might have with very large images).
    2. If you're talking about adding multiple images to a single panel, I would use ImageIcons. For a single image, I would think about making a custom subclass of JPanel and overriding its paintComponent method to draw the image.
    3. (see 2)
    0 讨论(0)
  • 2020-11-22 00:40

    I can see many answers, not really addressing the three questions of the OP.

    1) A word on performance: byte arrays are likely unefficient unless you can use an exact pixel byte ordering which matches to your display adapters current resolution and color depth.

    To achieve the best drawing performance, simply convert your image to a BufferedImage which is generated with a type corresponding to your current graphics configuration. See createCompatibleImage at https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html

    These images will be automatically cached on the display card memory after drawing a few times without any programming effort (this is standard in Swing since Java 6), and therefore the actual drawing will take negligible amount of time - if you did not change the image.

    Altering the image will come with an additional memory transfer between main memory and GPU memory - which is slow. Avoid "redrawing" the image into a BufferedImage therefore, avoid doing getPixel and setPixel at all means.

    For example, if you are developing a game, instead of drawing all the game actors to a BufferedImage and then to a JPanel, it is a lot faster to load all actors as smaller BufferedImages, and draw them one by one in your JPanel code at their proper position - this way there is no additional data transfer between the main memory and GPU memory except of the initial transfer of the images for caching.

    ImageIcon will use a BufferedImage under the hood - but basically allocating a BufferedImage with the proper graphics mode is the key, and there is no effort to do this right.

    2) The usual way of doing this is to draw a BufferedImage in an overridden paintComponent method of the JPanel. Although Java supports a good amount of additional goodies such as buffer chains controlling VolatileImages cached in the GPU memory, there is no need to use any of these since Java 6 which does a reasonably good job without exposing all of these details of GPU acceleration.

    Note that GPU acceleration may not work for certain operations, such as stretching translucent images.

    3) Do not add. Just paint it as mentioned above:

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

    "Adding" makes sense if the image is part of the layout. If you need this as a background or foreground image filling the JPanel, just draw in paintComponent. If you prefer brewing a generic Swing component which can show your image, then it is the same story (you may use a JComponent and override its paintComponent method) - and then add this to your layout of GUI components.

    4) How to convert the array to a Bufferedimage

    Converting your byte arrays to PNG, then loading it is quite resource intensive. A better way is to convert your existing byte array to a BufferedImage.

    For that: do not use for loops and copy pixels. That is very very slow. Instead:

    • learn the preferred byte structure of the BufferedImage (nowadays it is safe to assume RGB or RGBA, which is 4 bytes per pixel)
    • learn the scanline and scansize in use (e.g. you might have a 142 pixels wide image - but in the real life that will be stored as a 256 pixel wide byte array since it is faster to process that and mask the unused pixes by the GPU hardware)
    • then once you have an array build according to these principles, the setRGB array method of the BufferedImage can copy your array to the BufferedImage.
    0 讨论(0)
  • 2020-11-22 00:42

    Create a source folder in your project directory, in this case I called it Images.

    JFrame snakeFrame = new JFrame();
    snakeFrame.setBounds(100, 200, 800, 800);
    snakeFrame.setVisible(true);
    snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
    snakeFrame.pack();
    
    0 讨论(0)
提交回复
热议问题