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?
Related
(general idea of what I'm doing and what I have)
I am trying to create a simple game where the user will need to guess the right spots in a 5x5 square grid based on luck. I would like to have the program create random spots (approx. 3-5) where the user will need to find each spot. So far I have the overall layout of the frame with a "life" counter that will go down every time the user clicks on the wrong spot. Temporarily, I hard-coded 3 spots the user will need to find named "hit". I'm still working on a way to implement a random number system where the correct spots will be made at random. This code is not complete so don't mind empty methods.
(Here is my code, main method class below this Display class)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Display implements ActionListener{
int lives = 3;
int[] hit = {10,2,22};
JFrame frame = new JFrame();
JPanel tile_panel = new JPanel();
JButton[] button = new JButton[25];
JTextField title = new JTextField();
JTextField life_label = new JTextField();
JLabel life_counter = new JLabel();
public Display(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,600);
frame.getContentPane().setBackground(Color.GRAY);
frame.setLayout(null);
title.setBounds(0,0,600,75);
title.setBackground(Color.GRAY);
title.setForeground(Color.GREEN);
title.setFont(new Font("Ink Free", Font.BOLD, 50));
title.setEditable(false);
title.setHorizontalAlignment(JTextField.CENTER);
title.setBorder(null);
title.setText("Sequence Game");
life_label.setBounds(480,260,100,25);
life_label.setBackground(Color.GRAY);
life_label.setForeground(Color.GREEN);
life_label.setFont(new Font("Roboto",Font.PLAIN,25));
life_label.setText("Lives: ");
life_label.setBorder(null);
life_label.setEditable(false);
life_counter.setBounds(500,300,100,25);
life_counter.setForeground(Color.GREEN);
life_counter.setFont(new Font("Roboto",Font.PLAIN,25));
life_counter.setText(String.valueOf(lives));
tile_panel.setBounds(25,120,400,400);
tile_panel.setBackground(Color.GRAY);
tile_panel.setLayout(new GridLayout(5,5, 1,1));
for (int i = 0; i < button.length; i++){
button[i] = new JButton();
button[i].setSize(80,80);
button[i].addActionListener(this);
tile_panel.add(button[i]);
}
frame.add(tile_panel);
frame.add(life_label);
frame.add(life_counter);
frame.add(title);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
boolean correct = false;
for(int i = 0; i < button.length; i++){
if (e.getSource() == button[i]){
for (int k = 0; k < hit.length; k++){
if (hit[k] == i){
button[i].setBackground(Color.GREEN);
correct = true;
}
}
if (correct == false){
button[i].setBackground(Color.RED);
lives--;
life_counter.setText(String.valueOf(lives));
}
i = button.length;
}
}
}
public void results(){
}
}
public class Main{
public static void main(String[] args){
new Display();
}
}
However, my problem is that the code I currently have doesn't work on Mac. For example, my font of the words don't show up properly, and most importantly my tiles don't change color like it should be doing. Funny enough, my code can only run properly on a Windows device.
Is there anyone that knows the reason for this?
The tiles aren't changing color on Mac because of the UI's default look and feel. I have the same issue on my Mac due to com.apple.laf.AquaLookAndFeel. You can switch to a cross-platform L&F like Metal: UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
I am trying to make a connect four gui.
I have a class Gui which creates a board ( an array[][] ints) and a method move- which accepts the player(int) and column(int)- and a method to check if there is a winner.
I created a gui with the gridLayout and I have a row of buttons and 7 arrays of JLabels (that are an ImageIcon of empty slot) I need to now access the bottommost JLabel of a specific array if a player chooses that column.
I created the buttons in a loop:
A) how do I access each button- they do not have unique names.
B) how do I access each JLabels- they were also created in a loop
C) where am I suppose to instantiate my Board Class?
D) when I am adding each new object in the gui I have
this.add(JLabel)--
how do I put all that into a new Panel so I can have a title bar on top of my grid?
my code for the gui
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class ConnectFourGui extends JFrame {
private JLabel title;
private JButton button;
ImageIcon[] emptySlot;
ImageIcon arrow;
public ConnectFourGui() {
this.setTitle("Connect Four");
this.setSize(800, 800);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel panel = new JPanel();
//Container container = this.getContentPane();
this.setLayout(new GridLayout(7, 7));
this.title = new JLabel("Connect Four");
title.setForeground(Color.RED);
title.setFont(new Font("Sans-Serif", Font.BOLD, 50));
title.setHorizontalAlignment(SwingConstants.CENTER);
for (int i = 0; i < 7; i++){
arrow = new ImageIcon("arrowButton.png");
this.button = new JButton(arrow);
this.add(button);
}
for (int i = 0; i < 7; i++){
emptySlot = new ImageIcon[6];
for (int j = 0; j<6;j++){
emptySlot[j] = new ImageIcon("emptySlot.png");
this.add(new JLabel(emptySlot[j]));
}
}
Try making seperate arrays for each column like this (see code below). Also make your array an array of JLabels instead of ImageIcons. And create each button with a unique name.
column1 = new JLabel[6];
column2 = new JLabel[6];
column3 = new JLabel[6];
column4 = new JLabel[6];
column5 = new JLabel[6];
column6 = new JLabel[6];
column7 = new JLabel[6];
for (int j = 0; j < 6; j++) {
column1[j] = new JLabel(emptySlot);
column2[j] = new JLabel(emptySlot);
column3[j] = new JLabel(emptySlot);
column4[j] = new JLabel(emptySlot);
column5[j] = new JLabel(emptySlot);
column6[j] = new JLabel(emptySlot);
column7[j] = new JLabel(emptySlot);
this.add(column1[j]);
this.add(column2[j]);
this.add(column3[j]);
this.add(column4[j]);
this.add(column5[j]);
this.add(column6[j]);
this.add(column7[j]);
}
To accces an element in the array per the button on top do something like this
buttonName.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a) {
column1[3].setIcon(newIcon);
}
}
you would be using a variable instead of the number 3 I used as an example
Instantiate your board class in your constructor.
I'm building a board game for a cs course, I've started with the engine - its backbone - and I've perfected it, I'm still stuck on the GUI part though. In the engine, I have a double array that initialises the board with the pieces, and it has a getWinner and move methods. In the GUI part, I created my JFrame and set its layout to gridlayout, and I've another double array there that checks the engine's array and prints the board with the board pieces accordingly.. however, whenever I move, the engine's array registers the move but it doesn't get displayed on my JFrame.. I've no idea on how to do it..
Here's my Main class in the GUI package:
package eg.edu.guc.loa.gui;
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import eg.edu.guc.loa.engine.*;
import eg.edu.guc.loa.engine.Point;
#SuppressWarnings("serial")
public class LOA extends JFrame{
static Tiles[][] Jboard;
static Board b = new Board();
static Color temp;
static Color col1 = Color.DARK_GRAY;
static Color col2 = Color.LIGHT_GRAY;
static JFrame LOA = new JFrame();
JButton b1, b2;
public LOA(){
Jboard = new Tiles[8][8];
LOA.setLayout(new GridLayout(8, 8));
initBoard();
LOA.setSize(600, 600);
LOA.setVisible(true);
LOA.setLocationRelativeTo(null);
LOA.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.printBoard();
}
public static void initBoard(){
remove();
b.printBoard();
for(int i = 0; i<8; i++){
if (i%2 == 0){
temp = col1;
}
else{
temp = col2;
}
for(int j = 0; j<8; j++){
Jboard[i][j] = new Tiles(temp, i, j);
LOA.getContentPane().add(Jboard[i][j]);
if (temp.equals(col1)){
temp = col2;
}
else{
temp = col1;
}
if(b.getPiece(new Point(j, i)).getPlayer() == BoardCell.PLAYER_1_PIECE){
Jboard[i][j].hasChecker(true);
Jboard[i][j].setWhite(true);
Jboard[i][j] = new Tiles(temp, i, j);
}
if(b.getPiece(new Point(j, i)).getPlayer() == BoardCell.PLAYER_2_PIECE){
Jboard[i][j].hasChecker(true);
Jboard[i][j].setWhite(false);
Jboard[i][j] = new Tiles(temp, i, j);
}
}
}
}
public static void remove(){
for(int i = 0; i<8;i++){
for(int j = 0; j<8; j++){
if(Jboard[i][j] != null)
LOA.remove(Jboard[i][j]);
}
}
}
public static void main (String [] args){
new LOA();
}
}
Any help will be much appreciated.. Thanks in advance.
EDIT:
b.print() prints the Engine's array on the console, and remove() is just my attempt on removing the old frame and building a new one based on the new updated array (with moved piece), which obviously failed.
As shown in this much simpler MVCGame, you can arrange for your view to register as a listener to your model using the observer pattern. User gestures should update the model; when notified by the model, the view should simply render the current state of the model. There should be no drawing in the model and no game logic in the view.
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];
I have created a grid that contains 10x10 buttons using 2d arrays. i tried x.getSource().getLabel() but compiler says they are not compatible. also i want to get the specific button that was clicked.
I want to get the exact button that was clicked from the grid i made and get its label. what method i need to use?
import javax.swing.JFrame; //imports JFrame library
import javax.swing.JButton; //imports JButton library
import java.awt.GridLayout; //imports GridLayout library
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class ButtonGrid extends JFrame implements ActionListener
{
JFrame frame=new JFrame(); //creates frame
JButton[][] grid; //names the grid of buttons
public int x;
public int y;
public ButtonGrid(int width, int length)
{ //constructor
char temp;
String charput;
frame.setLayout(new GridLayout(width,length)); //set layout
grid = new JButton[width][length]; //allocate the size of grid
for(int y=0; y<length; y++)
{ //start
for(int x=0; x<width; x++)
{
temp=charRand(); //get random character
charput = ""+temp; //converts character to string
grid[x][y]=new JButton(); //creates new button
frame.add(grid[x][y]); //adds button to grid
grid[x][y].addActionListener(this);
grid[x][y].setLabel(charput); //set charput as label
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
/* generates randomiz letter for the button of the grid*/
public char charRand()
{
String consonantList = new String("BCDFGHL"); //list 1
String consonantList2 = new String("MNPRSTWY"); //list 2
String consonantList3= new String("JQXZVK"); //list 3
String vowelList = new String("AEIOU"); //list of vowels
int vowelOrConsonant; //holder of random number
int chosen; //selects the chosen random letter
Random randGen = new Random(); //generates random int value
char selected; //gets the random letter chosen by variable chosen
vowelOrConsonant = randGen.nextInt(4);
if (vowelOrConsonant == 0)
{
chosen = randGen.nextInt(5); //list of vowels
selected = vowelList.charAt(chosen); //selects a char from vowels
}
else if(vowelOrConsonant == 1)
{
chosen = randGen.nextInt(7); //list 1
selected = consonantList2.charAt(chosen); //selects a char
}
else if(vowelOrConsonant == 2)
{
chosen = randGen.nextInt(8); //list 2
selected = consonantList2.charAt(chosen); //selects a char
}
else
{
chosen = randGen.nextInt(6); //list 3
selected = consonantList.charAt(chosen);
}
return selected; //returns the random letter
}
public static void main(String[] args)
{
new ButtonGrid(10,10);//makes new ButtonGrid with 2 parameters
}
public void actionPerformed(ActionEvent x)
{
/* i get wrong output on this line.
* i want to get the exact button that was clicked and get its label.
*/
if (x.getSource()==grid[x][y])
JOptionPane.showMessageDialog(null,x.getSource().getLabel);
}
}
getSource() returns an Object, so you need to cast it to JButton, like this:
public void actionPerformed(ActionEvent x) {
JOptionPane.showMessageDialog(null, ((JButton)x.getSource()).getText());
}
Also note that getLabel() and setLabel() are deprecated and should be replaced by getText() and setText().
You can make a class that extends Jbutton. and add two fields to it of type int(X & Y ). The constructor will look like this: public MyButton(int x, y);
And when you are filling your grid, don't use directly the Jbutton class. Use your class and for X & Y supply the i & j parameters of the two for cycles that you are using. Now when you are using Action Listener for your button you can use his X & Y fields as they represent its place on the grid. Hope this helps! It tottaly worked for me and its simple as hell.