Output a matrix in JTextArea [duplicate] - java

This question already has answers here:
how to convert a matrix in string in order to output it in JTextArea
(4 answers)
Closed 9 years ago.
I am trying to output a matrix in JTextArea, but I have problems with converting the matrix into string in order to output it...
My whole class is:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import java.awt.*;
class ConvertMatrix extends JFrame implements ActionListener
{
JLabel rows = new JLabel ("Numri i rreshtave"+'\n');
JTextField inrows = new JTextField (5);
JLabel columns = new JLabel ("Numri i kolonave eshte");
JTextField incolumns = new JTextField (5);
JLabel matrix = new JLabel("Matrica ka formen");
JTextField inmatrix = new JTextField(30);
JButton mat = new JButton("Afisho matricen");
JTextArea matric = new JTextArea(10,21);
int x;
int y;
int[][] matrica = new int [x][y];
public ConvertMatrix ()
{
super ("Matrica e konvertuar");
setSize(300, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Container content = getContentPane();
content.setLayout(new FlowLayout ());
content.setBackground(Color.pink);
content.add(rows);
rows.setForeground(Color.blue);
content.add(inrows);
content.add(columns);
columns.setForeground(Color.red);
content.add(incolumns);
content.add(matrix);
content.add(inmatrix);
matrix.setForeground(Color.gray );
content.add(mat);
content.add(matric);
mat.addActionListener(this);
setContentPane(content);
}
public void mbushMatricen(int x, int y){
for (int i =0; i<x; i++)
for (int j=0; j<y; j++)
matrica[i][j]=(int) ((double) Math.random()*10);
}
public void actionPerformed(ActionEvent event)
{
String rresht = inrows.getText();
int rreshtii = Integer.parseInt(rresht);//kthimi i stringut ne integer
String shtyll = incolumns.getText();
int shtylle = Integer.parseInt(shtyll);
mbushMatricen(rreshtii,shtylle);
String matricaString = "";
for( int i=0; i<rreshtii; i++){
for( int j=0; j<shtylle; j++){
matricaString += matrica[i][j] + " ";
}
matricaString += "\n";
}
matric.setText(matricaString);
}
public static void main(String []args)
{ ConvertMatrix m = new ConvertMatrix();
}
}
the problem is that it gives me these error:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at ConvertMatrix.mbushMatricen(ConvertMatrix.java:87)
at ConvertMatrix.actionPerformed(ConvertMatrix.java:98)
where line 87 is: matrica[i][j]=(int) ((double) Math.random()*10);
where line 98 is: mbushMatricen(rreshtii,shtylle);
I have also tried these method:
public void actionPerformed(ActionEvent event)
{
String rresht = inrows.getText();
int rreshtii = Integer.parseInt(rresht);//kthimi i stringut ne integer
String shtyll = incolumns.getText();
int shtylle = Integer.parseInt(shtyll);
mbushMatricen(rreshtii,shtylle);
StringBuilder matricaString = new StringBuilder();
for( int i=0; i<rreshtii; i++)
for( int j=0; j<shtylle; j++)
matricaString.append(Character.toString(matrica[i][j]));
matric.setText(matricaString.toString());
}
but is said to me: The method toString(char) in the type Character is not applicable for the arguments (int)
PLEASE CAN YOU HELP ME...I am a beginner in java

This worked well:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import java.awt.*;
public class ConvertMatrix extends JFrame implements ActionListener{
JLabel rows = new JLabel ("Numri i rreshtave"+'\n');
JTextField inrows = new JTextField (5);
JLabel columns = new JLabel ("Numri i kolonave eshte");
JTextField incolumns = new JTextField (5);
JLabel matrix = new JLabel("Matrica ka formen");
JTextField inmatrix = new JTextField(30);
JButton mat = new JButton("Afisho matricen");
JTextArea matric = new JTextArea(10,21);
int x;
int y;
double[][] matrica;
public ConvertMatrix (){
super ("Matrica e konvertuar");
setSize(300, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Container content = getContentPane();
content.setLayout(new FlowLayout ());
content.setBackground(Color.pink);
content.add(rows);
rows.setForeground(Color.blue);
content.add(inrows);
content.add(columns);
columns.setForeground(Color.red);
content.add(incolumns);
content.add(matrix);
content.add(inmatrix);
matrix.setForeground(Color.gray );
content.add(mat);
content.add(matric);
mat.addActionListener(this);
setContentPane(content);
}
public void mbushMatricen(int x, int y){
matrica = new double[x][y];
for (int i =0; i<x; i++){
for (int j=0; j<y; j++){
matrica[i][j]=((double) Math.random()*10);
}
}
}
public void actionPerformed(ActionEvent event){
String rresht = inrows.getText();
int rreshtii = Integer.parseInt(rresht);//kthimi i stringut ne integer
String shtyll = incolumns.getText();
int shtylle = Integer.parseInt(shtyll);
mbushMatricen(rreshtii,shtylle);
String matricaString = "";
for(int i=0; i<rreshtii; i++){
for( int j=0; j<shtylle; j++){
matricaString += matrica[i][j] + " ";
}
matricaString += "\n";
}
matric.setText(matricaString);
}
public static void main(String []args){
ConvertMatrix m = new ConvertMatrix();
}
}

You should use DecimalFormat class
import java.text.DecimalFormat;
formatter = new DecimalFormat("#0");
matricaString += formatter.format(matrica[i][j]) + " ";
DecimalFormat

Related

how to remove two jbuttons that have the same values and same colors by clicking them?

I have a matrix of colorful buttons and I need to compare their colors and their values after clicking them. All my code does is removing every button without searching their values or colors.Also i need to add the jlabel without rearranging jbuttons. How can i fix the problem?
public class Legos2 extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
public JPanel jp = (JPanel)this.getContentPane();
public JButton[][] jb = new JButton[12][24];//my matrix
public static JLabel jl = new JLabel("score",SwingConstants.CENTER);//a jlabel to count the scores every time two buttons are removed
public Legos2() {
super();
this.setSize(2000,2000);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
jp.setLayout(new GridLayout(12, 24));//size of my jpanel
Random rnd = new Random();
Color[] c = {Color.lightGray, Color.gray, Color.white, Color.cyan};//colored jbuttons
final int MAXCOLOR = c.length;
JButton jb1;
for(int i = 0;i <jb.length;i++) {
for(int j = 0; j<jb[i].length; j++) {
int k = (int) (Math.random()*9+1);//k is a random integer from 1 to 9
jb1 = new JButton(Integer.toString(k));
add(jb1);
jb[i][j]=jb1;
jb[i][j].addActionListener(this);
}
}
for(int i=0; i<jb.length; i++){
for(int j = 0; j<jb[i].length; j++) {
jb[i][j].setBackground(c[rnd.nextInt(MAXCOLOR)]);//i add colors in here
}
}
for (int row = 0; row < jb.length; row++) {
for (int column = 0; column < jb[row].length; column++) {
jb[row][column].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText();
// now iterate over all the jbuttons you have
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
String bText = b.getText();
if(e.getSource()==b)
if(buttonText.equals(bText)){
b.setEnabled(false);
jl.setText(Integer.toString(i));
}
}
}
}
}
);
jp.add(jb[row][column]);
}
}
}
}
The following is mcve of the required functionality. Please review and ask for clarifications as needed:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class Legos2 extends JFrame{
private static final long serialVersionUID = 1L;
private static final int ROWS = 12, COLS =24;
public JButton[][] jb = new JButton[ROWS][COLS];
private int score = 0;
public static JLabel jl;
public Legos2() {
super();
this.setSize(2000,2000);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel jp= new JPanel();
jp.setLayout(new GridLayout(ROWS, COLS));
Random rnd = new Random();
Color[] c = {Color.lightGray, Color.gray, Color.white, Color.cyan};
final int MAXCOLOR = c.length;
//all can be done in one loop
for(int i = 0;i <jb.length;i++) {
for(int j = 0; j<jb[i].length; j++) {
int k = (int) (Math.random()*9+1);//k is a random integer from 1 to 9
JButton button = new JButton(Integer.toString(k));
button.setBackground(c[rnd.nextInt(MAXCOLOR)]);
button.addActionListener(e -> {
disableTwoMatchingButtons(button);
});
jb[i][j]=button;
jp.add(button);
}
}
add(jp); //add panel at content pane center
jl= new JLabel("",SwingConstants.CENTER);
updateScore(0);
add(jl, BorderLayout.PAGE_END); //add label at content pane bottom
pack();
setVisible(true);
}
private void disableTwoMatchingButtons(JButton button) {
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
if(b.isEnabled() && button.getText().equals(b.getText()) &&
button.getBackground().equals(b.getBackground())){
b.setEnabled(false);
button.setEnabled(false);
updateScore(2* Integer.valueOf(b.getText()));
return;
}
}
}
}
private void updateScore(int value) {
score += value;
jl.setText("Score: "+ score );
}
public static void main(String[] args) {
new Legos2();
}
}
If you need to disable all matching button, and not just two, use :
private void disableAllMatchingButtons(JButton button) {
for(int i=0;i<jb.length;i++){
for(int j=0;j<jb[0].length;j++){
JButton b = jb[i][j];
if(b.isEnabled() && button.getText().equals(b.getText())
&& button.getBackground().equals(b.getBackground())){
b.setEnabled(false);
updateScore(Integer.valueOf(b.getText()));
}
}
}
}
(instead of disableTwoMatchingButtons)
For future post always consider posting an mcve, and stick to one question per post.

