JLabels in GridLayout not always colored

I am creating a basic Tic-Tac-Toe application in Java Swing and for this purpose I started researching the drawing. However, I ran into a problem where the subclass JPanel

contains more than one instance of the subclass JLabel

that overrides the method paintComponent(Graphic)

in an inline array format GridLayout

. The problem is that only the first element in this array is colored .

Example for a custom subclass JLabel

:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JLabel;

@SuppressWarnings("serial")
public class DrawLabel extends JLabel {

    private boolean hasPaint;

    public DrawLabel() {
        super();
        this.hasPaint = false;
    }

    public void draw() {
        hasPaint = true;
        repaint();
    }

    public void clear() {
        hasPaint = false;
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;

        if (hasPaint) {
            g2.drawOval(getX(), getY(), getWidth(), getHeight());
        } else {
            g2.clearRect(getX(), getY(), getWidth(), getHeight());
        }
    }
}

      

Example for a custom subclass JPanel

:

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class DrawPanel extends JPanel {

    private Dimension size;
    private DrawLabel[][] fields;

    public DrawPanel(Dimension d) {
        super();
        this.size = d;
        this.fields = new DrawLabel[size.height][size.width];

        this.setLayout(new GridLayout(size.height, size.width));

        for (int i = 0; i < size.height; i++) {
            for (int j = 0; j < size.width; j++) {
                this.fields[i][j] = new DrawLabel();
                this.add(fields[i][j]);
            }
        }
    }

    public void draw(int row, int col) {
        fields[row][col].draw();
    }

    public void clear() {
        for (int i = 0; i < size.height; i++) {
            for (int j = 0; j < size.width; j++) {
                fields[i][j].clear();
            }
        }
    }
}

      

An example of a script causing problems:

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;

public class Driver {

    public static void main(String[] args) {
        DrawPanel board = new DrawPanel(new Dimension(2, 1));

        JFrame canvas = new JFrame();
        canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvas.add(board, BorderLayout.CENTER);
        canvas.pack();

        canvas.setLocationRelativeTo(null);
        canvas.setVisible(true);

        board.draw(0, 0); // This gets painted.
        board.draw(0, 1); // This does not get painted!
    }

}

      

Curiously, if DrawPanel.draw(int, int)

changed to set the text of an element instead of drawing on it, only the second element is updated and the first is not, which is the exact opposite of the original problem.

I tried to find other problems and questions related to drawing subcomponents, but I have yet to find a problem like this where it seems that every instance outside the first in GridLayout

cannot be allocated in the same way. What could be wrong?

Thanks for your time and effort!

+3


source to share


1 answer


g2.drawOval(getX(), getY(), getWidth(), getHeight());

      

A component is painted relative to the component, not the panel the component is painted on. The getX / Y () methods return the location of the component relative to the parent component.

So if the size of each component is (200, 200) then the oval of the first component will be colored using

g2.drawOval(0, 0, 200, 200);

      

The second component will be colored in:



g2.drawOval(200, 0, 200, 200);

      

but since the component is only 200px wide, the origin x 200 location is outside the bounds of the component, so there is nothing to draw.

Instead, just use:

g2.drawOval(0, 0, getWidth(), getHeight());

      

+4


source







All Articles