i have a Jframe which has some panels as instance variables and one of the panels is a grid board (i am implementing Lines of action game). After my game ends I have a button "Play again" which i want to reinitialize my board panel. I tried a lot of things like removing my panel from the content pane and re-initializing it, but nothing worked so far. Here are some of the things i tried (i didn't try them all at once )
public class Frame extends JFrame implements MouseListener{
JLabel l = new JLabel();
Panel1 Boards;
Panel2 newGame;
Panel3 winner;
Point lastCheckerSelected;
Board game = new Board();
public Frame() {
setResizable(false);
setTitle("Lines Of Action");
setBounds(290, 350, 1000, 700);
setLayout(null);
winner=new Panel3();
winner.playAgain.addMouseListener(this);
getContentPane().add(winner);
Boards= new Panel1();
getContentPane().add(Boards);
setDefaultCloseOperation(EXIT_ON_CLOSE);
l.setIcon(new ImageIcon(
"E:\\background0213.jpg"));
l.setBounds(0 ,0 , 1000 , 700);
getContentPane().add(l);
validate();
newGame=new Panel2();
newGame.b.addMouseListener(this);
getContentPane().add(newGame);
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
Boards.x[i][j].addMouseListener(this);
Boards.y[i][j].addMouseListener(this);
}
}
}
public void mouseClicked(MouseEvent e) {
if(e.getSource().equals(newGame.b)) {
Boards.setVisible(true);
newGame.setVisible(false);
game=new Board();
}
if(this.game.getWinner()==1) {
winner.setVisible(true);
winner.whiteWins.setVisible(true);
}
if(this.game.getWinner()==2) {
winner.setVisible(true);
winner.greywins.setVisible(true);
}
if(e.getSource().equals(winner.playAgain)) {
//this.getContentPane().remove(Boards);
// this.game= new Board();
// Boards = new Panel1();
// this.getContentPane().add(Boards);
//Boards.setVisible(true);
// validate();
// Boards.repaint();
}
}
public static void main(String[] args) {
Frame frame = new Frame();
frame.setVisible(true);
}
I still cant make my new panel appear ( removing the Boards panel from the content pane makes it disappear which is good but the new one does not appear)
here is my panel =1 that contains the board
public class Panel1 extends JPanel {
JButton[][] x = new JButton[8][8];
JButton[][] y=new JButton[8][8];
Graphics g;
public Panel1() {
setBounds(0, 30 ,400 ,400);
setLayout(new GridLayout(8, 8));
setOpaque(false);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
x[i][j] = new JButton();
x[i][j].setSize(50, 50);
if ((i % 2 == 0 && j % 2 == 0) || (i % 2 != 0 && j % 2 != 0)) {
x[i][j].setBackground(Color.DARK_GRAY.darker());
// x[i][j].setBackground(new Color(111,89,81,150));
}
else {
// Color.OPAQUE = 2;
x[i][j].setBackground(Color.red.darker().darker());
// x[i][j].setBackground(new Color(223,37,32,150));
}
x[i][j].setEnabled(false);
add(x[i][j]);
}
}
for(int i = 0; i < 8 ;i++){
for(int j=0;j < 8;j++){
y[i][j]=new JButton();
x[i][j].add(y[i][j]);
// y[i][j].setSize(100,100);
// y[i][j].setEnabled(false);
// y[i][j].setOpaque(false);
// y[i][j].setContentAreaFilled(false);
// y[i][j].setBorderPainted(false);
y[i][j].setVisible(false);
}
}
for(int i=1;i<7;i++){
// y[0][i].setOpaque(true);
y[0][i].setBackground(Color.white);
y[0][i].setEnabled(true);
y[0][i].setVisible(true);
// y[7][i].setOpaque(true);
y[7][i].setBackground(Color.white);
y[7][i].setEnabled(true);
y[7][i].setVisible(true);
}
for(int i=1;i<7;i++){
// y[i][0].setOpaque(true);
y[i][0].setEnabled(true);
y[i][0].setBackground(new Color(102,125,153));
y[i][0].setVisible(true);
// y[i][7].setOpaque(true);
y[i][7].setEnabled(true);
y[i][7].setBackground(new Color(102,125,153));
y[i][7].setVisible(true);
}
// addMouseListener(this);
setVisible(false);
}
}
You could also try this:
if(e.getSource().equals(winner.playAgain))
{
Boards.removeAll();
revalidate();
repaint();
}
I don't think you need to create a new Panel1 instance.
i have a Jframe which has some panels as instance variables and one of
the panels is a grid board (i am implementing Lines of action game).
After my game ends I have a button "Play again" which i want to
reinitialize my board panel. I tried a lot of things like removing my
panel from the content pane and re-initializing it, but nothing worked
so far.
I think that CardLayout is best of choices
Try these four together. Need to see more of your code to make sure this work.
if(e.getSource().equals(winner.playAgain)) {
this.getContentPane().remove(Boards);
Boards = new Panel1();
this.getContentPane().add(Boards);
this.invalidate();
this.validate();
this.repaint();
}
After the components are made visible in the screen, if you remove and add components, then you have to call Component.repaint() or Component.validate() to call the repainting again. Do this inside your actionPerformed() of your playAgainButton()
Related
I am attempting to use Java Swing to create a Grid that allows me to access specific panels if I need to. The frame pulls up but there are no panels. I would like some advice on how to make the panels display in the frame while still allowing me to access the specific panel through the two dimensional array.
x=0;
y=0;
z=0;
JPanel[][] coordinate = new JPanel[5][5];
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.setSize(550,550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
panel.setBackground(Color.WHITE);
panel.setLayout(new GridLayout(5,5));
for(int i = 0; i<25; i++) {
if(z == 5) {
z = 0;
x = 0;
y++;
}
coordinate[x][y] = new JPanel();
coordinate[x][y].setBorder(BorderFactory.createLineBorder(Color.BLACK, 10));
panel.add(coordinate[x][y]);
z++;
x++;
}
frame.add(panel);
I made a class which takes as parameters 2 dimentions ( n,m ) and a matrix ( mat ). This class makes a JFrame,fills it with buttons colored white(for 1's) or black( for 0's).
The issue is, the matrix being sent is continually changing and i want the button colors to update. If i set the mainframe game = new mainframe(n,m,mat) inside the loop im changing the matrix in,it continually spawns JFrame windows.
I read some stuff on this site that using repaint() or revalidate() could do something like this. I tried putting it in various segments of code but had no luck with it.
The main class is just a loop which calls "mainframe" and updates a matrix in a loop. Here is the class which makes the actual GUI work:
package game;
import java.awt.Color;
public class mainframe extends Jframe {
public mainframe(int n,int m,int mat[][]){
JButton[] buttons = new JButton[n*m];
setSize(600,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new GridLayout(n,m));
for(int i = 0; i<n*m;i++) {
buttons[i] = new JButton();
}
int counter = 0;
for(int j=0;j<n;j++){
for(int k=0;k<m;k++){
if(mat[j][k]==0){
buttons[counter].setBackground(Color.BLACK);
}
add(buttons[counter]);
counter++;
}
}
}
}
Put the setVisible(true); or revalidate(); after you added your components. Better work with the frame content pane.
import javax.swing.*;
import java.awt.*;
class Scratch {
public static void main(String[] args) throws InterruptedException {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(600, 400);
jFrame.setVisible(true);
for (int i = 5; i < 10; ++i) {
jFrame.setContentPane(createPanel(i, i, new int[i][i]));
jFrame.revalidate();
Thread.sleep(1000);
}
}
public static JPanel createPanel(int n, int m, int[][] mat) {
JButton[] buttons = new JButton[n * m];
JPanel jPanel = new JPanel();
jPanel.setLayout(new GridLayout(n, m));
for (int i = 0; i < n * m; i++) {
buttons[i] = new JButton();
}
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
int index = k + k * j;
if (mat[j][k] == 0) {
buttons[index].setBackground(Color.BLACK);
}
jPanel.add(buttons[index]);
}
}
return jPanel;
}
}
When using a GridLayout, it diveds its container's space evenly between its row and column elements. However when calcuating the cell width wouldn't turn out in an integer, the exceeding space is put between the container's edges and its content in a way, that the container's content is centered by the GridLayout.
In this picture you can see exceeding space (colored green):
Since the frame's size is dragged to 233x233 the LayoutManager would offer each component floor(233 / 20) = 11 pixels height and width. Thus 233 % 20 = 13 pixels exceed and are put at the edges.
That's the code to generate the frame in the picture:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout layout = new GridLayout(20, 0);
layout.setHgap(0);
layout.setVgap(0);
frame.setLayout(layout);
for (int j = 0; j < 20; j++) {
for (int i = 0; i < 20; i++) {
JPanel panel = new JPanel();
panel.setBackground((i + j) % 2 == 0 ? Color.BLACK : Color.WHITE);
frame.add(panel);
}
}
frame.pack();
frame.getContentPane().setBackground(Color.GREEN);
frame.setVisible(true);
So I wonder if there's an easy way to make the container 'clip' or align in a way, that this exceeding space doesn't show up, but instead the container is resized to fit its content perfectly.
That's right but I want to keep the advantage of a GridLayout offering every cell the same size,
Yes well you can't have it both ways.
If you want every cell to be the same size, then you will see the background. One option would be to make the panel non-opaque, so you don't see the background of the panel.
If you want to completely fill the area available with the components, then some components will need to be a different size by one pixel.
For implementing point 2, maybe this example will be easy enough for you to use:
import java.awt.*;
import javax.swing.*;
public class BoardTest
{
private static void createAndShowGUI()
{
Float constraint = new Float(1);
RelativeLayout boardLayout = new RelativeLayout(RelativeLayout.Y_AXIS);
boardLayout.setRoundingPolicy( RelativeLayout.EQUAL );
boardLayout.setFill(true);
JPanel board = new JPanel(boardLayout);
board.setBackground(Color.GREEN);
RelativeLayout rowLayout = new RelativeLayout(RelativeLayout.X_AXIS);
rowLayout.setRoundingPolicy( RelativeLayout.EQUAL );
rowLayout.setFill(true);
for (int j = 0; j < 20; j++)
{
JPanel row = new JPanel( rowLayout );
for (int i = 0; i < 20; i++)
{
JPanel square = new JPanel();
square.setBackground((i + j) % 2 == 0 ? Color.BLACK : Color.WHITE);
row.add(square, constraint);
}
board.add(row, constraint);
}
JFrame frame = new JFrame("BoardTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(board);
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
It uses the Relative Layout class which allows you to control how the extra pixels are allocated to each of the components.
I am making a minesweeper program, and I need to implement a feature where the user can choose to resize the grid that the mines are on. I've finished this, but when I make a larger board the JFrame doesn't get any larger, with it.
This is the method that happens when the user wants to resize the board
public void mouseClicked(MouseEvent e) {
if(e.getSource() == quitButton && e.getButton() == 1){
System.exit(0);
}
// if I hit the reset size button this happens
if(e.getSource() == setDimension){
for (int r = 0; r < size; r++)
for (int c = 0; c < size; c++){
gameBoard.remove(board[r][c]); // removes the buttons from the board
}
inputSizeAndMines(); // lets the user choose the size and amount of mines
game = new MineSweeperGame(size, mines); // remakes the game
setBoard(); // adds new buttons based on what the user entered
displayBoard(); // makes visuals for the board
revalidate();
repaint();
}
This is the class that adds the panel to a JFrame
public class MineSweeper {
/**********************************
* Main class that does everything
**********************************/
public static void main(String[] args) {
JFrame frame = new JFrame("MineSweeper");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MineSweeperPanel panel = new MineSweeperPanel();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
Any help would be appreciated
Call pack on the frame again once you have re-calculated the preferred size of the panel
The problem is when I set the background color of the square JPanel as square.setBackground(colors[j]) the square draws only the first color of the list of colors without displaying the other 3. This is my code:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
#SuppressWarnings({ "unused", "serial" })
public class RegionPartition extends JFrame
{
JLayeredPane layeredPane;
JPanel regionBoard;
JLabel regionPiece;
private static int DELAY = 200;
private Color[] colors = new Color[]{Color.PINK, Color.GREEN, Color.BLACK, Color.RED};
public RegionPartition()
{
Dimension boardSize = new Dimension(500, 500);
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
regionBoard = new JPanel();
layeredPane.add(regionBoard, JLayeredPane.DEFAULT_LAYER);
regionBoard.setLayout( new GridLayout(4, 4) );
regionBoard.setPreferredSize( boardSize );
regionBoard.setBounds(0, 0, boardSize.width, boardSize.height);
Random random = new Random();
for (int i = 0; i < 16; i++) {
JPanel square = new JPanel(new BorderLayout());
square.setBorder(BorderFactory.createLineBorder(Color.black));
regionBoard.add( square );
square.setBackground(Color.green);
int j=0;
square.setBackground(colors[j]);
j++;
}
}
{
JPanel panel = new JPanel()
{
Clients[] c = new Clients[128];
Random random = new Random();
private final int SIZE = 450;
private int DELAY = 9999999;
public void paintComponent (Graphics g)
{
super.paintComponent(g);
for (int i=0; i<c.length; i++)
{
int x = ( int ) ( random.nextFloat() * SIZE ) + 10;
int y = ( int ) ( random.nextFloat() * SIZE ) + 10;
g.drawOval( x, y, 10, 10 );
g.fillOval(x, y, 10, 10);
}
for (int j=0; j<DELAY; j++)
{
repaint();
}
}
};
panel.setOpaque(false);
//Set the glass pane in the JFrame
setGlassPane(panel);
//Display the panel
panel.setVisible(true);
}
public static void main(String[] args)
{
JFrame frame = new RegionPartition();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
protected void paintComponent(Graphics g)
{
// TODO Auto-generated method stub
}
}
That is because you are always setting j to 0 on each iteration:
int j=0;
square.setBackground(colors[j]);
j++;
you may want to change j for an i or do a nested loop, that depends on what you really want to do here.
If you want to make all 16 squares have all four colors in a grid like manner, you might want to change your loop to something like:
for (int i = 0; i < 16; i++) {
JPanel square = new JPanel(new GridLayout(2,2));
square.setBorder(BorderFactory.createLineBorder(Color.black));
regionBoard.add( square );
for(int j=0; j<4; ++j){
JPanel insideSquare = new JPanel();
insideSquare.setBackground(colors[j]);
square.add(insideSquare);
}
}
Because you only have 4 colors in your color array, but your loop index exceeds this, you could use:
square.setBackground(colors[ i % colors.length]);
to alternate the colors of your squares.
You are instantiating int j within the scope of your for loop, so its value is not preserved across multiple iterations. You should declare it at a point in your code to allow it scope over your entire for loop.
int j = 0;
<for loop>
square.setBackground(colors[j]);
j++;
<end for>
However, your j is serving the purpose of i in this situation, where i is sufficient as an array index. It would be more correct to remove j entirely and instead do the following:
square.setBackground(colors[i]);