Calling methods from another class and retrieving their results (Java)

I have 2 classes (IterativeVsRecursive and Sequence) and the Sequence class performs mathematical actions and returns the values to IterativeVsRecursive, or at least that is the intent.
I believe I am missing something easy, but am stumped on how to make this work.
IterativeVsRecursive Class:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.midi.Sequence;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class IterativeVsRecursiveGUI extends JFrame implements ActionListener {
private JLabel radioButton1Label = new JLabel();
private JLabel radioButton2Label = new JLabel();
private JLabel inputLabel = new JLabel();
private JLabel resultLabel = new JLabel();
private JLabel efficiencyLabel = new JLabel();
private JLabel computeButtonLabel = new JLabel();
private ButtonGroup radioButtonGroup = new ButtonGroup();
private JRadioButton radioButtonIterative = new JRadioButton("Iterative");
private JRadioButton radioButtonRecursive = new JRadioButton("Recursive");
private JTextField inputField = new JTextField();
private JTextField resultField = new JTextField();
private JTextField efficiencyField = new JTextField();
private JButton computeButton = new JButton();
private int efficiencyCounter;
public IterativeVsRecursiveGUI()
{
super("Project 3");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(6, 2));
radioButtonGroup.add(radioButtonIterative);
radioButtonIterative.setSelected(true);
// radioButtonIterative.setText("Iterative");
getContentPane().add(radioButtonIterative);
radioButtonGroup.add(radioButtonRecursive);
// radioButtonRecursive.setText("Recursive");
getContentPane().add(radioButtonRecursive);
inputLabel.setText("Enter number: ");
getContentPane().add(inputLabel);
getContentPane().add(inputField);
computeButton.setText("Compute");
computeButton.addActionListener(this);
getContentPane().add(computeButton);
resultLabel.setText("Result: ");
getContentPane().add(resultLabel);
getContentPane().add(resultLabel);
resultField.setEditable(false);
efficiencyLabel.setText("Efficiency: ");
getContentPane().add(efficiencyLabel);
getContentPane().add(efficiencyField);
efficiencyField.setEditable(false);
pack();
}
#Override
public void actionPerformed(ActionEvent button) {
int result;
efficiencyCounter = 0;
if (radioButtonIterative.isSelected()) {
result = Sequence.computeIterative(Integer.parseInt(inputField.getText()));
} else {
result = Sequence.computeRecursive(Integer.parseInt(inputField.getText()));
}
resultField.setText(Integer.toString(result));
efficiencyField.setText(Integer.toString(efficiencyCounter));
}
public static void main(String[] args) {
IterativeVsRecursiveGUI IterativeVsRecursiveGUI = new IterativeVsRecursiveGUI();
IterativeVsRecursiveGUI.setVisible(true);
}
}
Sequence class:
public class Sequence {
private int efficiencyCounter = 0;
public int computeIterative(int input) {
int answer = 0;
if (input == 0) {
efficiencyCounter++;
answer = 0;
} else if (input == 1) {
efficiencyCounter++;
answer = 1;
} else {
efficiencyCounter++;
int firstTerm = 0;
int secondTerm = 1;
for (int i = 2; i <= input; i++) {
answer = (3 * secondTerm) - (2 * firstTerm);
firstTerm = secondTerm;
secondTerm = answer;
}
}
return answer;
}
public int computeRecursive(int input) {
int answer = 0;
efficiencyCounter++;
if (input == 0) {
answer = 0;
} else if (input == 1) {
answer = 1;
} else {
answer = (3 * computeRecursive(input - 1)) - (2 * computeRecursive(input - 2));
}
return answer;
}
}
The intent is to have a GUI that displays the results of the Sequence class.
I should have been clear in that it is not allowing me to call the non-static methods in Sequence, but if I make them static, by adding "void", then the computeRecursive method throws an errror saying that 'void' type not allowed here
Or, since the method is already an instance method, create an instance of Sequence
#Override
public void actionPerformed(ActionEvent button) {
int result;
efficiencyCounter = 0;
Sequence sequence = new Sequence();
if (radioButtonIterative.isSelected()) {
result = sequence.computeIterative(Integer.parseInt(inputField.getText()));
} else {
result = sequence.computeRecursive(Integer.parseInt(inputField.getText()));
}
resultField.setText(Integer.toString(result));
efficiencyField.setText(Integer.toString(efficiencyCounter));
}

