I have a little issue with selecting from an array list. I am writing some code to enable me fix about 10 JButtons in a circle, I got that right, but then ..... I want to set an actionListener on each of the Buttons, but I don't get it, all the buttons inherit the actions required for one. How do I make it specific,... here's my code.... Thanks in advance!
private JButton quest;
public Beginner() {
int n = 10; // no of JButtons
int radius = 200;
Point center = new Point(250, 250);
double angle = Math.toRadians(360 / n);
List<Point> points = new ArrayList<Point>();
points.add(center);
for (int i = 0; i < n; i++) {
double theta = i * angle;
int dx = (int) (radius * Math.sin(theta));
int dy = (int) (radius * Math.cos(theta));
Point p = new Point(center.x + dx, center.y + dy);
points.add(p);
}
draw(points);
}
public void draw(List<Point> points) {
JPanel panels = new JPanel();
SpringLayout spring = new SpringLayout();
// Layout used
int count = 1;
for (Point point : points) {
quest = new JButton("Question " + count);
quest.setForeground(Color.BLUE);
Font fonte = new Font("Script MT Bold", Font.PLAIN, 20);
quest.setFont(fonte);
add(quest);
count++;
spring.putConstraint(SpringLayout.WEST, quest, point.x, SpringLayout.WEST, panels);
spring.putConstraint(SpringLayout.NORTH, quest, point.y, SpringLayout.NORTH, panels);
setLayout(spring);
panels.setOpaque(false);
panels.setVisible(true);
panels.setLocation(10, 10);
add(panels);
// action Listener to be set on individual buttons
quest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a) {
if (quest.equals(points.get(5)))
;
String c = "Hello!";
JOptionPane.showMessageDialog(null, c);
}
});
}
}
The problem is that expression
if (quest.equals(points.get(5)));
does nothing. I guess it should be rewritten like this
if (quest.equals(points.get(5))) {
String c = "Hello!";
JOptionPane.showMessageDialog(null, c);
}
The way I am understanding the question is that you have multiple buttons and you would like each button to have it's own action associated with it. There are a couple ways to go about doing this. Either you create a new ActionListener for each JButton depending which button you are creating.
You can also create a large case/switch or if/else within the ActionListener that gets determined by which button was selected. To do this you can call the getActionCommand() function for the ActionEvent object.
quest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a) {
if (a.getActionCommand().equals("Question 1"))
{
String c = "Hello!";
JOptionPane.showMessageDialog(null, c);
}
else if(a.getActionCommand().equals("Question 2"))
{
//have it do something else
}
//and so on so forth
}
});
You need to rethink the entire design. You have this line:
if (quest.equals(points.get(5))) {
But points is a list containing Point objects; points.get(5) returns a Point.
quest is a JButton. How can a JButton instance equal a Point instance?
Related
I have a little better than beginner level understanding of Java and I am having trouble with a student assignment. I had to turn a class (student.java) "into a button" - which I have done (that's why instead of creating a new instance of JButton, my code creates a new instance of "student"). I need to have the button relocate its position to wherever the user clicks the mouse. I have successfully done that, so my assignment requirements have been met.
However, I would like to have the button move smoothly to the location of the mouse click, as opposed to abruptly jumping from the previous position to the new position. Below is my code. The maths inside of the mouseClicked() method is what I have tried, but it has no effect on the motion of the button.
null layout is required
must use MouseListener (not ActionListener)
button must be an instance of class student
Any tips would be greatly appreciated. Thank you!
public myJPanel(){
super();
setLayout(null);
setBackground(Color.decode("#F5F2EB"));
setVisible(true);
setPreferredSize(new Dimension(640,480));
setMinimumSize(new Dimension(640,480));
setMaximumSize(new Dimension(640,480));
Font f = new Font("Copperplate Gothic Bold", Font.BOLD, 16);
student btn = new student("First","Last", num, "");
add(btn);
btn.setBounds(100, 150, 400, 90);
btn.setText(btn.getInfo());
btn.setBackground(Color.decode("#89A690"));
btn.setForeground(Color.decode("#F5F2EB"));
btn.setOpaque(true);
btn.setFont(f);
btn.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40));
// move btn object
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x = e.getX(); //mouse click x position
int y = e.getY(); //mouse click y position
int px = btn.getX() - x; //previous btn x position(to get distance between old / new position)
int py = btn.getY() - y; //previous btn y position(to get distance between old / new position)
double speed = 5; //speed
double ang = (float)Math.atan2(py, px) * 180 / Math.PI; //angle
x += Math.cos(ang * Math.PI/180) * speed; //move to x
y += Math.sin(ang * Math.PI/180) * speed; //move to y
btn.setLocation(x,y); //relocate button to new location
}});
You need some kind of animation concept in your code, simply updating the location will not move it smoothly. Changes you require
remove setLocation() code from mouse listener
a timer to trigger calculation and update of button position
interpolation of current position given elapsed time, angle etc.
Example. Here I've calculated total distance, and then interpolated "distance so far" based on time and speed.
Also note use of Math.toDegrees() and Math.toRadians(), although you don't really need them at all unless you want to use ang as degrees elsewhere...
public class Foo {
private static class Animate extends JPanel {
private JButton btn;
private int startX;
private int startY;
private long startTime;
private double ang;
private double distance;
public Animate() {
super();
setLayout(null);
btn = new JButton("Dr Horse");
btn.setBounds(100, 150, 40, 10);
add(btn);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
startX = btn.getX();
startY = btn.getY();
startTime = System.nanoTime();
int px = btn.getX() - e.getX();
int py = btn.getY() - e.getY();
distance = Math.sqrt(px * px + py * py);
ang = Math.toDegrees(Math.atan2(py, px));
}
});
Timer timer = new Timer(1000 / 20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
double duration = (System.nanoTime() - startTime) / 1e6;
int speed = 50;// pixels per second
double distanceSoFar = Math.min(speed * duration / 1000d, distance);
int x = startX - (int) (distanceSoFar * Math.cos(Math.toRadians(ang)));
int y = startY - (int) (distanceSoFar * Math.sin(Math.toRadians(ang)));
btn.setLocation(x, y);
}
});
timer.setRepeats(true);
timer.start();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new Animate());
frame.setSize(500, 400);
frame.setVisible(true);
}
}
I'm working on a project and the general idea of my work is to do every part of it in a stand alone project, then add it when finished to the main project through libraries.
My problem is - one part I have done was to perform a painting on a panel.
When I add a layer pane which connects it to the main project , there is no drawing actually happening.
Here is my project sample code:
In code sample 1 there is JLayeredPane which contains my panel to perform drawing.
In code sample 2 there is a button. Its actionPerformed is to add that JLayeredPane to a panel. But the problem is that the drawing is not appearing after adding the JLayeredPane.
Code sample 1:
public class GraphGui extends javax.swing.JFrame {
/**
* Creates new form GraphGui
*/
adjacencyMatrix m = new adjacencyMatrix();
Dfs df = new Dfs();
int[] x = new int[df.MAX_VERTS];
int[] y = new int[df.MAX_VERTS];
public Graphics2D d;
public Graphics2D doo;
int i = 0;
public GraphGui() {
setlookAndFeel();
initComponents();
setLocationRelativeTo(null);
DFS.setVisible(true);
adjMatrics.setVisible(false);
//display is the panel that draw over
d = (Graphics2D) display.getGraphics();
doo = (Graphics2D) jPanel2.getGraphics();
}
//crating an initialization of components are done automatically
public void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
df.dfs();
doo.setFont(new Font("TimesRoman", Font.BOLD, 19));
doo.drawString("visits: " + df.out, 5, 20);
df.out = "";
}
public void AddE1ActionPerformed(java.awt.event.ActionEvent evt) {
String j = start1.getText();
int k = Integer.parseInt(j) - 1;
String c = end1.getText();
int v = Integer.parseInt(c) - 1;
df.addEdge(k, v);
d.setFont(new Font("TimesRoman", Font.BOLD, 17));
d.drawLine(x[k] + 30, y[k] + 20, x[v], y[v] + 19);
}
public void AddV1ActionPerformed(java.awt.event.ActionEvent evt) {
String f = ver1.getText();
String toUpperCase = f.toUpperCase();
char r = toUpperCase.charAt(0);
df.addVertex(r);
int radius = 30;
int R = (int) (Math.random() * 256);
int G = (int) (Math.random() * 256);
int B = (int) (Math.random() * 256);
x[i] = R % 320;
y[i] = B % 167;
d.setColor(new Color(R, G, B));
d.setFont(new Font("TimesRoman", Font.BOLD, 15));
d.drawOval(x[i], y[i], radius, radius);
d.fillOval(x[i], y[i], radius, radius);
d.setColor(Color.BLACK);
d.drawString(r + "", x[i] + 10, y[i] + 20);
d.drawOval(0, 0, radius, radius);
i++;
}
What code sample 1 is supposed to do is shown at this link:
https://pbs.twimg.com/media/CG8INXZXAAEqthh.png:large
Code Sample 2
{
private void graphBTActionPerformed(java.awt.event.ActionEvent evt) {
GraphGui gr=new GraphGui();
jPanel2.removeAll();
jPanel2.add(gr.DFS);
MainLayer.setVisible(false);
Displaylayer.setVisible(true);
}
}
And at the link below is what I got after adding the panel-
nothing draws.
https://pbs.twimg.com/media/CG8IR7rWoAA3qKG.png:large
There are 2 separate issues here.
(1) Simplest answer is - you need to call 'getGraphics' from within your action method. Not from the constructor. E.g.
public void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Graphics2D doo = (Graphics2D) jPanel2.getGraphics();
...
doo.setFont(...);
doo.drawString(...);
}
(2) This would yield visible drawings, but they'll disappear whenever java decides to repaint - e.g. if you minimize the frame. This can be solved by paintComponent() as mentioned in the remarks. The basic idea is that your component (eg jPanel2) would hold a data structure of eveything it needs to paint - Strings, edges, vertexes etc. In paintComponent you draw them all. In actionPerformed() you change the datastructure and invoke 'repaint'. A sketch of this approach:
class MyPanel extends JPanel{
private String text;
private Point[] vertextes;
public void addVertext(..)
public void paintComponent(Graphics g){
... use g to drawString, drawOval... according to 'text' and 'vertexes'
}
}
// Then in your JFrame:
private MyPanel p;
...
actionPerfomred(...){
p.addVertext(..)
p.repaint();
}
In short, I want to set the text of a JLabel to be that of a JTextField in a JPanel (pnlUser) and then drag the JLabel across the screen from JPanel onto another JTextField in another JPanel (pnlGrid).
Here are the details.
I have written a "Solitaire Scrabble" program. The user can either position the text cursor in a grid cell (a JTextField in pnlGrid) and type a letter that is in the list of "User letters" (a JTextField in pnlUser) OR the user can simulate dragging a letter from "User letters" and dropping it into the destination grid cell in pnlGrid.
I say "simulate" because the selected letter is not actually dragged across the screen. I use the mouse pointer HAND_CURSOR to make the drag/drop as real as possible, but I haven't figured out how to make the HAND_CURSOR "grab" the letter and physically drag the letter across the board to its destination.
As it is, the letter is highlighted but left in the "User letters" area while the HAND_CURSOR moves along the grid during the drag operation. When it gets to the destination cell in pnlGrid and the mouse button is released, the letter is erased from "User letters" and suddenly appears in the grid cell.
So the letter is more or less "teleported" (beam me up, Scotty) from "User letters" to a grid cell. This is too abstract. I want the user letter to be at the tip of the HAND_CURSOR's pointing finger and be dragged along the grid into the grid cell where it will be dropped, as shown in the 3 pictures below.
I've successfully made it happen in a small test program (source below) using JLayeredPane, but I can't make it happen in the game. But I knew nothing about JLayeredPane until two days ago so I don't really know what I'm doing. (I adapted an Oracle tutorial program that demos JLayeredPane.)
I just read about the "glass pane" and thought it would maybe be easier to implement until I downloaded the source for that demo, which is quite long, so since it's totally new and will be even harder to adapt.
So I thought before I spend more hours in frustration I should ask:
Is a JLayeredPane or a setGlassPane approach appropriate? Is there an easier or better way to drag a JLabel from one JPanel onto another another JPanel?
(The approach in the program is to determine which "User letter" is being pointed at, store that letter in a JLabel, and then make sure that during mouseDragged the HAND_CURSOR fingertip is right at the bottom center of the letter.)
package mousemoveletter;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import static java.awt.Color.*;
import java.awt.event.*;
import static javax.swing.SwingUtilities.invokeLater;
public class LayeredPaneDemo extends JPanel
{
private static final int USER7 = 7;
static Cursor HAND = new Cursor(Cursor.HAND_CURSOR);
static Cursor ARROW = new Cursor(Cursor.DEFAULT_CURSOR);
private static JLayeredPane layeredPane;
private static JLabel lblToMove;
private static JPanel pnlUser;
private static JPanel pnlGrid;
private static final JTextField[] txtUser = new JTextField[USER7];
public LayeredPaneDemo() // constructor
{
pnlGrid = new JPanel();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(240, 240));
pnlGrid.setSize(140, 140);
pnlGrid.setBorder(new EtchedBorder(RED, GREEN));
pnlGrid.setBackground(YELLOW);
lblToMove = new JLabel("XXX");
lblToMove.setSize(new Dimension(40,40));
layeredPane.add(pnlGrid, 0,0);
layeredPane.add(lblToMove, new Integer(0), -1);
add(layeredPane);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("LayeredPaneDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new LayeredPaneDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
makeUser();
frame.add(pnlUser);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
invokeLater(new Runnable()
{
public void run() {
createAndShowGUI();
}
});
}
private static void makeUser(){
pnlUser = new JPanel(new GridLayout(1,USER7));
pnlUser.setPreferredSize(new Dimension(225, 50));
pnlUser.setBackground(Color.green);
pnlUser.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for(int k = 0; k < USER7; k++)
{
txtUser[k] = new JTextField("" + (char)(Math.random()*26+65));
txtUser[k].setName("" + k);
txtUser[k].setEditable(false);
txtUser[k].addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent e)
{
lblToMove.setCursor(HAND);
int w = Integer.parseInt(e.getComponent().getName());
lblToMove.setText(txtUser[w].getText());
layeredPane.setLayer(lblToMove, 0, 0);
lblToMove.setLocation(e.getX() + (e.getComponent().getWidth())*w,
e.getY() + layeredPane.getHeight() - e.getComponent().getHeight()/2);
};
});
txtUser[k].addMouseListener(new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
lblToMove.setCursor(ARROW);
}
});
pnlUser.add(txtUser[k]);
}
}
}
Thanks to #trashgod, I figured it out by following his links to this example and variation; I adapted the drag/drop of the chessboard found there to my own particular needs for "Scrabble".
The code below is not final code for my Solitaire Scrabble program, but proof-of-concept, possibly usable by others wishing to drag a cell from a 1xN grid onto a MxM grid.
package components;
import java.awt.*;
import static java.awt.BorderLayout.NORTH;
import static java.awt.BorderLayout.SOUTH;
import java.awt.event.*;
import static java.lang.Integer.parseInt;
import javax.swing.*;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import javax.swing.event.MouseInputAdapter;
public class ChessBoard //implements MouseListener, MouseMotionListener
{
static Point parentLocation;
int homeRow, homeCol; // where to restore moved user letter if dropped on occupied cell
static int N = 11; // NxN 'chessboard' squares
static int S = 44; // square dimensions: SxS
static int W ; // chessboard dimensions: WxW
static int USER7 = 7;
static Font dragFont;
static JFrame frame;
JLayeredPane layeredPane;
static JPanel gamePanel, // encompasses both pnlGrid and pnlUser
pnlGrid,
pnlUser;
JLabel userDragLetter = new JLabel(); // main item to drag around or restore if needed
int xAdjustment, yAdjustment; // how to locate drops accurately
String userLetters[] ;
public ChessBoard() // constructor
{
W = S*N;
dragFont = new Font("Courier", Font.PLAIN, S);
userLetters = new String[USER7];
for (int i = 0; i < USER7; i++)
userLetters[i] = "" + (char)(65 + Math.random()*26);
Dimension gridSize = new Dimension(W, W);
Dimension userSize = new Dimension(W, S);
Dimension gameSize = new Dimension(W, (W + S));
frame = new JFrame();
frame.setSize(new Dimension(gameSize)); // DO NOT USE PREFERRED
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize( gameSize ); // NO PREFERRED => NO GRID!
gamePanel = new JPanel();
// **EDIT** LOSE THIS LINE gamePanel.setLayout(new BorderLayout());
gamePanel.setPreferredSize(gameSize);
pnlGrid = new JPanel();
pnlGrid.setLayout(new GridLayout(N, N));
pnlGrid.setPreferredSize( gridSize );
pnlGrid.setBounds(0, 0, gridSize.width, gridSize.height);
pnlUser = new JPanel();
pnlUser.setLayout(new GridLayout(1, N));
pnlUser.setPreferredSize(userSize);
pnlUser.setBounds(0, gridSize.height, userSize.width, userSize.height);
layeredPane.add(pnlGrid, JLayeredPane.DEFAULT_LAYER); // panels to drag over
layeredPane.add(pnlUser, JLayeredPane.DEFAULT_LAYER); // " "
for (int i = 0; i < N; i++){
for (int j = 0; j < N; j++){
JPanel square = new JPanel();
square.setBackground( (i + j) % 2 == 0 ? Color.red : Color.white );
pnlGrid.add( square );
}
}
for (int i = 0; i < N; i++) {
JPanel square = new JPanel(new BorderLayout());
square.setBackground(Color.YELLOW);
pnlUser.add(square);
}
for (int i = 0; i < USER7; i++)
addPiece(i, 0, userLetters[i]);
gamePanel.addMouseListener(new MouseInputAdapter()
{
public void mousePressed (MouseEvent e){mousePressedActionPerformed (e);}
public void mouseReleased(MouseEvent e){mouseReleasedActionPerformed(e);}
});
gamePanel.addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent me){mouseDraggedActionPerformed(me);}
});
// **EDIT: LOSE THE NEXT TWO LINES AND REPLACE BY THE LINE AFTER THEM**
// gamePanel.add(layeredPane, NORTH);
// gamePanel.add(pnlUser, SOUTH);
gamePanel.add(layeredPane);
}
private void addPiece(int col, int row, String glyph) {
JLabel piece = new JLabel(glyph, JLabel.CENTER);
piece.setFont(dragFont);
JPanel panel = (JPanel) pnlUser.getComponent(col + row * N);
piece.setName("piece " + glyph + " # " + row + " " + col);
panel.add(piece);
}
void mousePressedActionPerformed(MouseEvent e)
{
userDragLetter = null; // signal that we're not dragging if no piece is in the square
gamePanel.setCursor(new Cursor(Cursor.HAND_CURSOR));
Component c = pnlGrid.findComponentAt(e.getX(), e.getY());
if(c != null)
return; // Illegal to click pnlGrid
c = pnlUser.findComponentAt(e.getX(), e.getY() - pnlGrid.getHeight());
if(c == null | c instanceof JPanel)
return; // letter already played; can't drag empty cell
parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY() + gamePanel.getHeight() - pnlUser.getHeight();
userDragLetter = (JLabel)c;
userDragLetter.setPreferredSize(new Dimension(S, S)); // prevent 2 letters in a square
userDragLetter.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
layeredPane.add(userDragLetter, JLayeredPane.DRAG_LAYER);
homeRow = parseInt(userDragLetter.getName().substring(10,11)); // save restore location
homeCol = parseInt(userDragLetter.getName().substring(12,13));
}
void mouseDraggedActionPerformed(MouseEvent me)
{
if (userDragLetter == null)
return; // nothing to drag
int x = me.getX() + xAdjustment; // make sure grid cell will be chosen in-bounds
int xMax = layeredPane.getWidth() - userDragLetter.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = layeredPane.getHeight() - userDragLetter.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
if(y >= pnlGrid.getHeight())
return; // can't drag to location off grid
userDragLetter.setLocation(x, y);
}
void mouseReleasedActionPerformed(MouseEvent e)
{
//**EDIT: CHANGED NEXT LINE**
gamePanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
if (userDragLetter == null)
return; // nothing to drag; nothing to release
// Make sure the chess piece is no longer painted on the layered pane
userDragLetter.setVisible(false);
layeredPane.remove(userDragLetter);
userDragLetter.setVisible(true);
int xMax = layeredPane.getWidth() - userDragLetter.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = layeredPane.getHeight()- userDragLetter.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = pnlGrid.findComponentAt(x, y); // find deepest nested child component
if(c == null) // then grid cell is unoccupied so ...
c = pnlUser.findComponentAt(x, y); // see if there's a letter there ...
if(c == null | (c instanceof JLabel)){ // and if illegal or there is one, put it back...
userDragLetter.setLocation(parentLocation.x + xAdjustment,
parentLocation.y + yAdjustment + gamePanel.getHeight());
userDragLetter.setVisible(true);
addPiece(homeCol, homeRow,userDragLetter.getName().substring(6,7));
layeredPane.remove(userDragLetter);
return;
}
else // but if NO letter ...
{
Container parent = (Container)c;
parent.add( userDragLetter ); // put one in the grid cell
parent.validate();
}
userDragLetter.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
public static void main(String[] args)
{
new ChessBoard();
frame.add(gamePanel);
frame.setDefaultCloseOperation( DISPOSE_ON_CLOSE );
// frame.setResizable( false );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
This is what I am having trouble with. I am making a Keno game out of a Crystals code I was given. So far, I have been able to choose 20 of the 80 and turn them red. However, I have the button set to when I press it it says "Game is a draw" and the window closes.
I am trying to put in a code where it will randomly draw 20 numbers without repeating, and then they turn yellow, however, if the CPU and the human match a number, it will turn green. I have no idea how to start this code or how to go about doing it. Here is what I have:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.lang.String;
public class Kenogame {
// constants
public static final int WIDTH = 4;
public static final int HEIGHT = 20;
public static final int INITIAL = 0;
public static final int RED = 1;
public static final int YELLOW = 3;
public static final int CHECKED = 4;
private int turn = RED; // to track which player should play next
private int[][] playerGrid; // to record each player's move
private int[][] shadowGrid; // to keep track of which atoms have been FOUND
private int[][] crystalGrid; // to extract a single crystal from playerGrid
private int row, column; // position of most recently added atom
private int lowX, lowY, highX, highY; // corner coordinates of current crystal
private int player1Score = 0;
private int player2Score = 0;
// GUI related fields
private JButton[] buttonArray;
// private JTextField scoreField1;
// private JTextField scoreField2;
// private JLabel labelRED; // Label "Red" on GUI
// private JLabel labelYELLOW; // Label "Yellow" on GUI
private JLabel labelTurn; // Label displays whose turn is next
private int numberToSelect = 20;
Kenogame() {
createGUIAndPlay();
}
private void createGUIAndPlay() {
final JFrame f = new JFrame();
// create the panels
JPanel topPanel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel(new GridLayout(WIDTH, HEIGHT));
JPanel labelPanel = new JPanel();
// represents the 2D grid of buttons on the GUI
buttonArray = new JButton[WIDTH * HEIGHT];
// stores the positions of atoms in both player's crystals
playerGrid = new int[WIDTH][HEIGHT];
// shadowGrid keeps track of which atoms have been found
shadowGrid = new int[WIDTH][HEIGHT];
// used to store a crystal to determine if it is a perfect crystal
crystalGrid = new int[WIDTH][HEIGHT];
JButton endGameButton = new JButton("Start Draw");
// labelRED = new JLabel("Red");
// scoreField1 = new JTextField(3);
// scoreField1.setEditable(false);
//labelYELLOW = new JLabel("Yellow");
labelTurn = new JLabel(Integer.toString(numberToSelect), Label.LEFT);
Dimension dim = labelTurn.getPreferredSize();
labelTurn.setPreferredSize(new Dimension(dim.width + 100, dim.height + 10));
// scoreField2 = new JTextField(3);
// scoreField2.setEditable(false);
// scoreField1.setText("0");
// scoreField2.setText("0");
// create the buttons on which players will make their moves
for (int i = 0; i < HEIGHT * WIDTH; i++) {
buttonArray[i] = new JButton(Integer.toString(i + 1));
buttonPanel.add(buttonArray[i]);
}
final Color buttColor = buttonArray[0].getBackground();
// add the action listener to the buttons
for (int i = 0; i < HEIGHT * WIDTH; i++) {
buttonArray[i].setActionCommand(Integer.toString(i));
buttonArray[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
if (button.getBackground() == Color.RED) {
button.setBackground(buttColor);
numberToSelect++;
} else {
if (numberToSelect > 0) {
button.setBackground(Color.RED);
numberToSelect--;
}
}
// button.setEnabled(false);
int buttonIndex = Integer.valueOf(button.getActionCommand());
row = buttonIndex / WIDTH;
column = buttonIndex % WIDTH;
// playMove();
labelTurn.setText(Integer.toString(numberToSelect));
// updateGUI();
}
});
}
endGameButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String s;
// Need to add "ball draw here" for Keno
// 20 random numbers between 1 and 80
// each time a "ball" matches one selected on the Keno ticket add to a counter
// at end look up payout for the number of matches corresponding to the counter
if (player1Score > player2Score)
s = "RED wins the game";
else if (player1Score < player2Score)
s = "YELLOW wins the game";
else
s = "Game is a draw";
JOptionPane.showMessageDialog(f, s, "Game Over", JOptionPane.PLAIN_MESSAGE);
System.exit(1);
}
});
labelPanel.add(endGameButton);
labelPanel.add(labelTurn);
topPanel.add(labelPanel, BorderLayout.NORTH);
topPanel.add(buttonPanel, BorderLayout.CENTER);
f.add(topPanel);
f.setSize(1000, 400);
f.setTitle("Keno");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
private void playMove() {
playerGrid[row][column] = turn;
if (turn == RED) {
turn = YELLOW;
} else {
turn = RED;
}
}
private void initialize() {
highX = highY = Integer.MIN_VALUE;
lowX = lowY = Integer.MAX_VALUE;
for (int row = 0; row < HEIGHT; row++)
for (int column = 0; column < WIDTH; column++) {
crystalGrid[row][column] = INITIAL;
}
}
public static void main(String[] args) {
new Keno();
}
}
// green for a match, yellow for a no-match.
I have 4 lines towards the bottom where I am supposed to insert the code. I would really appreciate it if someone could give me a hand on this.
To draw 20 non-repeating numbers, you can do the following:
put your 80 numbers in a collection.
shuffle the collection
the elements are now in random order and you can loop over the collection to get the first 20 elements.
If you give me more details on what you are stuck, I can provide further information.
I'm in the process of creating a frogger type game and have gotten pretty far in getting the program to do what I want it to do. However, I'm starting to think that to finish the game I will have to use way to much code and there must be a simpler way achieve the same results. I'm not looking for an answer, just need some more information.
Question 1: What can I use for the images that represent the moving Icons or cars? I'm currently using JButtons. The problem is that is difficult to get the buttons to move uniformly and I want to use 24 different moving Icons and from what I've learned so far I will have to add a new JButton for each icon.
Question 2: The way that I've gotten the Jbutton icons to move is to use a timer delay and then a counter to increment the x values. This works for the most part, but is there a better, perhaps simpler, way to move icons across the screen?
Any tips, tutorials etc are greatly appreciated.
Here is one of the classes that I've created to get movement of the icons:
public class EnemyJPanel extends JButton {
JButton enem = new JButton();
JButton enem12 = new JButton();
JButton enem13 = new JButton();
JButton enem1 = new JButton("1");
JButton enem2 = new JButton("2");
JButton enem3 = new JButton("3");
JButton enem4 = new JButton("4");
JButton score = new JButton("Score");
JButton enem5 = new JButton("5");
JButton enem6 = new JButton("6");
JButton enem7 = new JButton("7");
JButton enem8 = new JButton("8");
JButton yard = new JButton("50 Yard Line");
int i = 16;
int u = 576;
int d = 16;
int n = 576;
int k = 16;
int l = 16;
int dummyval = 16;
public EnemyJPanel(){
super();
setLayout(null);
enem1.setBounds(16,300,40,55);
enem2.setBounds(16,245,40,55);
enem3.setBounds(16,190,40,55);
enem4.setBounds(16,135,40,55);
score.setBounds(16,80,601,55);
yard.setBounds(16,355,601,55);
enem5.setBounds(16,410,40,55);
enem6.setBounds(16,465,40,55);
enem7.setBounds(16,520,40,55);
enem8.setBounds(16,575,40,55);
enem12.setBounds(16,300,40,55);
enem13.setBounds(16,300,40,55);
add(enem1);
add(enem2);
add(enem3);
add(enem4);
add(score);
}
public void addEnemy(){
enem1.setBounds(16,300,40,55);
enem2.setBounds(16,245,40,55);
enem3.setBounds(16,190,40,55);
enem4.setBounds(16,135,40,55);
score.setBounds(16,80,601,55);
add(enem1);
add(enem2);
add(enem3);
add(enem4);
add(score);
}
public void enemyMovement(){
i++;u--;d++;n--; // increments lateral movement from a timer in
dummyval++; // the dummy value is needed to keep the icons looping
dummyval = dummyval + 2;
enem1.setBounds(i,300,40,55);
i = i + 2;
if (dummyval > 176){
k++; k = k + 2;
enem12.setBounds(k,300,40,55);
}
if (k > 176){
l++;
l = l + 2;
enem13.setBounds(l,300,40,55);
}
enem2.setBounds(u,245,40,55);
enem3.setBounds(d,190,40,55);
enem4.setBounds(n,135,40,55);
enem5.setBounds(i,410,40,55);
enem6.setBounds(u,465,40,55);
enem7.setBounds(d,520,40,55);
enem8.setBounds(n,575,40,55);
if(i > 576){ // resets button
i = 16;
}
if(k > 576){
k = 16;
}
if(u < 16){
u = 576;
}
u = u - 2; // increase lateral speed
if(d == 576) {
d = 16;
}
if(n < 16){
n = 576;
}
n = n - 5; //increases lateral speed
}
}
The problem is created because you try to manage all the "stuff" separately. It looks like you may be missing some basic information on classes
First, I would create a custom class, something like
class ButtonObject extends JButton
{
public ButtonObject(String text, int x, int y, int width, int height)
{
super(text);
this.setBounds(x, y, width, height);
}
}
You also may want to take a look at arrays and create an array of your new ButtonObject.
The for loop will help you get through all the objects in your array.
ButtonObject[] enemies = new ButtonObject[10];
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
int y = 300 - (i * 55);
enemies[i] = new ButtonObject(text, 16, y, 40, 55);
}
There is probably a better way to do it than buttons but you may want to stick with them for now for simplicity.