I am creating a Tic-Tac-Toe game in which a square in the grid is represented by a class called Square which I created. It extends JButton, but I added a boolean field called pressable which states whether or not the button can be pressed in-game. If the button already has a letter, then it cannot be pressed. I want to implement code in my actionPerformed() method that will check the pressable variable, and if pressable is false, it will not change the letter of the square. I am using the getSource() method on my ActionEvent to give me a reference to the square pressed. Therefore, I need to cast the Object to type Square so that I can access its pressable field. But when I do this, I get the following error: java.lang.ClassCastException: javax.swing.JButton cannot be cast to tic.tac.toe.Square This makes no sense to me. Before I needed each square to have a pressable field, I used a JButton, which worked just fine. But since Square inherits JButton, I would think that it would work as well. How can I fix this?
The JVM is telling you the truth: the object returned by getSource() is in fact a JButton and is not a Square object, despite your statements above. So the fact is, you are adding your ActionListener to a JButton and not to a Square object. You will need to inspect your code to see why this is so. If you need more of our help, you'll need to show this code.
Edit
You state:
I looked into it and realized that my "Start" button was going through the same process, which is where the error came from.
Thank you for the update.
This suggests that you're using one ActionListener for all buttons, which you'll not want to do. Certainly all the tic-tac-toe buttons can use the same listener, but any others should use there own separate listener object, perhaps via an anonymous inner class.
You could disable the JButton the first time it is clicked with .setEnabled(false) which would get around this issue. But I agree with HovercraftFullOfEels.
Related
I have a panel, let's call it detailsPanel, which holds a Person reference and displays its field values in the following manner:
Name: person.getName ();
Surname: person.getSurname ();
Emain: person.getEmail ();
.... .......
.... .......
And so on. I will use JLabels (correctly aligned using a GridBagLayout) to show each (fieldName, fieldValue). I have a lot of fields to display.
The problem is that the panel which shows the details must be always visible, i.e it will not be shown in a modal JDialog, so that i could create the panel by simply reading my Person object fields at the panel creation.
The panel must always be visible, and its Person reference will change when the user selects a different row in a Person list. This means i will call a method to update its state, something like:
detailsPanel.setPerson (aPerson);
Now, i'm wondering how i should update all the fields. Should i keep a reference to all the JLabels which show the values, and use setText(value) on each of them when i update the panel, or would it be better to override getText() method for every label, returning the correct field value, so that in the update method i would only repaint the panel, and the text would automatically change when the getter method is used on a different Person object?
Any suggestion is appreciated!
Since this is UI stuff which is usually called almost never (relative to how often things are called in other computation) you don't need to worry about efficiency at all. Just do what you think is the most elegant solution. There are three options That quickly come to my mind. They are ordered from quick and static to elegant and reusable:
Quick and dirty: create your constructor and make everything look nice. Then move everything from the constructor to a separate init() method and every time the entities change, you just call removeAll(); and then init() again.
As you suggested, keep a reference to all labels and use the setPerson() method to update all panels. Then call this method in the constructor (this is arguably the most common solution).
As you suggested, build your own extension of JLabel. This new class should either have an update() method which is to be called when things change, or have it set its own listeners to ensure that it gets notified of any relevant change.
If you are planning to create a single panel which is supposed to display all kinds of objects, you could have those object implement an interface called Displayable which gives you generic access to all its values and maybe even listeners to each value. An alternative to the Displayable interface is to use reflection and use annotations to allow the panel to get its values for display.
Please note that the most elegant solution is - contrary to what some people may tell you - not always the best for any situation. How much maintenance do you expect there to be in the future? How big is the application? Will you ever hand off the code to someone else? All these and more need to be considered to decide how "nice" you want your solution to be.
I have a problem about modify button background. I am using netbeans gui builder for build form. I am trying change button background when the second frame is open and turn it back when second frame close.
public void update(boolean x){
if(x==true){
circleButton.setOpaque(true);
circleButton.setBackground(new java.awt.Color(0, 0, 0));
System.out.println("testoutput");
}
}
this is my update method from first class.
I added window listener to second frame.
private void formWindowOpened(java.awt.event.WindowEvent evt) {
isitopen = true;
//this is first class which includes button
homework hwork = new homework();
hwork.update(isitopen);
System.out.println("testoutput2");
}
I got 2 testoutput but color of the button didn't change.
What can i do to fix this issue ?
You're creating a new homework object in your formWindowOpened(...) method, one completely unrelated to the homework object that is displayed, and changing the state of the new object will have no effect on the displayed one.
A simple and WRONG solution is to use static fields or methods.
Instead one simple solution is to give the calss with your formWindowOpened(...) method a valid reference to the displayed homework object, something that can be done with a constructor parameter or a setHomework(...) method.
A much better and even simpler solution:
Make the 2nd window a modal JDialog, not a JFrame
This way homework will know when the window is open and can set its own button colors. When the 2nd window opens, program flow in the calling class is put on hold, and only resumes when the 2nd window closes -- just like using a JOptionPane.
For more on this, please see The Use of Multiple JFrames, Good/Bad Practice?
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
I have 5 classes for this project, Button Minefield GUI MenuBar Game.
Button is an individual mine cell.
Minefield contains a 2d array of buttons, and operations that concern all of the buttons.
GUI is the portion above the MineField grid, displaying the reset button, time lapsed and how many flags remain,
Game puts all of the other classes in Panels and places them in the applet. No game logic here.
Here is a screenshot of my applet
I'm having problems when it comes to using inheritance. If I can solve this issue, I can do the other problems too. It has to do with invoking a method in the super class.
One of my problems:
When a Button mine cell is right-clicked, the mouse listener picks it up and changes the text of the JButton to "F" for flag. However, I want to update the counter of how many flags are available, which is a variable in the Minefield class. Finally, I want the GUI class to listen for changes to that variable and update the JLabel.
In the MouseListener for Button:
if (e.getButton() == MouseEvent.BUTTON3)
{
advanceCurrentState();
if (currentState == "FLAG")
super.setNumFlagsRemaining(-1); //update the Minefields variable
}
Back in Minefield:
public void setNumFlagsRemaining(int delta)
{
numFlagsRemaining += delta;
}
But this doesn't work. When I am debugging, super.setNumFlagsRemaining(-1) is creating a new instance of Minefield and I cannot update the variable inside the super class. I thought that it would update the existing object of Minefield, but I read that Java does not pass by reference, so I was confused as how to do it. If you need to see additional code please say so, I tried to not clutter this post with 5 whole classes and say, "fix it".
You do not provide enough code so I can only guess here.
I think you are confused with key word super
It actually mean to call method from the super class which you had inherited.
I doubt that JButton inherits anything from your class Minefield. Usually it is in opposite way.
Also count of the fields is stored and displayed in the JLabel. So you, actually, have to call method of the class which has this JLabel and takes care of total count.
I want to show one JLabel and one JComboBox when one particular RadioButton is selected in previous frame, otherwise it should be hidden. Even when I implement ComponentListener in that class his abstract methods(componentShown(), componentHidden()) are never called.
I think that your problem can be handled pretty easily, without even getting into these event handlers. Just pass a variable from your initial frame, when the RadioButton is selected, to the new frame (maybe a boolean variable with true value). Then, in your new fame, simply show the components, based on the value of that variable.
I hope you can handle the passing of variables, by handling the constructor parameters of your new frame.
Hope this helps ! Any clarifications required, please comment.
Hello? anyone had a problem like: cursor blinking in more than one field at a time?
In my case the following happens: When you double click on a field JTextField, opens a JDialog, so
after closing this, the focus is directed back to the field clicked before opening the screen.
What happens is that after performing this action, two fields are flashing at the same time (usually the first field
screen, as well as the field in which efetuei double click).
This medium is random, there are cases in which it does not occur.
When debugging the inner class Handler, contained within the class DefaultCaret more specifically the actionPerformed method, realized
that: time is a field, and time is another, which are precisely the fields that are flashing (q seems obvious I know). but they are
the own inner classes of Java that are calling the method.
When passing over the field using the Tab, the cursor false, vanishes.
I'm using JDK 6
I returned the focus within the invokeLater(), but not solved. Now both synchronized flash
The first JComponent focusable is one of the fields that flashing improperly
I'm using my own FocusTraversalPolicy, does that may be influencing? The funny thing is that there is no treatment particularly strange about my class.
I noticed that the standard Java class, using a method within the Syncronized getFirstComponent(), but added the same control, but still is not ok
Actually it's Focus issue for me.
Normally when JTextComponent looses Focus setCaretVisible(false) / setSelectionVisible(false) is called and when Focus gained opposite thing happens.
After closing JDialog try to return Focus inside invokeLater(). Also check what's the first focusable JComponent in the JDialog's parent.
This situation occurs because the project I'm developing is quite large, so do not get small examples of implementation
The project has many components, Tables and Container's, which require focus through at the same time.
It turns out that Swing, put in a queue for execution, a lot of threads, and then dispatching them going, and while he did not finish running it, you can cram grabFocus() or requestFocus(), which does not cry, the first he has to finish everything and then run my request focus.
Resolved palliatively this situation, using the Swing SwingUtilities.invokeLater(...);
Thanks for the tips.