Unable to find the coordinates of the pressed buttons

only problem is that whenever i set initial value for the x and y to be greater than 10,it gives bad result.Please help.It works fine for the values less than 10 for x and y.
i have also debugged it and find out whenever the button is pressed after the 10th index it behaves like setting the variable i to 1.i am unable to fix this issue as i am new in java.so i really need help in this.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.JFrame;
class butMaddFrame extends JFrame implements ActionListener
{
int x=12;
int y=12;
JButton[][] buttons = new JButton[x][y];
JPanel mPanel = new JPanel();
JPanel bPanel = new JPanel();
JPanel cPanel = new JPanel();
JTextArea scoreKeeper = new JTextArea();
Container c = getContentPane();
int[][] intArray = new int[x][y];
public butMaddFrame()
{
butGen();
score2();
//cPanel.add(scoreKeeper);
bPanel.setLayout(new GridLayout(x,y));
mPanel.setLayout(new BorderLayout());
mPanel.add(bPanel, BorderLayout.CENTER);
// mPanel.add(cPanel, BorderLayout.LINE_END);
c.add(mPanel);
setTitle("ButtonMaddness");
setSize(1000,400);
setLocation(200,200);
setVisible(true);
}
private void butGen()
{
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
{
buttons[i][j] = new JButton(String.valueOf(i)+"x"+String.valueOf(j));
buttons[i][j].setActionCommand("button" +i +"_" +j);
buttons[i][j].addActionListener(this);
bPanel.add(buttons[i][j]);
}
}
private void score()
{
// String string = "";
// for(int i=0;i<x;i++)
// {
// for(int j=0;j<y;j++)
// string += i+"x"+j+" => " +String.valueOf(intArray[i][j]) +"\t";
// string+= "\n";
// }
// scoreKeeper.setText(string);
}
private void score2()
{
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
buttons[i][j].setText(String.valueOf(intArray[i][j]));
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().contains("button"))
{
int i = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll ("_", "").charAt(0)));
int j = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll ("_", "").charAt(1)));
intArray[i][j]++;
// buttons[i][j].setVisible(false);
buttons[i][j].setBackground(Color.black);
System.out.println(e.getActionCommand() +" " +i +" " +j);
}
// score2();
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class buttonMaddness {
public static void main(String[] args)
{
butMaddFrame myFrame = new butMaddFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Your problem is here:
replaceAll("_", "").charAt(0)
because some of your buttons have things like 11_9 for
example. So you get just the first 1 of the number 11.
Just change your actionPerformed method
to this and your bug will be fixed.
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().contains("button")) {
String str = e.getActionCommand().replaceAll("button", "");
System.out.println(str);
String[] v = str.split("_");
int i = Integer.parseInt(v[0]);
int j = Integer.parseInt(v[1]);
/*
int i = Integer.parseInt(Character.toString(e.getActionCommand()
.replaceAll("button", "").replaceAll("_", "").charAt(0)));
int j = Integer.parseInt(Character.toString(e.getActionCommand()
.replaceAll("button", "").replaceAll("_", "").charAt(1)));
*/
intArray[i][j]++;
// buttons[i][j].setVisible(false);
buttons[i][j].setBackground(Color.black);
System.out.println(e.getActionCommand() + " " + i + " " + j);
}
// score2();
}

