Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am quite new to Java. I decided to code tic-tac-toe as practice (from scratch).
Anyway, I am trying to have the 'JLabel label' change when I click; going from 1, then 2, etc. Eventually, it will change to something other than numbers. But, for now, it works for a test.
The 'System.out.println("Number of clicks: " + mouseIn);' works fine, and produces the output I want. A picture of the console and JFrame/JPanel/JLabel can be seen here:
(The little 1 in the JFrame is the JLabel. I want to match what is output in the console.
I have googled, and searched, and tried everything I know (which ain't much!) and I can't get the dang thing to work...I'm just asking for some guidance. Main method just includes building of JFrame/Panel.
Code below:
From the main class, called (namone.java [named it this for my own reasons]):
public void run(JPanel p) //Takes panel from main method {
for(int i = 0; i < ticList.length; i++){
ticList[i] = new JButton(buttonText); //For every position in
//ticList[], create a JButton object
p.add(ticList[i]);
ticList[i].setPreferredSize(new Dimension(140,140));
ticList[i].addMouseListener(mouse); //Load mouseListner
}
//Set mouseIn to click value in MouseEvents Class
int mouseIn = mouse.getClicks();
//Set text value to text value in MouseEvents class
text = mouse.getText();
//Output...
System.out.println("Number of clicks: " + mouseIn); //For testing
String mouse = Integer.toString(mouseIn); //Convert mouseIn value (from MouseEvents.java) to mouse
JLabel label = new JLabel(); //New JLabel
p.add(label); //Add label to screen
label.setText(mouse); //Set the text of the label to value of mouse
System.out.println(mouse); //For testing
//So I can see if it's working (clicks wise)
}
And then the code from my MouseEvents.java class:
public class MouseEvents extends namone implements MouseListener {
int clicks = 1;
String text = "first"; //For testing purposes
public namone game = new namone();
public int getClicks(){
return clicks;
}
public String getText(){
return text;
}
public int intToString(){
Integer.toString(clicks);
return clicks;
}
#Override
public void mouseClicked(MouseEvent e) {
clicks++;
intToString();
JPanel p = new JPanel();
text = "" + clicks;
game.run(p);
}
As I said. I am very new to Java and I'm trying to learn how to develop applications with it. I'm sure it's caused by my own ignorance.
Thanks.
Assuming that mouse is of type MouseEvents that you write, one possibility is that you need to pass mouse.getText() to your call to label.setText(.).
Regardless, the way you set up your game is a bit strange to me. What is the reason to create a brand new JPanel every time someone clicks? Why not maintain the original JPanel and update it instead. I personally would attach a custom ActionListener to each JButton that runs some code everytime the button is clicked. If this ActionListener is an inner class, it can also view variables in the scope that the JButton is defined.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I've created a simple game which a player plays against computer.
I've got an issue in the timing of the turns, the computer should be the first to make a move than the real player should make his move by clicking LeftChoice or RightChoice button.
Here's my problem at code:
public class GameForm extends javax.swing.JFrame {
/**
* Creates new form GameForm
*/
final int SIZE = 10;
int CurrentSize = 10;
int PC_SUM=0;
int HUMAN_SUM=0;
boolean PC_TURN = true;
int[] RandArr = new int[SIZE];
public GameForm() {
initComponents();
}
public void init(){
for(int i = 0 ; i<SIZE;i++){
RandArr[i] = (int)(Math.random()*100)+1;
}
jTextField3.setText("");
jTextField4.setText(Integer.toString(PC_SUM));
jTextField5.setText(Integer.toString(HUMAN_SUM));
}
public void HUMAN_updateLeft(){
HUMAN_SUM+=RandArr[0];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public void HUMAN_updateRight(){
HUMAN_SUM+=RandArr[CurrentSize-1];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public static boolean WhoIsBigger(int[] arr){
int even=0,odd=0;
for(int i=0;i<arr.length;i+=2){
if(i%2==0){
even+=arr[i];
odd+=arr[i+1];
}
else{
odd+=arr[i];
even+=arr[i+1];
}
}
return even>odd;
}
public void PC_updateLeft(){
PC_SUM+=RandArr[0];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_updateRight(){
PC_SUM+=RandArr[CurrentSize-1];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_TURN(){
if(WhoIsBigger(RandArr))
PC_updateLeft();
PC_updateRight();
}
public void FullGame(){
while(RandArr.length>0){
if(PC_TURN){
PC_TURN();
PC_TURN = false;
}
}
}
//start button listener
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
init();
jTextField2.setText(Arrays.toString(RandArr));
jTextField1.setText("-");
jButton1.setEnabled(false);
FullGame();
}
//left button listener
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateLeft();
}
//right button listener
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateRight();
}
How can i know that the real player has made his move so it'll change PC_TURN to True and the game will move on?
Firstly, you should follow Java Naming Conventions when it comes to naming your variables. As it stands, PC_TURN looks as though it is a constant, although it is not a constant since you are changing it's value. So a more appropriate name would be pcTurn.
You also seem to have a method called PC_TURN() which I am assuming is the method which causes the computer to take it's turn and do something. So it would be better if this was named something descriptive like takePCTurn(). Notice the use of camelCase throughout. Capital letters at the start of a name should be reserved for classes and interfaces, not variables or methods.
The same goes for your method name
public void FullGame()
should be written as
public void fullGame()
Keeping to coding conventions like this make it easier for others to read and understand your code and keep everything neat and tidy. It's a good habit to get into. :)
I don't know where your left and right buttons are being declared or what you have named them, but you will need to add an event listener to each button which causes something to happen when they are clicked. I also am unsure about the purpose of RandArr.length > 0. You really don't need a loop here since this is an application with a GUI, it is never going to close unless you explicitly tell it to (e.g by clicking the close button). So I will just give you a generic solution.
You basically want the players turn to trigger the computer to take it's turn until some game over condition is met.
Example:
//Assuming this is called when the Start button is clicked
public void fullGame() {
takePCTurn();
}
public void takePCTurn() {
//Do PC's turn logic
//You might want to check if the Computer Won the game here
}
class PlayerTurnListener implements ActionListener() {
public void actionPerformed(ActionEvent e) {
//Do Player's turn logic
//You might want to check if the Player Won the game here
takePCTurn();
}
}
//We can create an instance of our listener and add it to both buttons
PlayerTurnListener playerTurnListener = new PlayerTurnListener();
leftButton.addActionListener(playerTurnListener);
rightButton.addActionListener(playerTurnListener);
So the first thing that happens is fullGame() is called by your Start button which then calls takePCTurn(); causing the computer to take it's turn. Now nothing will happen until the player clicks the left or right button. When they do this, the PlayerTurnListener's actionPerformed() method is called and you can do some logic in there and then takePCTurn(); will be called once again.
Rinse and repeat until gameover.
Hope that helps :)
You should attach a clickListener onto the left and right buttons. Then when the user clicks one that event will be fired. You should change PC_TURN to true there and re-run the loop if needed.
Example:
JButton yourButton = new JButton("Your Button");
yourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
PC_TURN = true;
// extra code
}
});
If this is a Swing or other GUI then you will need to get rid of the while loop.
Remember that GUI programs are non-linear and are event-driven, and so rather than a restricting while loop which risks completely feezing your GUI, you would change the program's state depending on whose turn it is -- have a variable indicating whose turn it is -- and then change the behavior of the program based on the state.
If you need more specific help, then you're going to need to ask a much more complete question including one with enough code and explanation to allow us to understand your problem better (but not too much code).
Regarding the code you've posted:
Yes, definitely get rid of that while loop.
Your code is hard to understand, mainly because you're variable naming is poor. Rather than using variable names like jTextField1, use names that make logical sense, that make your code "self-debuggin", such as humanScoreField and computerScoreField, etc.
Also learn and follow standard Java naming practices including having all variables start with lower case letters, classes with upper case letters, use camelCase for all except for constants which are all upper-case.
Tell more about just what this code is supposed to be doing, what the buttons and the JTextfields represent, what behaviors you desire, etc...
I'm attempting to create dynamic interface that essentially creates a grid of a growing number of panels that look similar to the picture below. I've got some rough code to achieve that. I have an issue in regards to handling events for the JButtons that i've added to an ArrayList. I'm aware that creating inner class event handlers is best practise, how would I handle events for a scaling number of buttons that are stored in an ArrayList?
Currently i've resulted to getting the objects source to achieve this.
Global Variables:
ArrayList<JButton> buttons = new ArrayList<JButton>();
Adding buttons to the panel:
for (int i = 0; i < 2; i ++) {
int xTotal = 150;
if (i == 0) {
xTotal = 132;
}
else {
xTotal = 308;
}
xTotal = xTotal + xTotal;
JButton currentButton = new JButton("+");
currentButton.setBounds(xTotal , 375, 45, 25);
currentButton.setFont(currentButton.getFont().deriveFont(14f));
currentButton.addActionListener(new AddHandler());
buttons.add(currentButton);
panel.add(currentButton);
}
Event handler:
class AddHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == buttons.get(0)) {
System.out.println("hello");
}
else {
System.out.println("it worked");
}
}
}
It looks to me like you're creating more than just a collection of JButtons. Instead you appear to be wanting to create (and correct me if I'm wrong), a collection of images/text with JButton. This suggests that you want to create a class that encapsulates one (?) menu item, that holds a JLabel for the image, a JLabel perhaps for the text, perhaps other components, and a JButton that the user can press to select the menu item. This component would be a JPanel that (important here) uses layout managers to intelligently arrange all of its constituent components. I would recommend not using ActionListeners but rather create a separate stand along class that extends AbstractAction, that you can use to set each JButton's Action, either via the JButton's constructor or via its setAction(...) method. Then you could place a collection of these JPanels in a master JPanel that uses perhaps a GridLayout, and have it held in a JScrollPane.
The details of my suggestions and the code would of course depend on the details of your GUI and your current code.
Other "side" recommendations:
Don't use null layouts and setBounds(...). Often newbie Swing programmers feel that this is the easiest way to create complex GUI's, and in the short term it may be, but in the long term, when it comes time to maintain, upgrade and enhance your GUI, it isn't. Also the GUI's so created may look OK on one platform and screen resolution, but they look terrible on all others. Learn about and use the layout managers.
Maybe you want a collection of Actions or the JButtons, but I'm not sure you need this. If the button's Action knows what to do, then no collection is needed. The Action could have a constructor that passes in references to the name and price of the menu item.
Even though youve already accepted another answer, I want to share what I have on my mind.
The idea of my idea is to store a number (maybe an ID) on the button by creating a subclass of JButton.
(ID could be, perhaps the ID of the food item this button is currently linked to)
class FoodButton extends JButton{
long id;
public FoodButton(String text, long id){
super(text);
this.id = id;
}
//Perhaps more constructors
public long getId(){
return id;
}
}
Then writing a single actionListener that gets the source of the event (even though you seem to think thats bad practice, I think it makes sense in this example), Observe:
ActionListener al = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
FoodButton btn = (FoodButton) e.getSource();
long id = btn.getId();
//Do something now that you know what button was clicked (id)
}
}
Let me note again that this actionListener is created before your loop, so you only need one, and you'll assign the same one to all your buttons.
Then inside your loop instead of creating a normal JButton, you create a FoodButton:
ActionListener al = new ActionListener(){...};
for (int i = 0; i < 2; i ++) {
//...
//Assigning id 'i' here, but you could pick something else
JButton currentButton = new FoodButton("+", i);
//...
currentButton.addActionListener(al);
buttons.add(currentButton);
panel.add(currentButton);
}
I hope this makes some sense to you.
Also, as someone who used to use null layouts too, once you get accustomed to using layoutmanagers, im sure you will like them.
I tried to figure this out myself but I can't. I'm stuck at a strange problem.
I have a Java Program with multiple classes and forms (I use Intellij and the build in GUI-Creator). When I switch from one Screen to another I just call frame.setVisible(false); at the leafing window and frame.setVisible(true); at the window I want to show next.
On a Button Click I make this:
In Class 1:
if (e.getSource() == umschaltenButton) {
this.mainW.goToMainWindow();
logger.log(Level.INFO, "Switched Back to MainMenu");
frame.setVisible(false);
}
And here is the weird part.
In Class 2:
public void goToMainWindow() {
frame = tvElectronics.drawMainWindow(); // I get a new Frame with new Images and so on
frame.addMouseListener(al);
frame.add(BotomPanel); // in here is the JComboBox
frame.setSize(LENGTH, HEIGHT);
comboBox1.removeAllItems(); // Here it tryes to refere to the old frame before i made frame = tvElectronics.drawMainWindow();
Vector<String[]> content = tvElectronics.getContent();
for (int i = 0; i < tvElectronics.getAnz(); ++i) {
comboBox1.addItem((i + 1) + ". " + content.get(i)[3]);
}
comboBox1.setSelectedIndex(chanel);
frame.setVisible(true);
}
And so it tries to update the old frame from class2 which no longer exists because of the new one I just created. And so I have 2 frames open: one as I want it and one strange old frame form class2.
My problem is that I want bind my JComboBox to a new Frame and update it but it is still connected to the old one and that causes weird problems like jumping back in the function. I mean it is at the last line of goToMainWindow() and then it starts again at the first line.
First off you should avoid swapping JFrames as your program does since this is a very annoying GUI design. Please read The Use of Multiple JFrames, Good/Bad Practice? for more on this.
Next, it's impossible for us to tell what GUI view your JComboBox is associated with.
But having said that, it really shouldn't matter. Instead of doing what you're doing, I would give the display class that holds a JCombBox a public method that you call on the containing display class that clears the contained JComboBox's model or that places items in the model. This way, there will be no ambiguity as to which JComboBox you're referring to, and this way you avoid directly exposing a view's inner components.
As an aside, I try to gear my display or view classes towards creating JPanels, not JFrames as this will give my code much greater flexibility.
For example
// my display class
class Display1 {
private DefaultComboBoxModel<String> myModel = new DefaultComboBoxModel<>();
private JComboBox<String> myCombo = new JComboBox<>(myModel);
public void removeAllComboElements() {
myModel.removeAllElements();
}
public void addElement(String ele) {
myModel.addElement(ele);
}
}
Same for your Display2 class. Then you can call the correct method on the JComboBox that is held by the correct view/display.
This way, when you swap displays, perhaps by using a CardLayout, you can clear the JComboBox in the display that is being shown by calling its own method to clear its own combobox's model.
I am working on a lab, it's a connect four game. I'm having trouble specifically with basic concepts like how classes communicate with each other, how to use private instance variables, how to use an ArrayList, how to compare JLabels or set them as something comparable...
To give a brief breakdown I have four classes GUI, Game, Player, Name
I can create the GUI by using two four loops, the game is a grid with 7 columns of 6 pieces. The pieces are images,
JLabel Piece = new JLabel("images/blank.png");
for example to denote an empty spot.
The GUI is based on a JFrame, single content pane and four panels, one for a header which indicates who is playing and who won, another for the 7 buttons accompanying the 7 rows, the grid itself of the possible places to be played and then a button panel which gives you the option to replay.
I'm lacking in a lot of concepts. For instance, the replay button shouldn't appear until the game has ended.
I don't understand how to use an ArrayList. I tried to use
ArrayList<ArrayList<JLabel>> myList = new ArrayList<ArrayList<JLabel>>();
So when I create the GUI by running two for loops like so
For ( c = 0 ; c<8 ; c++) {
ArrayList<JLabel> column = new ArrayList<JLabel>();
For ( r = 0 ; r<7 ; r++) {
ArrayList<JLabel> row = new ArrayList<JLabel>();
JLabel empty = new JLabel("images/blank.png");
row.add(empty);
}
column.add(row);
}
Even this small step I've already got confused.
I know the two for loops above are not correct specifically the ArrayList.
I don't know how to create the arraylist and then use them.
using something like
column.get().get();
myList.get().get();
to get a specific piece.
I don't know how to pass that to an argument so that for example if I push on button 7 for column 7, and no pieces have been played yet, I can start from the lowest area column 7 row 6 and update that to a played piece, red or yellow for the appropriate player.
This is vague and I doubt I'll get anywhere but I am desperate for help. There isn't much time available from the TA's / Teacher and I believe I am lacking significantly to be able to finish this project.
I understand how it works/what I have to do in words but in terms of applying Java code...
I'd appreciate any help.
OK first off you should use an array of Enums. ArrayLists are intended for lots of items and that can have rapidly changing numbers. Arrays are intended to house data in a grid of some sorts. Since you are using a static board, use arrays! They are also much less memory-intensive. Example:
//Note you should use [column][row] as that is common practice.
States[][] grid = new States[7][6];
//And initialize it:
for(int i = 0; i < grid.length; i++)
for(int o = 0; o < grid[i].length; o++)
grid[i][o] = EMPTY_JLABEL;
Then declare an enum (this is a new class) (NOTE: replace FULL_PLAYER_ONE_JLABEL and FULL_PLAYER_TWO_JLABEL with the JLabels that have the image for each.):
public enum States {
FULL_PLAYER_ONE(FULL_PLAYER_ONE_JLABEL), FULL_PLAYER_TWO(FULL_PLAYER_TWO_JLABEL), EMPTY(EMPTY_JLABEL);
//The image of the appropriate state.
private JLabel label;
//Enum constructors must be private
private States(JLabel label) {
this.label = label;
}
public JLabel getLabel() {
return label;
}
}
In your GUI, have a JButton that is only added to the frame when the game is over. Also add a button to indicate when each column has been clicked by the player.
JButton button = new JButton();
//Initialize JButton and add to frame...
//Anytime before the frame is set to visible:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
/* Perform tests for for what should happen.
For example test whose turn it is then call a method to add a piece to that column. Then call a checker to see if someone has won. If so, display the replay button, otherwise do nothing (allow other player to move).
*/
}
}
This question already has answers here:
How to set Action Listener to 3 buttons
(3 answers)
Closed 6 years ago.
As part of an exercise, I would like to design a program that displays a 9x9 grid of JButtons. When I click on a button, I would like that button to change in some way, like say originally it displays an 'o', but when you click on it, it displays an 'x', or maybe it changes colors, etc., while the other buttons remain unchanged.
However, I am not sure how to do this. I have created a 2D array of JButtons, and placed each on in a 9x9 GridLayout panel. I also set an ActionListener for each one. The problem is, I do not know how to change the color or text of only one button. Here is the short version of my program only displaying the relevant parts.
private JButton[][] t = new JButton[9][9]; //Declared much earlier in the program, right after the class declaration.
public void buildTile()
{
panelc.setLayout(new GridLayout(9, 9));
for(int r = 0; r < 9; r++)
{
for(int c = 0; c < 9; c++)
{
t[r][c] = new JButton("O");
t[r][c].setBackground(Color.BLACK);
t[r][c].setForeground(Color.WHITE);
t[r][c].addActionListener(new TileListener());
panelc.add(t[r][c]);
}
}
}
private class TileListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//Some code to change a specific button
}
}
How may I specify which button to perform some sort of aesthetic change to?
In the actionlistener e.getSource() will return the button you clicked