I am very much a noob when it comes to swing. So far, all of my knowledge comes from YouTube and Stack Overflow. I am trying to make an interactive 5x5 board, with a random image in every spot, and a transparent JLabel on every image. I have a 2D array of ints, and I paint an image based on the ID value from the 2D array.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Panel extends JPanel{
int rows, cols, size;
int[][] gameBoard;
static final int SCREEN_SIZE = 500;
Panel(){
setPreferredSize(new Dimension(SCREEN_SIZE, SCREEN_SIZE));
setBackground(new Color(135, 206, 235)); //Sky blue
newBoard();
}
//Here
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) g2D.drawImage(Images.getImage(board[r][c]), size*c, size*r, null);//Paints an image based on each int value in the 2D array
}
void newBoard() {
rows = cols = 5;
size = 100;
board = new int[rows][cols];
fill();
}
void fill() {
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) gameBoard[r][c] = Images.randomTile(); //fills the 2D array with random values that relate to which image to display
}
}
(I took out all the irrelevant stuff)
This part works perfectly fine. The problem is that I tried to make an array of transparent JLabels with MouseListeners to cover each image. While testing, I made them opaque, but they didn't show up. I looked through StackOverflow to find my problem, and I keep on seeing people say not to override paint, but to override paintComponent. When I tried it, I got the background, but not the images. It is the same exact code, when I override paint, everything works fine, but when I change paint to paintComponent, I just get the background.
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) g2D.drawImage(Images.getImage(board[r][c]), size*c, size*r, null);//Paints an image based on each int value in the 2D array
}
Works perfectly
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) g2D.drawImage(Images.getImage(board[r][c]), size*c, size*r, null);//Paints an image based on each int value in the 2D array
}
Only shows the background
EDIT:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class Panel extends JPanel implements MouseListener{
int rows, cols, size;
int[][] board, shadowBoard;
JLabel[][] labelBoard;
static final int SCREEN_SIZE = 500;
Panel(){
setPreferredSize(new Dimension(SCREEN_SIZE, SCREEN_SIZE));
setBackground(new Color(135, 206, 235));
newBoard();
/*Timer tick = new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
});
tick.start();*/
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) g2D.drawImage(Images.getImage(board[r][c]), size*c, size*r, null);
}
//Board methods
void newBoard() {
rows = 5;
cols = 5;
size = 100;
board = shadowBoard = new int[rows][cols];
labelBoard = new JLabel[rows][cols];
fillLabelBoard();
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) this.add(labelBoard[r][c]);
fill();
//printBoard();
}
void newBoard(int r, int c) {
rows = r;
cols = c;
board = new int[rows][cols];
shadowBoard = new int[rows][cols];
size = (int) ((r>c)? SCREEN_SIZE/r : SCREEN_SIZE/c);
Images.resize(size);
fill();
//printBoard();
}
void fill() {
for (int r = 0; r<rows; r ) for (int c = 0; c<cols; c ) board[r][c] = Images.randomImage();
}
void fillLabelBoard() {
for (int r = 0; r<rows; r ) {
for (int c = 0; c<cols; c ) {
labelBoard[r][c] = new JLabel();
labelBoard[r][c].setBounds(0, 0, size, size);
labelBoard[r][c].setBackground(Color.red);
labelBoard[r][c].setOpaque(true);
labelBoard[r][c].addMouseListener(this);
//add(labelBoard[r][c]);
}
}
}
//Debugging
void printBoard() {
for (int[] r: board) {
for (int c: r) System.out.print(c);
System.out.print("\n");
}
System.out.println(rows);
System.out.println(cols);
System.out.println(size);
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.print("click");
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Full, unedited code
CodePudding user response:
The origin paint method inside JComponent does use the RepaintManager to determine if the rendering/painting must be done or not. Also it has a mechanism for Double-Buffering etc. inside.
paint only calls paintComponent when the component or it's client rectangle is marked as dirty, so a paint is necessary.
When you are overwriting paint you just call the origin method and after this you paint your own stuff - this will always be done.
But when you override paintComponent your parts will not be rendered when the origin paint method does not see the need to render/paint it. If you want to use paintComponent - you have to ensure the component will be marked as dirty/to render. For details look into JComponent paint implementation.
CodePudding user response:
Again, no issue. Both paint and paintComponent will produce a grid, the problem isn't with the code you're presenting us.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new Panel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Panel extends JPanel implements MouseListener {
int rows, cols, size;
int[][] board, shadowBoard;
JLabel[][] labelBoard;
static final int SCREEN_SIZE = 500;
Panel() {
setPreferredSize(new Dimension(SCREEN_SIZE, SCREEN_SIZE));
setBackground(new Color(135, 206, 235));
newBoard();
/*Timer tick = new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
});
tick.start();*/
}
// public void paint(Graphics g) {
// super.paint(g);
// Graphics2D g2D = (Graphics2D) g;
// paintBoard(g2D);
// }
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
paintBoard(g2D);
}
protected void paintBoard(Graphics2D g2d) {
for (int r = 0; r < rows; r ) {
for (int c = 0; c < cols; c ) {
g2d.drawRect(c * size, r * size, size, size);
// g2D.drawImage(Images.getImage(board[r][c]), size * c, size * r, null);
}
}
}
//Board methods
void newBoard() {
rows = 5;
cols = 5;
size = 100;
board = shadowBoard = new int[rows][cols];
labelBoard = new JLabel[rows][cols];
fillLabelBoard();
for (int r = 0; r < rows; r ) {
for (int c = 0; c < cols; c ) {
this.add(labelBoard[r][c]);
}
}
// fill();
// printBoard();
}
void newBoard(int r, int c) {
rows = r;
cols = c;
board = new int[rows][cols];
shadowBoard = new int[rows][cols];
size = (int) ((r > c) ? SCREEN_SIZE / r : SCREEN_SIZE / c);
//Images.resize(size);
// fill();
//printBoard();
}
// void fill() {
// for (int r = 0; r < rows; r ) {
// for (int c = 0; c < cols; c ) {
// board[r][c] = Images.randomImage();
// }
// }
// }
void fillLabelBoard() {
for (int r = 0; r < rows; r ) {
for (int c = 0; c < cols; c ) {
labelBoard[r][c] = new JLabel();
labelBoard[r][c].setBounds(0, 0, size, size);
labelBoard[r][c].setBackground(Color.red);
labelBoard[r][c].setOpaque(true);
labelBoard[r][c].addMouseListener(this);
//add(labelBoard[r][c]);
}
}
}
//Debugging
void printBoard() {
for (int[] r : board) {
for (int c : r) {
System.out.print(c);
}
System.out.print("\n");
}
System.out.println(rows);
System.out.println(cols);
System.out.println(size);
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.print("click");
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
}