Need to set a double value depending on which item(s) are selected from a JList

My code so far:
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TestFile2 {
public static void main(String args[]) {
String size[] = {"Small", "Medium", "Large", "Extra Large"};
String toppings[] = {"Cheese", "Pepperoni", "Sausage", "Spinach", "Pepperoncini"};
JFrame f = new JFrame("Pizza");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JList list1 = new JList(size);
JList list2 = new JList(toppings);
Container c = f.getContentPane();
JScrollPane sp1 = new JScrollPane(list1);
sp1.setColumnHeaderView(new JLabel("Select Size"));
JScrollPane sp2 = new JScrollPane(list2);
sp2.setColumnHeaderView(new JLabel("Select Toppings. Hold Ctrl to select multiple toppings"));
Box box = Box.createHorizontalBox();
box.add(sp1);
box.add(sp2);
list1.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
JList jListSource = (JList) e.getSource();
Object[] selection = jListSource.getSelectedValues();
if (!e.getValueIsAdjusting()) {
System.out.println("----");
for (int i = 0; i < selection.length; i++) {
double costSize;
if (selection[i].equals("Small")) {
costSize = 7.00;
} else if (selection[i].equals("Medium")) {
costSize = 9.00;
} else if (selection[i].equals("Large")) {
costSize = 11.00;
} else {
costSize = 14.00;
}
System.out.println("selection = " + selection[i]);
System.out.println("selection = " + costSize);
}
}
}
});
c.add(box, BorderLayout.CENTER);
f.setSize(
300, 200);
f.setVisible(
true);
}
}
I need to do something similar to what I did with list1.
I need to have the user select from a JList both the size of pizza and the toppings. At the end I need to be able to calculate the total cost. Each topping is $1. Any point in a certain direction would be greatly appreciated as I have been pulling my hair out for the past few hours trying different methods for this problem.
Thanks in advance.
I hope this will help :) ... there are other ways to do it.... this just one of them ...
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TestFile2 {
private static JList list1;
private static JList list2;
public static void main(String args[]) {
String size[] = {"Small", "Medium", "Large", "Extra Large"};
String toppings[] = {"Cheese", "Pepperoni", "Sausage", "Spinach", "Pepperoncini"};
JFrame f = new JFrame("Pizza");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
list1 = new JList(size);
list2 = new JList(toppings);
Container c = f.getContentPane();
JScrollPane sp1 = new JScrollPane(list1);
sp1.setColumnHeaderView(new JLabel("Select Size"));
JScrollPane sp2 = new JScrollPane(list2);
sp2.setColumnHeaderView(new JLabel("Select Toppings. Hold Ctrl to select multiple toppings"));
Box box = Box.createHorizontalBox();
box.add(sp1);
box.add(sp2);
list1.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent e)
{
handleEvent(e);
}
});
list2.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent e)
{
handleEvent(e);
}
});
c.add(box, BorderLayout.CENTER);
f.setSize(
300, 200);
f.setVisible(
true);
}
protected static void handleEvent(ListSelectionEvent e)
{
double cost = 0.0;
Object[] selection = list1.getSelectedValues();
Object[] toppings = list2.getSelectedValues();
if(toppings.length == 0)
System.out.println("Please select a topping");
if(selection.length == 0)
System.out.println("Please select a size");
if (!e.getValueIsAdjusting())
{
System.out.println("----");
for (int i = 0; i < selection.length; i++)
{
double costSize;
if (selection[i].equals("Small")) {
cost = 7.00;
} else if (selection[i].equals("Medium")) {
cost = 9.00;
} else if (selection[i].equals("Large")) {
cost = 11.00;
} else {
cost = 14.00;
}
}
for (int i = 0; i < toppings.length; i++)
{
cost++;
}
System.out.println("Total = " + cost);
}
}
}

