Search code examples
javaswingjframejbuttonpaint

How to use paint method in a JPanel


I am working on a slot machine in Java and so far I created a button that will randomly generate two pictures. My code compiles but when I run it, all the stuff I put in the paint method does not show up. Is there anything I am missing? Thanks for your help and here is some of my code.

    public void paint(Graphics g) {
        super.paintComponents(g);
        g.drawString("Int 1 is" + int1,30,30);
        g.drawString("Int 2 is" + int2,30,80);
        switch (int1) {
            case 0:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img, 300, 500, this);
                break;
            case 1:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img2,300,500,this);
                break;
            case 2:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img3,300,500,this);
                break;
            case 3:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img4,300,500,this);
                break;
            case 4:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img5,300,500,this);
                break;
            case 5:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img6,300,500,this);
                break;
            case 6:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img7,300,500,this);
                break;
            case 7:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img8,300,500,this);
                break;
            case 8:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img9,300,500,this);
                break;
            case 9:
                g.setColor(Color.white);
                g.fillRect(300,300,300,500);
                g.drawImage(img10,300,500,this);
                break;
        }
        switch (int2) {
            case 0:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img, 800, 500, this);
                break;
            case 1:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img2,800,500,this);
                break;
            case 2:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img3,800,500,this);
                break;
            case 3:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img4,800,500,this);
                break;
            case 4:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img5,800,500,this);
                break;
            case 5:
\               g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img6,800,500,this);
                break;
            case 6:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img7,800,500,this);
                break;
            case 7:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img8,800,500,this);
                break;
            case 8:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img9,800,500,this);
                break;
            case 9:
                g.setColor(Color.white);
                g.fillRect(300,300,800,500);
                g.drawImage(img10,800,500,this);
                break;
        }
        this.setVisible(true);
    }

Solution

  • Problems:

    • You're drawing directly in a JFrame -- don't do this as you can mess up the JFrame graphics.
    • Your overriding the paint method and calling the super.paintComponents(...) method, again a dangerous thing to do, and something that should never be done.

    Instead you could do your drawing in the paintComponent(...) method of a JPanel and call the correct super.paintComponent(...) method inside of it, as described in the Swing painting tutorials, but why bother. Much easier would be to create an array of ImageIcons and simply call setIcon(...) on 3 (or however many you need) JLabels, after randomly selecting an Icon from the array or ArrayList.

    Also, never do this:

    try {
    
      // .... some code here
    
    } catch (IOException e) {
    
    }
    

    At least print out the stack trace within the catch block so you can identify any IO exceptions if they occur:

    try {
    
      // .... some code here
    
    } catch (IOException e) {
      e.printStackTrace(); // ****** added ********    
    }
    

    For example, the following code will produce this GUI:

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    // extend JPanel, not JFrame as it gives the class more flexibility as to where to use
    public class ShowRandomImages extends JPanel {
       // images from Andrew Thompson's example image page,
       // http://stackoverflow.com/questions/19209650/example-images-for-code-and-mark-up-qas
       private static final String IMAGE_SHEET_PATH = "https://i.sstatic.net/memI0.png";
       // how many JLabels to show in a row
       private static final int LABEL_COUNT = 3;
       // need to get subimages from image sheet. There are 6 columns in the sheet
       private static final int IMAGE_COLUMNS = 6;
       // array of JLabel
       private JLabel[] labels = new JLabel[LABEL_COUNT];
       // hold all the images as ImageIcons read in
       private List<Icon> imageIconList = new ArrayList<>();
       // to randomize the images
       private Random random = new Random();
    
       // pass the ImageIcon List into this class
       public ShowRandomImages(List<Icon> iconList) {
          this.imageIconList = iconList;
          // jpanel hold row of image-displaying JLabels
          JPanel labelHolderPanel = new JPanel(new GridLayout(1, 0, 5, 0));
          for (int i = 0; i < labels.length; i++) { // create all JLabels in array
             labels[i] = new JLabel();
             labels[i].setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
             labels[i].setHorizontalAlignment(SwingConstants.CENTER); // center the icon
             labels[i].setIcon(getRandomIcon()); // initialize with a random image
             labelHolderPanel.add(labels[i]); // add to holder JPanel
          }
    
          // panel to hold button at bottom
          JPanel bottomPanel = new JPanel();
          // button uses an AbstractAction rather than an ActionListener
          bottomPanel.add(new JButton(new ShowRandomIconAction("Show Random Image")));
    
          setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
          setLayout(new BorderLayout());
          add(labelHolderPanel, BorderLayout.CENTER);
          add(bottomPanel, BorderLayout.PAGE_END);
       }
    
       private Icon getRandomIcon() {
          int randomIndex = random.nextInt(imageIconList.size());
          return imageIconList.get(randomIndex);
       }
    
       private class ShowRandomIconAction extends AbstractAction {
          public ShowRandomIconAction(String name) {
             super(name);
             int mnemonic = (int) name.charAt(0);
             putValue(MNEMONIC_KEY, mnemonic);
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
             for (JLabel jLabel : labels) {
                jLabel.setIcon(getRandomIcon());
             }
          }
       }
    
       private static void createAndShowGui(List<Icon> imageIconList) {
          ShowRandomImages mainPanel = new ShowRandomImages(imageIconList);
    
          JFrame frame = new JFrame("ShowRandomImages");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          try {
             final List<Icon> iconList = getImages();
             SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                   createAndShowGui(iconList);
                }
             });
          } catch (IOException e) {
             e.printStackTrace();
             System.exit(-1);
          }
       }
    
       // read in image sheet and extract sub-images from it
       private static List<Icon> getImages() throws IOException {
          List<Icon> iconList = new ArrayList<>();
          URL imageUrl = new URL(IMAGE_SHEET_PATH);
          BufferedImage imageSheet = ImageIO.read(imageUrl);
          for (int i = 0; i < IMAGE_COLUMNS; i++) {
             int x = (int) ((double) i * imageSheet.getWidth() / IMAGE_COLUMNS);
             int y = 0;
             int w = imageSheet.getWidth() / IMAGE_COLUMNS;
             int h = imageSheet.getHeight() / 2;
    
             BufferedImage subImage = imageSheet.getSubimage(x, y, w, h);
             iconList.add(new ImageIcon(subImage));
          }
          return iconList;
       }
    }
    

    Otherwise if you absolutely must display images in a painting method, I'd recommend:

    • Create a JPanel extending class that displays just one image, say called ImageDisplayPanel. You'll give your class 2 of these if you need to display 2 images.
    • Pass into it a List<BufferedImage>
    • Give it a displayRandomImage() method
    • In this method, select a random image from the list and set a BufferedImage field to this image, and call repaint().
    • The paintComponent method of the DrawImagePanel will draw the image held by the field if it is not null.
    • In the main GUI, call this method on your 2 or 3 image JPanels as needed.