JButton only appears on mouse?
Here's my code: I pulled out something that I didn't think was necessary. I may have taken some parentheses too, but I'm just trying to show the content I have.
What happens when I run the program, the background image draws (it's a PNG in resources) and only one button appears (my PLAY button) which is the first button - it is automatically selected.
I actually have four buttons, but in my code I have included PLAY and INSTRUCTIONS. The other three don't show up if I don't smoke over them. I know this is probably something weird about the drawing method, but I don't know how to fix it.
If I select a different button and hide the window and then reopen it, that button will only show one. I have to hover my mouse over to display other buttons.
I added super.paint()
to the paint method and I get all my buttons, but the background is gray. I think the problem is super.paint()
painting all my buttons, but g.drawImage(bg, 0, 0, null)
only painting my background, and I cannot do that without painting over the other.
Sorry if this was a mess. I am new to Java and I am having a hard time figuring out what I am trying to say.
public class MainMenu extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
//variables
public static Image bg;
public static void main(String[] args) {
MainMenu mainFrame = new MainMenu();
mainFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
mainFrame.setResizable(false);
mainFrame.setLocationRelativeTo(null);
mainFrame.setTitle ("Zumby");
mainFrame.setLayout(null);
// Loads the background image and stores in bg object.
try {
bg = ImageIO.read(new File("zumby.png"));
} catch (IOException e) {
}
mainFrame.setVisible(true);
}
/**
* Overrides the paint method.
* MONDAY
*/
public void paint(Graphics g)
{
// Draws the img to the BackgroundPanel.
System.out.println("paint");
g.drawImage(bg, 0, 0, null);
}
/**
*/
public MainMenu() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 500);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setOpaque(false);
setContentPane(contentPane);
contentPane.setLayout(null);
//create buttons
JButton btnPlay = new JButton("PLAY");
btnPlay.setBackground(Color.BLACK);
btnPlay.setForeground(Color.WHITE);
btnPlay.setFont(font);
btnPlay.setBorder(border);
btnPlay.setFocusPainted(false);
//if "Play" is clicked
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent click) {
setVisible(false);
new GamePlay(); //opens up GamePlay window
}
});
btnPlay.setBounds(600, 64, 141, 61);
contentPane.add(btnPlay);
JButton btnInstructions = new JButton("INSTRUCTIONS");
btnInstructions.setBounds(600, 160, 141, 61);
btnInstructions.setBackground(Color.BLACK);
btnInstructions.setFocusPainted(false);
// btnInstructions.setEnabled(true);
contentPane.add(btnInstructions);
repaint();
pack();
setVisible(true);
}
}
Swing uses the concept of "layering" for drawing ...
paint
calls paintComponent
, paintBorder
and paintChildren
. By overriding paint
and not calling super.paint
, you prevented the component from painting it in different layers.
In Swing, it is preferable to use it paintComponent
to create a custom paint that allows you to paint under any other components that can be added to the component.
public class TestPaint01 {
public static void main(String[] args) {
new TestPaint01();
}
public TestPaint01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Image backgroundImage;
public TestPane() {
try {
BufferedImage background = ImageIO.read(new File("/path/to/image.jpg"));
//backgroundImage = background.getScaledInstance(-1, background.getHeight() / 4, Image.SCALE_SMOOTH);
backgroundImage = background;
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
add(new JButton("Hello"));
}
@Override
public Dimension getPreferredSize() {
return backgroundImage == null ? super.getPreferredSize() : new Dimension(backgroundImage.getWidth(this), backgroundImage.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = (getWidth() - backgroundImage.getWidth(this)) / 2;
int y = (getHeight() - backgroundImage.getHeight(this)) / 2;
g.drawImage(backgroundImage, x, y, this);
}
}
}
You can find a Closer Look at Drawing Engine and Painting in AWT and Swing .
I think this is because you are overriding the draw method. Better to override the repaint, then call super.repaint (); Like this:
public void repaint(Graphics g)
{
super.repaint(g);
// Draws the img to the BackgroundPanel.
System.out.println("paint");
g.drawImage(bg, 0, 0, null);
}
Then the components are also redrawn.
But if all you want to do is show the image as a background, see here.
You are overriding paint()
but not calling super.paint()
. Therefore, the normal coloring of the components executed by the JFrame method implementation paint()
is not performed.
Because you are using Swing and JFrame
the drawing engine used to override paintComponent
not paint
, which is usually used with applets or AWTs.