JPanel in puzzle game not updating

I have a simple puzzle game. There is an image consisting of 16 tiles (randomly placed). Images are stored in an array and when game is launched they're added to main JPanel.
Game works in this way : Each image has atributes 'place' and 'number'. 'Place' is the current place on grid (either correct or not) and 'number' is the desired place for the image. When a user clicks image their 'place' and 'number' attributes are checked. If they match nothing happens. If not game checks if any image is currently in memory. If there is none, then this image's 'place' and 'number' are stored. If there is some image in memory, then the currently clicked image's 'plac'e is checked with stored image's 'number'. When they match - their places are exchanged. This part works properly. But now, I'm calling addComponent method on my JPanel with updated images and simply nothing happens. Shouldn't the new images be added to JPanel replacing the old ones ?
package Bonus;
import javax.swing.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.*;
class Puzzle extends JPanel implements ActionListener {
private int selected_nr=-1;
private int selected_pl=-1;
private boolean memory=false;
private static Img[] images;
public Puzzle(){
JFrame f = new JFrame("Smile");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.setSize(252,252);
f.setVisible(true);
setLayout(new GridLayout(4, 4));
images = new Img[16];
int[] buttons = new int[16];
for(int i=0; i<16; i++){
buttons[i] = i;
}
int rand;
int temp;
Random random;
random = new Random(System.currentTimeMillis());
for (int i = 0; i < buttons.length; i++) {
rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length;
temp = buttons[i];
buttons[i] = buttons[rand];
buttons[rand] = temp;
}
for (int i = 0; i < 16; i++) {
images[i] = new Img(i, buttons[i]);
}
addComponents(images);
}
public void addComponents(Img[] im){
this.removeAll();
for(int i=0; i<16; i++){
im[i].addActionListener(this);
im[i].setPreferredSize(new Dimension(53,53));
add(im[i]);
}
this.validate();
}
public void actionPerformed(ActionEvent e) {
Img b = (Img)(e.getSource());
int num = b.getNumber();
int pl = b.getPlace();
if(!(b.rightPlace())){
if(memory){
if(pl == selected_nr){
images[pl].setPlace(selected_pl);
images[selected_pl].setPlace(selected_nr);
selected_nr = -1;
selected_pl = -1;
memory = false;
addComponents(images);
}
else{
System.out.println("Try other image");
}
}
else{
memory = true;
selected_nr = num;
selected_pl = pl;
}
}
else{
System.out.println("OK !");
}
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Puzzle();
}
});
}
}
class Img extends JButton {
int number;
int place;
ImageIcon img;
public Img(int p, int n){
number = n;
place = p;
img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER);
setIcon(img);
}
public boolean rightPlace(){
boolean correct=false;
if(number == place){
correct = true;
}
return correct;
}
public void setPlace(int i){
place = i;
}
public int getNumber(){
return number;
}
public int getPlace(){
return place;
}
}
EDIT: Changed the code to use the answers, but still no luck. addComponents() gets updated images[] but doesn't revalidate them.
Rather than relying on precut image files, here's an example of slicing an existing image and shuffling the resulting pieces. It combines the helpful (+1) suggestions of both #Frederick and #akf.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageLabelPanel extends JPanel implements ActionListener {
private static final int N = 4;
private final List<JLabel> list = new ArrayList<JLabel>();
private final Timer timer = new Timer(1000, this);
ImageLabelPanel() {
this.setLayout(new GridLayout(N, N));
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
int w = bi.getWidth() / N;
int h = bi.getHeight() / N;
BufferedImage b = bi.getSubimage(c * w, r * h, w, h);
list.add(new JLabel(new ImageIcon(b)));
}
}
createPane();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
timer.start();
}
private void createPane() {
this.removeAll();
for (JLabel label : list) add(label);
this.validate();
}
#Override
public void actionPerformed(ActionEvent e) {
Collections.shuffle(list);
createPane();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageLabelPanel();
}
});
}
}
You are adding all of your components again to your JPanel without actually removing any of them. In your addComponents() method, I would first call removeAll(). You might want to rename that method to highlight the side-effects, as it no longer would only be adding components. Perhaps, resetComponents() would be better.
After changing the components, you need to 'refresh' the Swing component by calling invalidate() or revalidate().

Categories