I have a swing application which I have declared a JButton array inside it's constructor inside that class I have created a for loop in order to add a number of 114 JButton to class container.
but when that class runs it gives the exception
java.lang.ArrayIndexOutOfBoundsException: 0
On the statement that adding the Buttons to Container.
Can someone see the problem?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener
{
public Main()
{
Container pane = getContentPane();
JPanel panel = new JPanel();
JButton b[];
int i;
for (i = 0; i < 114; i++)
{
b = new JButton[i];
panel.add(b[i]);
}
pane.add(panel);
}
public void actionPerformed(ActionEvent ae)
{
}
public static void main(String[] args)
{
Main m = new Main();
m.setSize(500, 500);
m.setVisible(true);
}
}
You can't made expression like that
for(i=0; i<114;i++)
{
b = new JButton[i];
panel.add(b[i]);
}
In first execution it is new JButton[0], so your array size is 0.
You should use Collection (fe. ArrayList) or fixed size JButton array.
JButton[] b = new JButton[114];
for(i=0; i<114;i++)
{
b[i] = new JButton();
panel.add(b[i]);
}
At i = 0, b = new JButton[i]; creates an array of size 0, so trying to reference b[0] (i.e. the first element) will be out of bounds.
And you never construct b[i].
You probably want to move the array construction outside the loop, something like:
b = new JButton[114];
for (i = 0; i < 114; i++)
{
b[i] = new JButton();
panel.add(b[i]);
}
since b is an array type which holding collection of JButton objects.So you need to create
one JButton object for each location of that array. The code what Dukeling is given is
correct approach. And also one thing you have forgotten,You need to define the size of
your array like JButton b[]=new JButton[size];
Related
I'm not certain if the title is the right way to word what I'm asking, sorry if it's not, but what I'm trying to do is create a memory match game using GUI. I have an array, and I've got the button printing an element from the array at random, but, the issue is, that I can have the same element printing multiple times. Is there a way to remove that element from being selected once it's used?
If there isn't a way to do that, any ideas on how I could go about getting it to use each element only once?
This is my current code:
package MemoryMatching;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MemoryGUI extends JFrame implements MemoryMatch, ActionListener{
JPanel mainPanel, boardPanel;
JButton [][] gridButtons = new JButton[3][4];
char cardArray[] = new char[12];
int numInPlay;
public MemoryGUI(){
cardArray[0] = 'A';
cardArray[1] = 'A';
cardArray[2] = 'B';
cardArray[3] = 'B';
cardArray[4] = 'C';
cardArray[5] = 'C';
cardArray[6] = 'D';
cardArray[7] = 'D';
cardArray[8] = 'E';
cardArray[9] = 'E';
cardArray[10] = 'F';
cardArray[11] = 'F';
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(4,3));
setBoard();
mainPanel.add(boardPanel, BorderLayout.CENTER);
add(mainPanel);
}
#Override
public void actionPerformed(ActionEvent e) {
JButton btnClicked = (JButton) e.getSource();
btnClicked.setEnabled(false);
char randomChar = cardArray[(int)new Random().nextInt(cardArray.length)];
btnClicked.setText(""+ randomChar);
faceUp();
}
#Override
public void setBoard() {
for(int x = 0; x < cardArray.length; x++) {
}
for(int row=0; row<gridButtons.length; row++){
for(int col=0; col<gridButtons[row].length;col++){
gridButtons[row][col] = new JButton();
gridButtons[row][col].addActionListener(this);
gridButtons[row][col].setText("No peeking");
boardPanel.add(gridButtons[row][col] );
faceDown();
}
}
}
#Override
public void isWinner() {
// TODO Auto-generated method stub
}
#Override
public void isMatch() {
}
#Override
public void faceUp() {
for(int x = 0; x < cardArray.length; x++) {
for(int y = 0; y < cardArray[x]; y++) {
}
}
}
#Override
public void faceDown() {
}
}
what I'm currently getting is something like
A B A
A F B
F D D
E F C
rather than:
B A C
D E F
A B C
F E D
The first example having three A and one C, rather than two of each as in the second example.
If possible I'd like to not be given the code outright, but a push towards the right direction.
A simple solution: don't use an array.
Instead, use a List<Integer> and shuffle that list. Then simply use the last element of the list for your purpose - and then remove the last element from the list; and shuffle again.
Of course, you could also write a bit of code to keep track of all indexes that you already used, and keep asking for random indexes until you get one that wasn't used before.
For your code, I think the following code would do the trick.
array = ArrayUtils.removeElement(array, element)
If you really want to use an array, look into Fisher–Yates shuffle for random shuffling of an array.
However, my recommendation would be to not use an array. Use a list as the other answer suggested.
String[] nomMois =
{"Janvier","FĂ©vrier","Mars","Avril","Mai","Juin","Juillet","Aout",
"Septembre","Octobre","Novembre","Decembre"};
JPanel tabJPanelMois[] = new JPanel[nomMois.length];
for(int indice=0; indice<tabJPanelMois.length; indice++){
tabJPanelMois[indice]= new JPanel();
tabJPanelMois[indice].setLayout(new GridLayout(0,7,8,18));
for(int j=1; j<=Date.dernierJourDuMois(indice+1,2017);j++){
tabJPanelMois[indice].add(new JButton(Integer.toString(j)));
}
I want to put an ActionListener on each Button but with that code i don't assign a name for each JButton so I can't,how must I do?
Define a temporal Button, and use it in the loop, creating a new object will allow you to recycle the variable x as much as you need:
JButton x;
for(int j=1; j<=Date.dernierJourDuMois(indice+1,2017);j++){
x = new JButton(Integer.toString(j));
x.setMyNewListener(abcListner);
tabJPanelMois[indice].add(x);
}
I am attempting to create a game of Sudoku. I am wanting to use the JSwing API. So, I am using an array of JLabels to display the grid. I have a picture drawn of a 3x3 grid, and I would like to display that in a 3x3 grid. My problem is it will not display the image. Can someone help me resolve the problem?
My Current Code looks like this, split into two class.
Main.class
package com.brendenbunker;
import javax.swing.*;
import java.awt.*;
public class Main{
FileMaker fileMaker;
void init() {
fileMaker = new FileMaker();
}
public static void main(String args[]){
ScreenGenerator gui = new ScreenGenerator();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = gui.gridPic.getIconWidth();
double height = gui.gridPic.getIconHeight();
int h = (int) height*4;
int w = (int) width*3;
gui.setSize(w,h);
gui.setTitle("Suduko");
gui.setVisible(true);
}
}
ScreenGenerator.class
package com.brendenbunker;
import javax.swing.*;
import java.awt.*;
public class ScreenGenerator extends JFrame{
//Intro Components
//JLabel temp;
JLabel[] gridLabel;
ImageIcon gridPic;
//intro Vars
public ScreenGenerator() {
setLayout(new FlowLayout());
gridPic = new ImageIcon(getClass().getResource("/Grid_Unified.png"));
gridLabel = new JLabel[8];
for (int i=0; i>=9; i++) {
gridLabel[i] = new JLabel("Hello");
}
for (int i=0; i>=9; i++) {
gridLabel[i].setIcon(gridPic);
add(gridLabel[i]);
}
}
}
All helped Appericiated
change you for loop, it will not enter into loop as per your condition.
change loop to this..
for (int i=0; i<8; i++) {
gridLabel[i] = new JLabel("Hello");
}
for (int i=0; i<8; i++) {
gridLabel[i].setIcon(gridPic);
add(gridLabel[i]);
}
it will work..
package com.brendenbunker;
import javax.swing.*;
import java.awt.*;
public class ScreenGenerator extends JFrame{
//Intro Components
//JLabel temp;
JLabel[] gridLabel;
ImageIcon gridPic;
//intro Vars
public ScreenGenerator() {
setLayout(new FlowLayout());
gridPic = new ImageIcon(getClass().getResource("/Grid_Unified.png"));
gridLabel = new JLabel[8];
//for (int i=0; i>=9; i++) {
//gridLabel[i] = new JLabel("Hello");
// }
for (int i=0; i>=9; i++) {
gridLabel[i] = new JLabel(gridPic);
add(gridLabel[i]);
}
}
}
if you need icon then use the above code if you want text and icon then the following change will help you
gridLabel[i] = new JLabel("hello", gridPic, JLabel.CENTER);
hopefully that help
Have a look at this: Displaying Image in Java
I used to program in Java. I have moved on to Python but I remember many difficulties with this! Use the IO file system to display it. You will find examples here.
Correct me if I am wrong, this is Java?
My first question here. Already got a lot of help but now I don't know how to do.
My code:
package view;
import javax.swing.*;
public class OptionPlayerNames {
JPanel playerPanel = new JPanel();
JTextField playerNames = new JTextField();
public OptionPlayerNames() {
for (int i = 0; i < 8; i++) {
// JTextField playerNames = new JTextField();
playerPanel.add(new JLabel("Player " + (i + 1)));
playerPanel.add(playerNames);
}
playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
playerPanel.add(Box.createHorizontalStrut(5));
}
public JPanel getPanel(){
return playerPanel;
}
public String getPlayerNames() {
return playerNames.getText();
}
I want to have 8 Jlabels with just under it 8 JTextFields for user input.
Then get the text of the textfields.
Now I get only 1 text from 1 textField. Off course I only add 1 field.
When I put the JTextField under the for loop I get what I want but how to I get the text from all the JTextFields then? playerNames is then not known in the getter.
Thank you for your help.
You can do as follows, creating a Listof JTextField:
JPanel playerPanel = new JPanel();
List<JTextField> playerNames = new ArrayList<JTextField>();
public OptionPlayerNames() {
for (int i = 0; i < 8; i++) {
JTextField playerName = new JTextField();
playerPanel.add(new JLabel("Player " + (i + 1)));
playerPanel.add(playerName);
playerNames.add(playerName);
}
playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
playerPanel.add(Box.createHorizontalStrut(5));
}
public JPanel getPanel() {
return playerPanel;
}
public String getPlayerNames() {
String output = "";
// Compound you exit from the playerNames List
// Or better, return a List of String
return output;
}
You need to declare a Vector or array of JTextField as an instance variable (not just one, as you've commented out) and fill it in as you loop. Then you have random (arbitrary) access to any text value. Conveniently, the index i is already there for you to index into the array.
There should be a tip-off that the type: JTextField is singular, but your variable name: playerNames is plural. :-)
Note that getPlayerNames() also needs to be re-done to handle an array not a single field.
While this will work, ultimately, the whole code block isn't good separation of Model & View, so as you advance in programming, be sure to pay attention to that concept.
In short, I would like to accumulate a bunch of JButton's to an array, and create one ActionListener class for the array.
I'm trying to create a calculator, and all the numbered buttons, such as "6", are in a JButton array, because I would like to have it input the set number into a temporary int, and it would be easier to create one method, instead of 10. I also have 40 other buttons, that I would like to apply the same principal to, but in a different array, so it would be much faster and easier to put these into a couple of ActionListener methods where the buttons data is implemented to that method.
this is the code I have:
private JButton num0, num1, num2, num3, num4, num5, num6, num7, num8, num9;
private JButton numArray[] = {num0, num1, num2, num3, num4, num5, num6, num7, num8, num9};
public GUI(){
numArray.AddActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
}
});
}
You can consider the proposal of Newb Monad. However, you can use the same listener for all your buttons, as in the following example.
public static void main(String[] args) {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
String text = ((JButton) e.getSource()).getText();
JOptionPane.showMessageDialog(null, text);
}
}
};
JPanel panel = new JPanel(new GridLayout(4,3));
JButton[] array = new JButton[10];
for (int i = 0; i < array.length; i++) {
array[i] = new JButton(String.valueOf(i));
array[i].addActionListener(listener);
panel.add(array[i]);
}
JOptionPane.showMessageDialog(null, panel);
}
You have the right idea. However, array objects do not have an addActionListener() method. You must add an action listener to each JButton individually. You can use the same listener for every button, but then you have to figure out which button was clicked inside the actionPerformed() method. IMO, a cleaner solution is to assign a separate listener to each JButton because that way each ActionListener can know which number is pressed without checking the source of the event. For example, you can create a NumberButtonListener class which takes an int as the only argument to its constructor. You can then create the JButtons and the corresponding NumberButtonListeners at the same time in a small loop.
This seems to work well for me.
I essentially loop through all of the buttons while checking it against the action (e.getSource()).
public void actionPerformed(ActionEvent e){
//loop through allbuttons to check if clicked
for(int i = 0; i < buttonArr.length; i++){
for(int j = 0; j < buttonArr[0].length; j++){
if(e.getSource() == buttonArr[i][j]){
//do stuff
}
}
}
}
I had a similar problem with a 2D array of buttons for a game of "Connect Four". I was able to use a for loop inside ActionListener to test which of my buttons had been pushed. The key was modifying the toString() method from my button class to supply the array element as a string:
Within the JPanel class definition:
...
discs = new RoundButton[6][7]; //my 2D array
...
public class RoundButton extends JButton {
...
public String toString() {
return "discs["+i+"]["+j+"]";
}
...
}
private class ButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent event) {
for (int i = 0; i < discs.length; i++){
for (int j= 0; j < discs[i].length; j++){
if (event.getSource() == discs[i][j]){
discs[i][j].setIcon(yellowDisc); //my particular action for that button
}
}
Sorry this is messy. I've never posted on here before.