Can't change/modify button background from another method - JAVA - java

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.

Related

ActionListener and dynamic(?) GUI

I've read through a dozen or so actionlistener/loop related questions here, but I'm not sure I've found my answer. I started on my first large Java project, a text RPG that's spiraled into around 5K lines of logic and game features which was functioning as intended using just the console - when I decided I'd try to build a Java swing GUI for it instead. Here's my problem:
I use a Room object which handles the description of where the player is at and also has an array of options for the player to choose next which it creates dynamically based on what cell the room's id is in on a csv file and what is beside it. I stopped outputting this to the console and instead started creating JButtons based on the options array like so:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
Over in actionlistener (Same class) this is how I tried to swing it:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
Then in my main class I call:
narrator.narrate(currentRoom, saveRoom); which takes care of some other logic concerning locked doors, encounters, etc.
Also in Main loop are some other methods related to autosave and tracking which rooms the player has visited. I know from other q/a i'v read on here that this is all pretty bad design, and I'm sttarting to understand that now, but my issue is this:
The first room of the game loads up fine, when I click a button it outputs to console(Just for testing) the correct trigger value of the room the button should be calling, so I'm getting that far, but how can I call the same method over again now?
-If I call narrate from actionListener it will wind up calling itself again and complain about ConcurrentModification.
-If I try to keep a loop going in my Main class it will keep looping and won't allow for the player to actually choose a button.
I've never used threads before, which I wonder might be the answer,and the closest thing to a related answer I've found is this:
Java: Method wait for ActionListener in another class
but I don't think moving actionListener to Main class would resolve my problem which is actionListener winding up calling itself recursively. And as for the observer-observable pattern... I just can't understand it :(
I appreciate any and all help, I've learned a LOT trying to make this thing work without seeking help as much as possible but this has stumped me.
Your loop in actionPerformed only checks whether a JButton exists in your optionList with the given actionCommand. However this can be done before actually doing something:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
now you can call narrate because you have finished iterating over the collection beforehand and will not get a ConcurrentModificationException

Do something when the close button is clicked on a JFrame (need clarification)

I'm looking for clarification about an answer given to an old question: Do something when the close button is clicked on a JFrame
In the answer, Ravindra Gullapalli suggested this code:
import javax.swing.JOptionPane;
/*Some piece of code*/
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
if (JOptionPane.showConfirmDialog(frame,
"Are you sure to close this window?", "Really Closing?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION){
System.exit(0);
}
}
});
Firstly, is this the proper way to do this in Netbeans?
Secondly, what is "frame"? (the first word in the 3rd line of code in the answer as well as the first parameter of showConfirmDialog). According to swing API, this should be of type Component. However, when I replaced this with the Title property of my JFrame, I still got a "cannot find symbol" error. Is the Component name different than the JFrame title, and if so where can I find it? In the NetBeans Navigator, it just says [JFrame] and does not display the Component name, unlike all the other Form objects which display and editable Component name next to the type.
"frame" is simply assumed to be the variable name for the JFrame in code not shown. If your program has a JFrame or other top-level Window named "frame" and it is in scope at that line of code, you're in business. Otherwise you will have to use the variable name that you currently are using. This is yet another reason to avoid "borrowing" code. Instead learn the concepts, borrow the ideas, and use both to write your own code.
With regard to:
Is the Component name different than the JFrame title, and if so where can I find it?
Not sure what you mean here. Again in the code in the answer, frame is the name of a variable, not a "component name" or "title". This involves Java 101 concepts -- variable names and variable scope, and has nothing to do with Swing or NetBeans.
With regard to:
is this the proper way for NetBeans"
it is if this is the behavior that you're trying to achieve.
Secondly, what is "frame"?
A reference to the frame that contains the close button you just clicked on.
However, when I replaced this with the Title property of my JFrame
Not sure why you would use the "Title" property. That is just a String. You can't open/close a String.
Firstly, is this the proper way to do this in Netbeans?
A better structure for the code in the WindowListener might be:
JFrame frame = (JFrame)windowEvent.getSource();
then you don't have to worry about defining a variable in your class.
Also you can use:
frame.dispose();
instead of System.exit(). The JVM will shut down if this is the last open window.

