0

I want that main should print hello (in a pop up dialogue box) everytime the button is clicked. So I designed the following program but it doesn't seem to work. The program compiles and executes just fine but when I click the button, I don't see the any dialogue box popping up. I have put in place the getter and setter of the boolean variable (button_clicked) whose value is being tested in the main() block. Please help if you know..

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class abc extends JFrame implements ActionListener{

boolean button_clicked = false;
JButton b1;

abc(){
    this.setSize (400, 400);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.createUI();
}

void createUI(){
    this.setLayout(null);
    b1 = new JButton("x");
    b1.setSize(110,30);
    b1.setLocation(10,210);
    this.add(b1);

    b1.addActionListener(this);
}

public boolean isButton_clicked() {
    return button_clicked;
}

public void setButton_clicked(boolean button_clicked) {
    this.button_clicked = button_clicked;
}


public void actionPerformed(ActionEvent arg0) {
    button_clicked = true;

    //I don't want to print the dialogue box from here..
    //I want to keep everything under main()'s control.
}

}


public class tempMain extends JFrame {

public static void main(String[] args) {
    abc temp = new abc();
    temp.setVisible(true);
    while(true){
        if(temp.isButton_clicked())
            JOptionPane.showMessageDialog(null, "Hello");
    }
}

}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Vivek Sethi
  • 894
  • 2
  • 13
  • 20
  • 2
    You should never use a while loop like that. This has a lot of design flaws. Your While loop will 1 be eating up CPU because it never sleeps. If you must use a while loop like this then at least make it in a new thread and sleep the thread after every iteration. However, this is still a poor design. – Quinma Aug 29 '12 at 17:19
  • Why the comments in your code? If you're going to insist on a bad design for your program, at least justify the reason for it. – Hovercraft Full Of Eels Aug 29 '12 at 17:48
  • @Hovercraft: I'm guessing that the comment is a plea for a _modeless_ dialog and play the `PropertyChangeListener` card. – trashgod Aug 29 '12 at 18:08
  • @trash: your guess is as good as any others since the original poster appears to not want to reveal the motivation behind his request. – Hovercraft Full Of Eels Aug 29 '12 at 18:09
  • @HovercraftFullOfEels: I posted my rationale behind such a design in an answer below.. – Vivek Sethi Aug 29 '12 at 19:47
  • @Quinma: My app requires me to do so. Actually the printing dialogue box statement was just a breakpoint to check if the control is being reverted to main under given conditions or not. (The control is being reverted to main but the button_clicked value never gets 'true' or something I guess). In the actual program, this dialoguebox line is replaced with a code that has to keep waiting for user input. That's why such a while is used. I'll try implementing it in another thread. Thanks for the heads up.. – Vivek Sethi Aug 29 '12 at 19:47
  • @trashgod: I have no idea what that is.. I'll study about it further.. – Vivek Sethi Aug 29 '12 at 19:48
  • @Vivek: if you're looking for good modular program design, the main logic and the *state* of your program shouldn't even be in your GUI classes, but rather in your model classes, again a la MVC as per my other comment. – Hovercraft Full Of Eels Aug 29 '12 at 20:42
  • @Vivek: There's a good example of this from Hovercraft [here](http://stackoverflow.com/a/5533581/230513), cited [here](http://stackoverflow.com/a/3072979/230513). – trashgod Aug 29 '12 at 21:02
  • @trashgod: thank you so much for the example.. I think this will make my life much easier once I understand it. – Vivek Sethi Aug 29 '12 at 22:26
  • 1
    Please learn java naming conventions and stick to them. And while you are at learning: never-ever do manual sizing/locating of components, that's the exclusive task of a suitable LayoutManager. – kleopatra Aug 30 '12 at 07:06
  • @kleopatra: what if I want to locate the components as per my wish and not any predefined layout..?? – Vivek Sethi Aug 30 '12 at 09:29
  • you don't want that ever, even if you don't know it yet :-) And even if you _really_ want it: write a LayoutManager that does exactly what you want. – kleopatra Aug 30 '12 at 09:41
  • I'll take note of that!! – Vivek Sethi Aug 30 '12 at 12:20

6 Answers6

3

Move the JOptionPane.showMessageDialog() call under the actionPerformed() method and delete the while() thing under the main method.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
  • There is a specific comment in the code stating that this solution is not desirable. I don't know why, but the programmer doesn't want to do it. – rlinden Aug 29 '12 at 17:29
  • @rlinden: the original poster needs to justify the rationale for his bad design decision. Until he does so, Dan's recommendation is the best. – Hovercraft Full Of Eels Aug 29 '12 at 17:51
  • @HovercraftFullOfEels: The thing is that the above code snippet is a part of huge program in which the abc class is to be re-used for many other future apps like this. In the actual code, there is a specific class that deals with printing of dialogue boxes and to maintain the object oriented integrity, I need to pass the control to that function in an altogether different class. The abc class just handles the GUI part of the program, rest functionality is modulated to different modules of the code. Hope you get my point. Just looking for a way around it.. – Vivek Sethi Aug 29 '12 at 19:35
  • @Vivek: you need to give more specific information on your exact requirements. Otherwise we'll not be able to give specific recommendations other than that in no way shape or form should you use an infinite loop here. – Hovercraft Full Of Eels Aug 29 '12 at 20:49
  • @HovercraftFullOfEels: Well, it's a long code actually. Btw I got rid of the infinite loop. Thank you. All I want is that as soon as somebody clicks on the button, some function in another class gets intimated, and based upon values in text fields (assuming there are text fields in which user enters values), does some business logic and gives the output accordingly.. Don't want everything to happen under the actionPerformed(). I'll read your example of MVC posted by trashdog in a comment above. Thank you again. – Vivek Sethi Aug 29 '12 at 22:24
