im having trouble finding out a way to merge the two JFrames in the code. I basically need the grid and stuff from one of the JFrames and an extra border around it. Because I need some buttons added to it. Here's the full code:
package opimejpanelit;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public class OpimeJpanelit {
public static JFrame frame;
public static JPanel panel;
public static void main(String[] args) {
frame = new JFrame("Huinjaa");
frame.setSize(1000, 600);
frame.setLocationRelativeTo(null);
new OpimeJpanelit();
//adds JPanel
panel = new JPanel();
frame.add(panel);
panel.setSize(900,600);
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public OpimeJpanelit() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int columnCount = 9;
private int rowCount = 7;
private java.util.List<Rectangle> cells;
private Point selectedCell;
public TestPane() {
cells = new ArrayList<>(columnCount * rowCount);
MouseAdapter mouseHandler;
mouseHandler = new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
Point point = e.getPoint();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
int column = e.getX() / cellWidth;
int row = e.getY() / cellHeight;
selectedCell = new Point(column, row);
repaint();
}
};
addMouseMotionListener(mouseHandler);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 400);
}
#Override
public void invalidate() {
cells.clear();
selectedCell = null;
super.invalidate();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
int xOffset = (width - (columnCount * cellWidth)) / 2;
int yOffset = (height - (rowCount * cellHeight)) / 2;
if (cells.isEmpty()) {
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
Rectangle cell = new Rectangle(
xOffset + (col * cellWidth),
yOffset + (row * cellHeight),
cellWidth,
cellHeight);
cells.add(cell);
}
}
}
if (selectedCell != null) {
int index = selectedCell.x + (selectedCell.y * columnCount);
Rectangle cell = cells.get(index);
g2d.setColor(Color.BLUE);
g2d.fill(cell);
}
g2d.setColor(Color.GRAY);
for (Rectangle cell : cells) {
g2d.draw(cell);
}
g2d.dispose();
}
}
}
I guess, It is not possible to merge two JFrame.
With a look at your code, It looks like you have tried adding up JPanel in the same container, but instead u created a new JFrame for it.
You can try using remove(component) method in JFrame to remove and add components again(If helpful).
If possible, Please provide a better clarity or pictorial representation of what you are trying to achieve.
Related
I started a Chess Project reusing some older code to paint a map everything basically has been copy pasted. The problem is the squares dont show up? I tried fixing it for a while now and got to no solution. Here are probably the three most important methods and a zip with the whole project. Some of it is in German.
https://drive.google.com/file/d/1nnZHLB0Ycy04eMyYbEmduMwbGhVLZ2VB/view?usp=sharing
public SchachFrame() {
super();
contentPane = new JPanel();
setContentPane(contentPane);
setBounds(0, 0, window.width, window.height);
contentPane.setBackground(Color.darkGray);
contentPane.setVisible(true);
ge = new GameEnvironment(this);
ge.setBounds(window.width/2 - 500, window.height/2 - 500, 1000, 1000);
ge.setVisible(true);
contentPane.add(ge);
Thread gameEnvironment = new Thread(ge);
gameEnvironment.start();
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void createMap(int width, int length, GameEnvironment ge) {
map = new Spielfeld[length][width];
Spielfeld.width = 1000/width;
Spielfeld.height = 1000/length;
for(int i = 0; i < length; i++) {
for(int j = 0; j < width; j++) {
this.map[i][j] = new Spielfeld(j, i, null);
this.map[i][j].setBounds(ge.getX() + j * Spielfeld.width, ge.getY() + i * Spielfeld.height, Spielfeld.width, Spielfeld.height);
this.map[i][j].setVisible(true);
ge.add(this.map[i][j]);
}
}
}
public void paintComponent(Graphics g) {
if((this.px + this.py) % 2 == 0) {
g.setColor(Color.blue);
} else {
g.setColor(Color.cyan);
}
g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
repaint();
}
Do not call repaint() in paintComponent. Otherwise you will never exit the EDT and lock up your code. And the first statement in paintComponent(Graphics g) should be super.paintComponent(g);
Updated to include an example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawSquareComponent extends JPanel {
static int WIDTH = 600;
static int HEIGHT = 600;
JFrame frame = new JFrame();
public static void main(String[] args) {
new DrawSquareComponent().start();
}
public void start() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
setBackground(Color.white);
MyComponent my =new MyComponent();
add(my); // add my component to panel
Random r = new Random();
for (int i = 0; i < 20; i++) {
int size = r.nextInt(50)+50;
int x = r.nextInt(WIDTH-size)+1;
int y = r.nextInt(HEIGHT-size)+1;
my.setBounds(x,y,size,size);
frame.repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
}
}
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
}
class MyComponent extends JPanel {
#Override
public void paintComponent(Graphics g) {
Graphics gg = g.create();
super.paintComponent(gg);
// location relative to parent's.
// used to check location in parent's coordinate space.
Point p = getLocation();
if ((p.x + p.y) % 2 == 0) {
gg.setColor(Color.blue);
} else {
gg.setColor(Color.cyan);
}
// paint this component so location is always 0,0.
// all you're doing is painting this squares background
gg.fillRect(0,0, this.getWidth(), this.getHeight());
gg.dispose();
}
}
Right now I have code to be able to randomize colored squares over a 25x25 board. What I'm trying to do is be able to make those colored squares turn white once pressed on and once it turns white, you can't reverse it. I was thinking about using Listeners but I'm not sure how to start.
Here is what I have to create the randomized squares.
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Color> colors;
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
colors = new ArrayList<Color>();
for (int index = 0; index < length; index++) {
int randomColor = (int) (Math.random() * availableColors.length);
colors.add(availableColors[randomColor]);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index));
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
}
Any help is much appreciated.
To change color on click, you just need a MouseListener, in the mouseClicked() method you must convert the click coordinates to row and column of the color grid, change that color and then ask the component to repaint.
Here the implementation, I just replaced your 1-dimensional color list with a 2-dimension color array, since it simplify the representation and the conversion from x,y to row,col.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
//This is the color that will be set when a cell is clicked
private static final Color CLICKED_COLOR = Color.white;
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
//Since you have a ROWSxCOLS color grid better use a 2-dimension array
private Color[][] cells;
//RandomColors across the given board size.
public TestPane() {
cells=new Color[ROWS][COLS];
for (int i=0;i<cells.length;i++) {
for (int j=0;j<cells[i].length;j++) {
int randomColor = (int) (Math.random() * availableColors.length);
cells[i][j]=availableColors[randomColor];
}
}
//Here the mouse listener, we only need to manage click events
//so I use a MouseAdapter to not implement the complete MouseListener interface
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
onClick(e);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
g2d.setColor(cells[row][col]);
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
//Finally the click handler
protected void onClick(MouseEvent e) {
//Convert mouse x,y (that are relative to the panel) to row and col
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
int row=(e.getY()-yOffset)/BOX_SIZE;
int col=(e.getX()-xOffset)/BOX_SIZE;
//Check that we are in the grid
if (row>=0&&row<ROWS&&col>=0&&col<COLS) {
//Set new color
cells[row][col]=Color.white;
//Repaint, only the changed region
repaint(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
}
}
You could use GridPane layout with a custom class for representing the squares
I have a working example here if you want to check
All squares handle their own painting
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[]{Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ColoredBoxes();
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Square> colors; // List of the representation of the Squares
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
GridLayout gridLayout = new GridLayout(ROWS, HEIGHT, 0, 0);
this.setLayout(gridLayout);
colors = new ArrayList<>();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int randomColor = (int) (Math.random() * availableColors.length);
Square temp = new Square(availableColors[randomColor], row, col);
colors.add(temp);
this.add(temp);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index).getColor());
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
public class Square extends JPanel {
private Color color;
private boolean clicked = false;
private int row;
private int col;
public Square(Color color, int row, int col) {
this.row = row;
this.col = col;
this.color = color;
this.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mousePressed(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
}
I'm trying to create a grid of customs JComponents. I want the grid being resizable without deform on my JComponent.
But I am only able to get a grid with clipped JComponent and bad resizing.
What I get :
What I want :
Here is my code :
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class Pawn extends JComponent {
private static Color pileColor = Color.LIGHT_GRAY;
private static Color faceColor = Color.DARK_GRAY;
private static Color mouseOverColor = new Color(255, 255, 127);
private static int padding = 10;
private String label;
private boolean pawnState;
private int radius;
private int row;
private int column;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame testPawnFrame = new JFrame("Test de la classe Pawn");
JPanel testPawnPanel = new JPanel();
testPawnPanel.setLayout(new GridLayout(3, 3,Pawn.padding*2,Pawn.padding*2));
for (int i = 0; i < 9; i++) {
testPawnPanel.add(new Pawn());
}
testPawnFrame.add(testPawnPanel);
addQuit(testPawnFrame);
testPawnFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testPawnFrame.pack();
testPawnFrame.setVisible(true);
}
public Pawn() {
this.pawnState = true;
this.radius = 50;
this.row = -1;
this.column = -1;
}
public Pawn(int row, int column) {
this();
this.row = row;
this.column = column;
}
public void setPosition(int row, int column) {
if (row >= 0 && column >= 0) {
this.row = row;
this.column = column;
} else {
throw new Error("La position donee est incorrecte.");
}
}
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(padding, padding, radius * 2, radius * 2);
if (pawnState) {
g2.setColor(pileColor);
} else {
g2.setColor(faceColor);
}
g2.fill(circle);
g2.setColor(Color.BLACK);
g2.draw(circle);
g2.drawRect(0, 0, 2 * (radius + padding), 2 * (radius + padding));
}
public Dimension getPreferredSize() {
return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
}
public Dimension getMinimumSize() {
return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
}
public void setBounds(int x, int y, int width, int height) {
radius = (int) Math.min(width, height) / 2;
super.setBounds(x, y, width+(padding*2), height+(padding*2));
repaint();
}
public static void addQuit(JFrame frame) {
ActionListener actionQuit = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
};
Box quitBox = new Box(BoxLayout.X_AXIS);
frame.add(quitBox, BorderLayout.SOUTH);
JButton quitButton = new JButton("Quit");
quitButton.addActionListener(actionQuit);
quitBox.add(Box.createHorizontalGlue());
quitBox.add(quitButton);
}
}
Edit :
I done some improvement to the code, thanks you all.
It's not perfect and it's not really optimized ,the resizing is pretty slow.
(if you have idea for optimize please tell me !)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class Pawn extends JComponent {
private static Color pileColor = Color.LIGHT_GRAY;
private static Color faceColor = Color.DARK_GRAY;
private static Color mouseOverColor = new Color(255, 255, 127);
private String label;
private boolean pawnState;
private int radius;
private double padding;
private int row;
private int column;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame testPawnFrame = new JFrame("Test de la classe Pawn");
JPanel testPawnPanel = new JPanel();
testPawnPanel.setLayout(new GridLayout(3, 3));
for (int i = 0; i < 9; i++) {
testPawnPanel.add(new Pawn());
}
testPawnFrame.add(testPawnPanel);
addQuit(testPawnFrame);
testPawnFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testPawnFrame.pack();
testPawnFrame.setVisible(true);
}
public Pawn() {
this.pawnState = true;
this.radius = 50;
this.padding = 0.1;
this.row = -1;
this.column = -1;
}
public Pawn(int row, int column) {
this();
this.row = row;
this.column = column;
}
public void setPosition(int row, int column) {
if (row >= 0 && column >= 0) {
this.row = row;
this.column = column;
} else {
throw new Error("La position donee est incorrecte.");
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
Dimension size = getSize();
radius = (int)(
(Math.min(size.width, size.height) / 2)
-(radius*padding));
Ellipse2D circle = new Ellipse2D.Double(
(size.width/2)-radius,
(size.height/2)-radius,
radius * 2, radius * 2);
if (pawnState) {
g2.setColor(pileColor);
} else {
g2.setColor(faceColor);
}
g2.fill(circle);
g2.setColor(Color.BLACK);
g2.draw(circle);
g2.drawRect(0, 0, getWidth()-1, getHeight()-1);
}
public Dimension getPreferredSize() {
int size = 2 * (radius);
return new Dimension(size, size);
}
public static void addQuit(JFrame frame) {
ActionListener actionQuit = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
};
Box quitBox = new Box(BoxLayout.X_AXIS);
frame.add(quitBox, BorderLayout.SOUTH);
JButton quitButton = new JButton("Quit");
quitButton.addActionListener(actionQuit);
quitBox.add(Box.createHorizontalGlue());
quitBox.add(quitButton);
}
}
That what i get now :
//super.paint(g);
super.paintComponent(g);
As already mentioned you need to invoke super on the method your are overriding
Don't override setBounds(). It is the job of the layout manager to determine the size/location of a component. This is the main problem with your code.
Some other problems:
There is no need to override getMinimumSize(). If you did, you would simply use:
return getPreferredSize();
Don't duplicate code if you don't have to.
return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
Don't repeat calculations. Create a variable. It is easier to debug and change.
//return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
int size = 2 * (radius + padding) + 1;
return new Dimension(size, size);
Note the "+1". I added this because the way the drawRect(...)method works. Try the code without the "+1" and you will see the bottom/right lines are missing. This is a perfect example of why you use variable to hold calculations. The change only needs to be done in one place.
Edit:
One more change:
//testPawnPanel.setLayout(new GridLayout(3, 3,Pawn.padding*2,Pawn.padding*2));
testPawnPanel.setLayout(new GridLayout(3, 3));
You don't want any space between your components, so let the layout manger do its job.
I honestly don't know what I'm doing wrong. (Although I'm sure it's quite a bit.) I've been trying to adjust my code for hours to no avail.
I'm attempting to cut up pieces of a picture and display them. Later, I will randomize where they are located and try to place them in their correct positions. Now, however, I'm having issues having anything show up on my JPanel at all. At one point, my test code displayed the image. Now, however, the same test code doesn't work.
If you can see what I'm doing wrong/where the issue is, please let me know. Hopefully it's something simple and stupid.
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
public class Lab10 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
MyFrame frame = new MyFrame();
MyPanel panel = new MyPanel();
frame.add(panel);
panel.setFocusable(true);
}
}
class MyFrame extends JFrame{
MyFrame(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setSize(800,800);
setResizable(false);
}
}
class MyPanel extends JPanel{
public static final int SIZE = 4;
private int oldx = -1;
private int oldy = -1;
private final String fileName = "houseTyrell.png";
public ImageArray imageArray = new ImageArray(fileName, SIZE);
MyPanel(){
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
if(e.getButton()==1){
if(oldx == -1){
oldx = e.getX();
oldy = e.getY();
}else{
//imageArray.swapPoints(oldx, oldy, e.getX(), e.getY());
oldx = -1;
oldy = -1;
repaint();
}
}
}
});
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
imageArray.draw(g2);
/*Image image2;
try {
image2 = ImageIO.read(new File("houseTyrell.png"));
System.out.println("I should print");
try{
g2.drawImage(image2, 0, 0, null);
} catch(Exception my){
System.out.println("Drawing issue");
}
} catch (IOException ex) {
System.out.println("Reading issue");
}*/
}
}
class ImageArray{
private Square[][] squares;
private String fileName;
private int size;
private int w;
private int h;
public ImageArray(String fileName, int size) {
this.size = size;
this.fileName= fileName;
squares = new Square[size][size];
try {
BufferedImage image = ImageIO.read(new File(fileName));
w = image.getWidth() / size;
h = image.getHeight() / size;
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
squares[row][col] = new Square(
image.getSubimage(row * w , col * h , w, h), row, col, w, h);
}
}
} catch (Exception e) {
System.out.println("Can't open file!");
}
shuffle();
}
//TODO
public void shuffle(){
for(int i = 0; i < size * size; i++){
}
}
//TODO
public void swapPoints(int oldx, int oldy, int newx, int newy){
}
public void draw(Graphics2D g2){
for(int i = 0; i < squares.length; i++){
for(int j = 0; j < squares[0].length; j++){
Square square = squares[i][j];
square.draw(g2);
}
}
}
}
class Square{
private BufferedImage image;
private int row;
private int col;
private int x,y;
private int w;
private int h;
Square(BufferedImage image, int row, int col, int w, int h){
this.image = image;
this.row = row;
this.col = col;
this.x = row * w;
this.y = col * h;
this.w = w;
this.h = h;
}
public void draw(Graphics2D g2){
try{
g2.drawImage(image, x, y, null);
} catch (Exception my){
System.out.println("Square issue");
}
}
public BufferedImage getImage(){
return image;
}
public int getRow(){
return row;
}
public int getCol(){
return col;
}
}
You are making the frame visible BEFORE you've finished establishing UI, try calling invalidate, validate and repaint on the frame AFTER you've added the panel...
public static void main(String[] args) {
MyFrame frame = new MyFrame();
MyPanel panel = new MyPanel();
frame.add(panel);
panel.setFocusable(true);
frame.invalidate();
frame.validate();
frame.repaint();
}
Frankly, your MyFrame class is doing very little (other then making your life more difficult), I'd consider getting rid of it, maybe replace it with a builder method which returns a frame which is not visible yet...
You should also be creating your UI from within the context of the Event Dispatching Thread, which can help solve other "weird" issues.
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
MyFrame frame = new MyFrame();
MyPanel panel = new MyPanel();
frame.add(panel);
panel.setFocusable(true);
frame.invalidate();
frame.validate();
frame.repaint();
}
});
}
See Initial Threads for more details
In the main method of Class Lab10, initialize the JPanel before the JFrame and it should work.
PS: Make sure the image referenced "houseTyrell.png" exists or use a fully qualified path temporarily for testing (i.e. c://test//houseTyrell.png).
I am trying to create the GUI for a connect four game and I want the chips to animate as they drop.I want the chip to look like it is passing behind the parts of the board that aren't cut out. The issue I am running into is that if I print out the board (the piece with the holes in it) first the falling chip will be on top of it and if I print out the chip first the board will cover it (since it is just a rectangle). Is there any way to do this without creating some complex polygons for the background image?
Here is the code I have so far:
public class ConnectFourGrid extends JPanel
{
ConnectFour game;
boolean animate = false;
int animateRow = 0;
int animateCol = 0;
int dropYPos = -30;
Timer dropTimer = new Timer(2, new animateListener());
ConnectFourGrid()
{
this.setPreferredSize(new Dimension(ConnectFour.NUM_OF_COLUMNS * 100, ConnectFour.NUM_OF_ROWS * 100));
}
class animateListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent arg0)
{
dropYPos += 5;
if (dropYPos == (animateRow * 100) + 10)
{
dropTimer.stop();
dropYPos = -30;
animate = false;
}
repaint();
}
}
public void setGame(ConnectFour game) { this.game = game; }
public ConnectFour getGame() { return game; }
public void animate(int row, int col)
{
animate = true;
animateRow = row;
animateCol = col;
dropTimer.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int row = 0; row < ConnectFour.NUM_OF_ROWS; row++)
{
for (int col = 0; col < ConnectFour.NUM_OF_COLUMNS; col++)
{
g.setColor(Color.BLUE);
g.fillRect(col * 100, row * 100, 100, 100);
if (game.getCurrentGameState()[row][col] == 0)
g.setColor(Color.WHITE);
else if (game.getCurrentGameState()[row][col] == 1)
g.setColor(Color.RED);
else
g.setColor(Color.YELLOW);
g.fillOval( col * 100 + 5, row * 100 + 10, 80, 80);
}
}
if (animate)
{
if (game.getCurrentPlayer() == 1)
g.setColor(Color.YELLOW);
else
g.setColor(Color.RED);
g.fillOval(animateCol * 100 + 5, dropYPos, 80, 80);
}
}
}
Okay, there are at least two ways I can think off doing this, one is to create a BufferedImage and use AlphaComposite to "poke" holes in it, the other is to use an Area and subtract holes from it...
The BufferedImage approach can be more efficient, as you only need to create the image when you need it, but can also be a little complicated.
Using an Area
This example demonstrates the use of an Area which has holes "pocked" out of it...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth() - 20;
int height = getHeight() - 20;
Area area = new Area(new Rectangle(10, 10, width, height));
int cellWidth = width / 4;
int cellHeight = height / 4;
for (int row = 0; row < 4; row++) {
int yPos = 10 + (row * cellHeight);
for (int col = 0; col < 4; col++) {
int xPos = 10 + (col * cellWidth);
area.subtract(new Area(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4)));
}
}
g2d.setColor(Color.BLUE);
g2d.fill(area);
g2d.dispose();
}
}
}
Using a BufferedImage and AlphaComposite
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage buffer;
public TestPane() {
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void invalidate() {
buffer = null;
super.invalidate();
}
protected BufferedImage getBoard() {
if (buffer == null) {
int width = getWidth() - 20;
int height = getHeight() - 20;
buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0, 0, width, height);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
g2d.setColor(new Color(0, 0, 0, 0));
int cellWidth = width / 4;
int cellHeight = height / 4;
for (int row = 0; row < 4; row++) {
int yPos = (row * cellHeight);
for (int col = 0; col < 4; col++) {
int xPos = (col * cellWidth);
g2d.fill(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4));
}
}
g2d.dispose();
}
return buffer;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
BufferedImage buffer = getBoard();
int x = (getWidth() - buffer.getWidth()) / 2;
int y = (getHeight() - buffer.getHeight()) / 2;
g2d.drawImage(buffer, x, y, this);
g2d.dispose();
}
}
}
Here is some code I found on the Web somewhere years ago:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class CompositeBoardTest extends JFrame {
private static int size = 400;
private static int offset = 10;
private static int ovalSize = size/4 - offset*2;
private static int pos = offset/2;
private static int incr = size/4;
public static void main( String[] args ) throws Exception {
SwingUtilities.invokeLater( new Runnable() {
public void run() { new CompositeBoardTest(); }
} );
}
public CompositeBoardTest() {
super( "CompositeBoardTest" );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Board board = new Board();
getContentPane().add( board );
setSize( size, size+34 );
setVisible( true );
}
static class Board extends JPanel implements ActionListener {
private int[][] pieces = new int[4][4];
private Piece addingPiece = null;
private Timer pieceDropped = null;
public Board() {
setPreferredSize( new Dimension( size, size ) );
setBounds( 0, 0, size, size );
// pieceDropped = new Timer( 10, this );
pieceDropped = new Timer( 20, this );
addMouseListener( new MouseAdapter() {
public void mousePressed( MouseEvent e ) {
int column = ( e.getPoint().x-pos )/incr;
addPiece( column );
}
});
}
protected void paintComponent( Graphics g ) {
super.paintComponent( g );
Graphics2D g2d = (Graphics2D) g;
Composite comp = g2d.getComposite();
Dimension d = getSize();
int w = d.width;
int h = d.height;
BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D gbi = buffImg.createGraphics();
// Clear area
g2d.setColor( Color.WHITE );
g2d.fillRect( 0, 0, w, h );
// Draw screen
// gbi.setColor( Color.YELLOW );
gbi.setColor( Color.BLUE );
gbi.fillRect( 0, 0, w, h );
// Draw pieces or holes
gbi.setColor( Color.RED );
for ( int row = 0 ; row < 4 ; row++ ) {
for ( int column = 0 ; column < 4 ; column++ ) {
if ( pieces[row][column] == 1 ) {
// gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 1.0f ) );
gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ) );
} else {
gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.CLEAR, 1.0f ) );
}
gbi.fillOval( incr*column+pos, incr*row+pos, ovalSize, ovalSize );
}
}
// Draw adding piece if we have it
if ( addingPiece != null ) {
gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_OVER, 1.0f ) );
gbi.fillOval( addingPiece.x, addingPiece.y, ovalSize, ovalSize );
}
// Draws the buffered image.
g2d.drawImage(buffImg, null, 0, 0);
g2d.setComposite( comp );
}
public void addPiece( int column ) {
if ( addingPiece == null ) {
if ( pieces[0][column] == 0 ) {
addingPiece = new Piece();
addingPiece.row = 0;
addingPiece.column = column;
addingPiece.x = incr*column+pos;
addingPiece.y = 0;
pieceDropped.start();
} else {
getToolkit().beep();
}
}
}
public void actionPerformed( ActionEvent e ) {
if ( addingPiece != null ) {
addingPiece.y += 5;
int row = ( addingPiece.y - pos )/incr + 1;
if ( row > 3 || pieces[row][addingPiece.column] == 1 ) {
pieces[row-1][addingPiece.column] = 1;
addingPiece = null;
pieceDropped.stop();
}
}
repaint();
}
}
private static class Piece {
public int row, column, x, y;
}
}
Click on a column to start the animation.