1

Recently I've been getting into making some simple games with Swing in Java. My current project is a chess-like game, so I figured I would start by making an 8 by 8 grid with JButtons and go from there.

The problem is that every time I run my app, half of the buttons are just missing, and they only appear when I hover above them. From what I've searched about this problem, most of the suggestions were saying that I shouldn't use null layout, and I should use some of the layouts already in Swing. But from what I've seen so far, Swing layouts are just a pain to work with (at least when compared to the Android ones), and I would prefer just using absolute positioning for now.

Also I've found that adding panel.repaint(); fixes the missing buttons, but I don't like that solution since it doesn't really fix the problem but more like it patches it. When running my app with repaint, I still see the missing buttons for a split second until they are repainted.

So what I am looking for is why this thing happens in the first place, and is there any way for it not to happen without using the bad Swing layouts.

import javax.swing.*;

public class Main {

    static final int TILE = 70;
    static final int WIDTH = 600;
    static final int HEIGHT = 600;

    public static void main(String[] args){
        JFrame frame = new JFrame("Knight's tour");
        frame.setSize(WIDTH, HEIGHT);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        JPanel panel = new JPanel();
        panel.setLayout(null);
        frame.add(panel);

        JButton[][] tiles = new JButton[8][8];

        for(int i = 0; i < 8; i++){
            for(int j = 0; j < 8; j++){
                tiles[i][j] = new JButton();
                tiles[i][j].setLocation(i*TILE, j*TILE);
                tiles[i][j].setSize(TILE, TILE);
                panel.add(tiles[i][j]);
            }
        }

        //panel.repaint(); //this thing fixes it, but I am looking for a better fix
    }
}
David Simka
  • 556
  • 1
  • 5
  • 14
  • If you want to fix the problem and not just patch it, then don't use a null layout. – resueman Jul 07 '15 at 13:30
  • Well that's sad :( Having made some simple apps in Android, the layouts there just work. Too bad I can't say the same for Swing. The BoxLayout which I assume is the same as LinearLayout in Android just refuses to work half of the times, and I also tried using the GridLayout, but it feels so hard to make it do what I want. It just feels so much easier with null layout. Maybe it's just my inexperience, but I really feel like the Swing layouts are bad. – David Simka Jul 07 '15 at 13:36
  • @DavidSimka the swing layouts can be a little tough to get used to, but if you follow my GridLayout link, theres a simple way to use it. – Olivier Poulin Jul 07 '15 at 13:37

3 Answers3

3

Normally one would do last after adding the panel and its components:

frame.pack();
frame.setVisible(true);

The pack() doing some layouting on preferred sizes.

One could do a JTable 8x8 too.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
2

Avoid using null layouts for a number of reason. Different platform will treat them differently. They are difficult to maintain, among many other reasons. Instead use layout managers, and let them do the laying out and sizing of the components, as they were designed to do with Swing apps. Learn more at Laying out components Within a Container

For a chess game, it sounds like a GridLayout would be ideal for what you're looking for, without the same problems you're currently experiencing.

Olivier Poulin
  • 1,778
  • 8
  • 15
  • @DavidSimka No problem, if you **absolutely** want to keep null layout, try overriding paintcomponent and calling `super.paintComponent(g)`, it might make the buttons appear without the lag from repaint. – Olivier Poulin Jul 07 '15 at 13:40
0

First, you need to do the painting on the event thread. Second, you should make a class that extends JPanel, and if you really want to use a null layout, your panel should override paintComponent, and that method should first call super.paintComponent() and then position the child buttons appropriately.

FredK
  • 4,094
  • 1
  • 9
  • 11