2

You might want to read about "How to Write an Action Listener" to help you implement an ActionListner in your code.

The basic idea for your code would be to:

  • Declare an event handler class
  • Register an instance of the event handler class as a listener with your JButton
  • Include code that implements the methods in listener interface. In your case, you would over-ride actionPerformed() and write your logic over there to show a dialog box. "How to Make Dialogs" would be another useful tutorial for you.
Sujay
  • 6,753
  • 2
  • 30
  • 49
  • The thing is that the above code snippet is a part of huge program in which the abc class is to be re-used for many other future apps like this. In the actual code, there is a specific class that deals with printing of dialogue boxes and to maintain the object oriented integrity, I need to pass the control to that function in an altogether different class. The abc class just handles the GUI part of the program, rest functionality is modulated to different modules of the code. Hope you get my point. Just looking for a way around it.. – Vivek Sethi Aug 29 '12 at 19:52
  • @VivekSethi: So you basically want that when the user clicks on the `JButton`, the control to transfer to another object. Would your `abc` class have reference to an instance of that separate class? If yes, then you can over-ride the `actionPerformed()` and call the appropriate method of the other class – Sujay Aug 29 '12 at 23:03
2

As @Quinman pointed out, your code design is really flawed. I understand that you do not want to put the JOptionPane under the actionperformed method for some personal reason which I don't understand. Based on that premise, I think that the best solution would be to create a callback, that is, make your JFrame know the main class and call it when the button is clicked.

It is possible to make this mechanism independent of the main class. Please check the Observer design pattern in order to understand how to do that.

Your code also has another flaw - when the button is clicked I get infinite Hello messages. In order to avoid that, you should set the button_clicked variable to false. I only mention that as a general tip, for in truth you really should get rid of the busy wait that your while is causing.

rlinden
  • 2,053
  • 1
  • 12
  • 13
  • The second flaw is an easy one to correct. Thanks though.. My app really requires me to wait for the user input forever (which would eventually come under the while(true){} and not the dialogue box line). But I like Observer design patter. Would wiki it. Thank you.. – Vivek Sethi Aug 29 '12 at 20:06
2

You may be looking for a modeless dialog. In this example, the main panel, named Observer, listens to an ObservedPanel in a dialog. By using a PropertyChangeListener, any changes made to the dialog are immediately reflected in the main panel.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

As has already been pointed out by a number of people, you approach and design are flawed. I won't go into further as it has already been dealt with, but as a suggestion you could try...

abc temp = new abc();
temp.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        JOptionPane.showMessageDialog(null, "Look Ma, I'm in Main...");
    }
});
temp.setVisible(true);

And in your abc class...

class abc JFrame implements {
    // build your class as normal

    public void addActionListener(ActionListener listener) {
        b1.addActionListener(listener);
    }    
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Please can you also explain me how this modification is actually passing the control to main? Is the temp object controlling the event listener here? – Vivek Sethi Aug 30 '12 at 12:42
  • Yes and no. The event listener is in main, but we provide a reference to it in temp. When the button is clicked, the listener is otified within main's context – MadProgrammer Aug 30 '12 at 19:38
0

Judging from the comments you provided, you want to reuse your abc class (which has a very poor name and does not comply to the Java naming standards) for several different purposes, so you do not want to include the code which is executed when you press the button in the abc class.

There are multiple solutions for this (where the first is my preferred one)

  • Pass an Action in the constructor of your abc class and couple that Action to the JButton. This way the class which constructs the abc instance is responsible for the behavior when the button is pressed
  • make abc abstract and let your ActionListener call that abstract method. You can then make concrete implementations of this class each time you want different behavior.

Further notes on your code:

  • get rid of that while( true ) loop
  • get rid of the null layout and use a LayoutManager instead
  • Swing components should be created and accessed on the Event Dispatch Thread. Consult the Concurrency in Swing tutorial for more information
Robin
  • 36,233
  • 5
  • 47
  • 99
  • Thank you.. I think the first one should do the trick. Any relevant example code if you could provide with.. any links..?? – Vivek Sethi Aug 30 '12 at 09:35
  • @VivekSethi See [the Action tutorial](http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html) – Robin Aug 30 '12 at 09:38