Minesweeper Java Inheritance

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.

variable when called in the same scope produces multiple values java

In a Java Swing desktop app. I have a number of smaller classes, all of which are made use of in an overarching App Class. One of such smaller classes is a JPanel that represents my login page. I've added a mouselistener to the login button on this page, that goes thus:
Public class loginPage extends JPanel{
String username;
boolean capturedName=false;
JTextField nameField;
...
loginButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
username = nameField.getText();
capturedName=true; //for redundant checking of mouse click event
System.out.println(username); //error checking
System.out.println(capturedName); //error checking
}
});
}
In a separate display class that represents my JFrame, I make the login page an attribute of said class and I instantiate this display class in my app class, after adding the login page to it. I am trying to capture the login page username attr in the App class and pass it to other methods. But when I run the code, and click on the login button, the value in the textbox isn't captured.
To error check, I tried the ff:
//Set login page GUI up
while(display.loginPage.username==null){ //this is initially true
if (display.loginPage.capturedName){ //boolean to check if button has been clicked
display.loginPage.username=display.loginPage.nameField.getText(); //intentional redundancy
String username=display.loginPage.username;
System.out.print(username);
//pass username to other methods
}
}
When I run the code, enter a name on the username textfield, and click login, the typed name and a true value for the capturedName boolean are both printed, but the
if (display.loginPage.capturedName)
condition is never fulfilled. Also when I add in print display.loginPage.username, I get a null value . What could be the reason for this discrepancy between the same values?
What could be the reason for this discrepancy between the same values?
You could have two objects of the same type, one displayed, whose state is being changed, and one not displayed that you're checking in the if block.
But again, for better help, consider creating and posting a Minimal, Complete, and Verifiable Example Program. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. As an aside, you will never want to use a MouseListener with a JButton as you're doing. Instead use an ActionListener as that is what it was built for.
"I've added a mouselistener to the login button" - Not a good idea, buttons should use ActionListener, see How to Write an Action Listeners and How to Use Buttons, Check Boxes, and Radio Buttons;
while(display.loginPage.username==null){ is a REALLY, REALLY bad idea which could lock up your UI and suggests that you violating the single thread rules of Swing. See Concurrency in Swing for more details.
What it sounds like you need is a modal dialog, which can block the execution of the code at the point the dialog is made visible...
See How to Make Dialogs for more details
Take a look at Java and GUI - Where do ActionListeners belong according to MVC pattern? for an example of a Login dialog/form using the MVC paridigm (Model-View-Controller)
Turns out as #MadProgrammer suggested, that I was creating two different loginPage objects in my display class. It's curious, however, that the mouselistener on the login page GUI that was visible actually listened for, and returned expected results of the better defined login page object (which was invisible).

back to previous page gui

if i have add a number and i print it in a new page(JFrame). now, i want to get back to
previous page to add another number.
how to write the code? because i want to keep thw new page open and back to previous page. the
new page is to display what the number that have been added by the user. totally no idea with
it.
i've try this
first frame called 'frame1'
second frame called 'frame2'
public static boolean isClicked = true;
if(btnOK.equals(isClicked))
{
frame2.setVisible(true);
frame1.setVisible(false);
}
1) The use of multiple JFrames in Java is a bad practice see here:
The Use of Multiple JFrames: Good or Bad Practice?
2) I would suggest using a LayoutManager like CardLayout which allows you to flip between containers like JPanels on a single JFrame:
How to Use CardLayout
3) You might also want to substitute your initial JFrame for a JDialog/JOptionPane, but that would depend on the usage of the initial JFrame.

Categories