1
package BlackjackPanels;

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

public class MainPanel extends JFrame implements ActionListener {

    private JPanel background;

    public MainPanel() {    
        super("Alan's Blackjack");
        setDefaultCloseOperation(EXIT_ON_CLOSE);        
        background = new JPanel() 
        {   
            @Override
            protected void paintComponent(Graphics g)
            {       
                try 
                {
                    BufferedImage image = ImageIO.read(new File("C:/Users/Ssangwook/Desktop/programming/javafiles/Blackjack/src/BlackjackImages/blackjackTableResized.jpg"));
                    super.paintComponent(g);
                    g.drawImage(image, 0, 0, this);
                } 
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        };

        background.setPreferredSize(new Dimension(1000,500));
        add(background);
        pack();
        setLocationRelativeTo(null);
        setResizable(false);
        //isRunning();
        setVisible(true);
    }

    public void isRunning() {
        background.setLayout(new BorderLayout(10, 10));
        DealerPanel dealer=new DealerPanel();
        background.add(dealer, BorderLayout.LINE_START);
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent a) {
    }

    public static void main(String [] args) {
        MainPanel game=new MainPanel(); 
        game.isRunning();
    }
}

DealerPanel

package BlackjackPanels;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

public class DealerPanel extends JPanel {

    private JButton hit = new JButton("Hit");
    public DealerPanel() {
        super();
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        setPreferredSize(new Dimension(100,100));
        setOpaque(false);
        setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.DARK_GRAY), "DEALER"));

    }

    protected void askBets() {

    }

    public void addListener(ActionListener a) {
        hit.addActionListener(a);
    }
}

Hello, I'm just getting started on making blackjack with GUI. However, I am running into a problem and I was really hoping somebody could explain it to me.

The problem seems to be with the repaint() inside the isRunning() method. Whenever I run the program on Eclipse, I get the DealerPanel panel on my background only half of the times. The other half times that don't show the panel, I have to minimize the JFrame window and bring it back up again and the panel for DealerPanel is somehow displayed again.

I did a little search on my own and found out that repaint() merely requests the AWT thread to call update() which then calls paint() and is therefore not a direct call to paint. Also, repaint() can be problematic since repaint() only schedules for paint() and returns immediately. Could this potentially have anything to do with my problem?

To summarize, my panel for background is always showing. However, my panel for Dealer Panel does not always show when I initially run the program. The times that the Dealer panel don't show, I hide and bring up the window and the panel is displayed. Anybody knows the reason behind this erratic behavior?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Alan H
  • 77
  • 1
  • 7

1 Answers1

2
  1. super.paintComponent(g); should always be called, normally first, regardless of what else you might be doing in the paintComponent method
  2. Don't perform operations in the paint method which may be time consuming, like loading images. Load these images in advance. Paint methods may called numerous times, sometimes in quick succession
  3. Avoid calling setPreferred/Minimum/MaximumSize
  4. You may need to call revalidate (or invalidate, validate on JFrame) on the top level container so that the container hierarchy is marked as needing to be relaid out, repaint won't do this.
  5. You should be launching your UI from within the context of of the EDT, see Initial Threads for more details
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks a lot! I took your advice and made all the changes to my code. After writing revalidate() into my code, the problem I mentioned was gone. If I may, I have one more question. I understand now that java swing is not thread safe for the most part and therefore I should always run it on EDT. I did some search and it seemed like many people use invokeLater() or invokeAndWait() to queue an event to EDT. Is this what you are suggesting me to do? Is there any better way to launch it within EDT? – Alan H Mar 21 '14 at 15:39
  • Yes, but in your case, only in the main method. When program starts, it starts in what is known as the "main thread", you need to get your code running in the EDT, using invokeLater. Don't assume anything about what thread you bein at this stage, invokeLater is safer – MadProgrammer Mar 21 '14 at 22:40