I have a window with a MenuItem "maddbound3" with the following ActionListener:
maddbound3.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
menu_addbound3();
}
}
);
When the menu is clicked this listener calls menu_addbound3() below:
void menu_addbound3()
{
while(getEditMode() != EditMode.NONE)
{
System.out.println("!... " + getEditMode());
synchronized(this)
{
try
{
wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
A MouseClicked event alters the value of the edit mode and issues a notifyAll() so that the while loop should exit. However, tests have shown that when the system is running through the while loop, the MouseClicked event never occurs on clicking the mouse.
Does the ActionListener block the MouseClicked event? How can I resolve this issue?
Thanks
Don't have a while(true) on the Swing event thread, and likewise don't call wait() on the Swing event thread -- you'll freeze the whole GUI making it completely unresponsive. You need to understand that the main Swing event thread or "event dispatch thread" is responsible for all Swing drawing and user interaction, and so if you tie it up with long-running or freezing code, you lock your entire GUI.
Instead, change the state of your program -- perhaps by setting a variable or two, and have the behavior of your program depend on this state. If you need more specific advice, please tell us what behavior you're trying to achieve, and we can perhaps give you a better way of doing it.
For more on the Swing event thread, please read: Lesson: Concurrency in Swing
Edit
You state:
When the user clicks the menu item I want to obtain information via a series of "discrete" mouse clicks from the window. Hence, on clicking the menu, the user would be prompted to "select a point in the window". So, what I need is for my ActionListener function (menu_addbound3) to then wait for a mouse click. Hence the wait/notify setup. A mouse click changes the edit_mode and notifyAll() causes the wait in the while loop to exit which then causes the while loop to exit and I can then prompt for my next bit of information within the menu_addbound3 function, repeating this as as I need to.
Thanks for the clarification, and now I can definitely tell you that you are doing it wrong, that you most definitely do not want to use the while loop or wait or notify. There are many ways to solve this issue, one could be to use some boolean or enum variables to give the program a state and then alter its behavior depending on the state. Your EditMode enum can be used in the MouseListener to let it know that its active, and then you could also give the MouseListener class a boolean variable windowPointSelected, set to false, and then only set it true after the first click has been made.
Edit 2
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class ProgState extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final Color EDIT_COLOR = Color.red;
private EditMode editMode = EditMode.NONE;
private boolean firstPointSelected = false;
private JMenuBar jMenuBar = new JMenuBar();
private JTextField firstPointField = new JTextField(15);
private JTextField secondPointField = new JTextField(15);
public ProgState() {
add(firstPointField);
add(secondPointField);
JMenu menu = new JMenu("Menu");
menu.add(new JMenuItem(new AbstractAction("Edit") {
#Override
public void actionPerformed(ActionEvent arg0) {
setEditMode(EditMode.EDITING);
setFirstPointSelected(false);
}
}));
jMenuBar.add(menu);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mEvt) {
if (getEditMode() == EditMode.EDITING) {
Point p = mEvt.getPoint();
String pStr = String.format("[%d, %d]", p.x, p.y);
if (!isFirstPointSelected()) {
firstPointField.setText(pStr);
setFirstPointSelected(true);
} else {
secondPointField.setText(pStr);
setEditMode(EditMode.NONE);
}
}
}
});
}
public void setEditMode(EditMode editMode) {
this.editMode = editMode;
Color c = editMode == EditMode.NONE ? null : EDIT_COLOR;
setBackground(c);
}
public EditMode getEditMode() {
return editMode;
}
public void setFirstPointSelected(boolean firstPointSelected) {
this.firstPointSelected = firstPointSelected;
}
public boolean isFirstPointSelected() {
return firstPointSelected;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public JMenuBar getJMenuBar() {
return jMenuBar;
}
private static void createAndShowGui() {
ProgState progState = new ProgState();
JFrame frame = new JFrame("EditMode");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(progState);
frame.setJMenuBar(progState.getJMenuBar());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum EditMode {
NONE, EDITING
}
From the discussion it seems that having your class assume a number of states is the best way to proceed. We can achieve this by one or more enum variables. The reason I found this so hard to grasp initially is that I couldn't see the benefit of having all of ones code in the MouseClicked function. This is ugly and unmanageable at best.
However, using multiple enums and splitting processing into a number of external functions, we do indeed achieve a nice system for what we want.
Related
I need to run a background thread in my Java GUI that only runs when I click a button and pauses when I click that button again. I am not exactly sure how to set this up, but I have placed a thread in my constructor and the while loop within is set to go through when I set a specific boolean to TRUE. One button switches from setting this boolean TRUE or FALSE.
Everything else I have in this GUI works fine. When I tried debugging the thread, it actually works as I step through the thread but nothing when I try running the GUI completely. The GUI is rather large so I'm gonna put up a portion of the constructor and the action listener of the button. The rest of the code is unnecessary since it works just fine. I need to know what I am doing wrong here:
public BasketballGUI() {
// certain labels and buttons
Thread runningSim = new Thread() {
public void run() {
while(simRun) {
// do stuff here
}
}
};
runningSim.start();
}
// other GUI stuff
// actionListener that should run the thread.
class SimButtonListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
if(!simRun) {
simRun = true;
sim.setText("Pause Simulator");
}
else if(simRun) {
simRun = false;
sim.setText("Run Simulator");
}
// other stuff in this actionListener
}
}
Establish a Swing based Timer with an ActionListener that will be called repeatedly.
In the actionPerformed(ActionEvent) method call repaint().
Start the timer (Timer.start()) when the user clicks Start
Stop the timer (Timer.stop()) when the user clicks Stop
If you cannot get it working from that description, I suggest you post an SSCCE of your best attempt.
I thought I had one 'lying around'.. Try this working SSCCE which uses images created in this SSCCE.
I could see this background thread useful for a Java GUI when handling button events to affect something like a text area or progress bar.
For the sake of argument, I will build you a tiny GUI that affects a Text Area. I hope this helps you.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.*;
public class TestClass extends JPanel {
super("TestClass - Title");
private AtomicBoolean paused;
private JTextArea jta;
private JButton btn;
private Thread thread;
public TestClass() {
paused = new AtomicBoolean(false);
jta = new JTextArea(100, 100);
btn = new JButton();
initialize();
}
public void initialize() {
jta.setLineWrap(true);
jta.setWrapStyleWord(true);
add(new JScrollPane(jta));
btn.setPreferredSize(new Dimension(100, 100));
btn.setText("Pause");
btn.addActionListener(new ButtonListener());
add(btn);
Runnable runnable = new Runnable() {
#Override
public void run() {
while(true) {
for(int i = 0; i < Integer.MAX_VALUE; i++) {
if(paused.get()) {
synchronized(thread) {
try {
thread.wait();
} catch(InterruptedException e) {
}
}
}
}
jta.append(Integer.toString(i) + ", ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
};
thread = new Thread(runnable);
thread.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
if(!paused.get()) {
btn.setText("Start");
paused.set(true);
} else {
btn.setText("Pause");
paused.set(false);
synchronized(thread) {
thread.notify();
}
}
}
}
}
Main class to call everything.
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class MainClass {
public static void main(final String[] arg) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestClass());
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
});
}
}
I did not test this code to see if it works exactly, Its main goal is to break you through your coders block and use my components to fix your issue. Hope this helped. Need anything else Email me at DesignatedSoftware#gmail.com
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
using sleep() for a single thread
I'm having issues with JTextField.setText() when using Thread.sleep(). This is for a basic calculator I'm making. When the input in the input field is not of the correct format I want "INPUT ERROR" to appear in the output field for 5 seconds and then for it to be cleared. The setText() method did work when I just set the text once to "INPUT ERROR" and by printing out the text in between I found it does work with both that and the setText("") one after the other. The problem arises when I put the Thread.sleep() between them.
Here's a SSCCE version of the code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Pattern;
import javax.swing.*;
public class Calc {
static Calc calc = new Calc();
public static void main(String args[]) {
GUI gui = calc.new GUI();
}
public class GUI implements ActionListener {
private JButton equals;
private JTextField inputField, outputField;
public GUI() {
createFrame();
}
public void createFrame() {
JFrame baseFrame = new JFrame("Calculator");
baseFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
BoxLayout layout = new BoxLayout(contentPane, BoxLayout.Y_AXIS);
contentPane.setLayout(layout);
baseFrame.setContentPane(contentPane);
baseFrame.setSize(320, 100);
equals = new JButton("=");
equals.addActionListener(this);
inputField = new JTextField(16);
inputField.setHorizontalAlignment(JTextField.TRAILING);
outputField = new JTextField(16);
outputField.setHorizontalAlignment(JTextField.TRAILING);
outputField.setEditable(false);
contentPane.add(inputField);
contentPane.add(outputField);
contentPane.add(equals);
contentPane.getRootPane().setDefaultButton(equals);
baseFrame.setResizable(false);
baseFrame.setLocation(100, 100);
baseFrame.setVisible(true);
}
/**
* When an action event takes place, the source is identified and the
* appropriate action is taken.
*/
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == equals) {
inputField.setText(inputField.getText().replaceAll("\\s", ""));
String text = inputField.getText();
System.out.println(text);
Pattern equationPattern = Pattern.compile("[\\d(][\\d-+*/()]+[)\\d]");
boolean match = equationPattern.matcher(text).matches();
System.out.println(match);
if (match) {
// Another class calculates
} else {
try {
outputField.setText("INPUT ERROR"); // This doesn't appear
Thread.sleep(5000);
outputField.setText("");
} catch (InterruptedException e1) {
}
}
}
}
}
}
I'm not actually using a nested class but I wanted it to be able to be contained in one class for you. Sorry about how the GUI looks but again this was to cut down the code. The the important section (if (e.getSource() == equals)) remains unchanged from my code. The simplest way to give an incorrect input is to use letters.
When you use Thread.sleep() you're doing it on the main thread. This freezes the gui for five seconds then it updates the outputField. When that happens, it uses the last set text which is blank.
It's much better to use Swing Timers and here's an example that does what you're trying to accomplish:
if (match) {
// Another class calculates
} else {
outputField.setText("INPUT ERROR");
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
outputField.setText("");
}
};
Timer timer = new Timer(5000, listener);
timer.setRepeats(false);
timer.start();
}
As Philip Whitehouse states in his answer, you are blocking the swing Event Dispatch Thread with the Thread.sleep(...) call.
Given that you've taken the time to set up an ActionListener already, it would probably be easiest to use a javax.swing.Timer to control clearing the text. To do this, you could add a field to your GUI class:
private Timer clearTimer = new Timer(5000, this);
In the constructor for GUI, turn off the repeats feature, as you really only need a one-shot:
public GUI() {
clearTimer.setRepeats(false);
createFrame();
}
Then, actionPerformed can be modified to use this to start the timer/clear the field:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == equals) {
inputField.setText(inputField.getText().replaceAll("\\s", ""));
String text = inputField.getText();
System.out.println(text);
Pattern equationPattern = Pattern.compile("[\\d(][\\d-+*/()]+[)\\d]");
boolean match = equationPattern.matcher(text).matches();
System.out.println(match);
if (match) {
// Another class calculates
} else {
clearTimer.restart();
outputField.setText("INPUT ERROR"); // This doesn't appear
}
} else if (e.getSource() == clearTimer) {
outputField.setText("");
}
}
You're doing a Thread.sleep() in the Swing main thread. This is NOT good practice. You need to use a SwingWorker thread at best.
What's happening is that it's running the first line, hitting Thread.sleep().
This prevents the (main) EDT thread from doing any of the repaints (as well as preventing the next line executing).
You should use a javax.swing.Timer to setup the delayed reaction and not put sleep() calls in the main thread.
I want to build a simple memory game. I want to put a replay button, which is play again the memory game.
I have built a class named MemoryGame and a main class.
Here is the part of the ButtonListener code.
public void actionPerformed(ActionEvent e) {
if (exitButton == e.getSource()) {
System.exit(0);
}
else if (replayButton == e.getSource()) {
//How can I declare it?
}
}
If I declare the replay button as :
new MemoryGame();
It's work fine, but it pops up another windows.
I want to clear the current display and return to the beginning, without a new windows. How can I do that?
EDIT :
I think I need to rewrite the code of my program, because my program does not have the init() method as suggested which is the initial state of the program.
My Java knowledge is very limited and usually I create less method and dump most into a method.
I will try to redo my program.
Thanks for the suggestions.
Show us what is inside the MemoryGame how you create its initial state. Effectively what folks are suggesting here is for you is to have an initial method which will set-up the game state which the MemeoryGame constructor will call. Then on replay-button of the game you call this method.
Something along these lines:
void init(){
this.x = 10;
this.y = 10;
}
public MemoryGame(){
init();
}
public void actionPerformed(ActionEvent e) {
if (exitButton == e.getSource()) {
System.exit(0);
}
else if (replayButton == e.getSource()) {
init();
}
}
one way you can do it although it might be dirty, is to grab your MemoryGame constructor, and put the stuff inside it inside another method, and call that method in your constructor and inside the button event.
as an example i have made the following class and it resets itself with the use of the previous technique:
public class App extends JFrame{
public static void main(String[] args){
new App();
}
public App(){
init();
}
private JButton changeColorButton;
private JButton resetAppButton;
private JPanel panel;
private void init() {
changeColorButton=null;
resetAppButton=null;
panel=null;
this.setSize(200,400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setBackground(Color.white);
panel.setPreferredSize(new Dimension(200,400));
changeColorButton = new JButton("Change");
changeColorButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.setBackground(Color.black);
panel.repaint();
}
});
changeColorButton.setPreferredSize(new Dimension(100,100));
resetAppButton = new JButton("Reset");
resetAppButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
init();
}
});
resetAppButton.setPreferredSize(new Dimension(100,100));
panel.add(changeColorButton);
panel.add(resetAppButton);
this.add(panel);
this.validate();
}
}
what this app does is it has two buttons. one changes the color and the other resets the app itself.
You should think about re-factoring your code so that the MemoryGame class does not create the GUI, then you wont be recreating it whenever you initialise a new Game.
It's a good idea to keep program logic separate to UI code.
What you could do is you could call dispose() on your JFrame. This will get rid of it and go to your title screen like this:
Here's the button code
public void actionPerformed(ActionEvent event)
{
if (closeButton = event.getSource())
{
System.exit(0);
}
if (playAgainButton = event.getSource())
{
Game.frame.dispose(); // Your class name, then the JFrame variable and call dispose
}
}
This will work but you may have a few problems reseting your program. If so then create a reset method where you can reset all your variables and call when playAgainButton is clicked. For example:
public void reset()
{
// Right here you'd reset all your variables
// Perhaps you have a gameOver variable to see if it's game over or not reset it
gameOver = false;
}
I want my GUI to make some checks when a JOptionPane appears.
Because I can't find any other way, I though I can do those each time the application window loses focus(its just checking a string). For that reason I added the following code on my JFrame:
appFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowLostFocus(WindowEvent e) {
System.out.println("Focus Lost");
}
#Override
public void windowClosing(WindowEvent e) {
//some other stuff here that work
}
});
The window closing listener works fine. Although when the JFrame isn't focused nothing happens. Shouldn't "Focus Lost" be printed each time I switch from JFrame to some other window? Also, will this method be triggered when a JOptionPane is shown?
The key to me is that you want a change in the GUI triggered by a change of a String variable. The best way I see to solve this is to make the String variable a bound property by using PropertyChangeListenerSupport. This way you can have the GUI attach a PropertyChangeListener to the class that holds the String variable and then be notified when it changes allowing you to update the GUI appropriately.
If you go this route, consider giving the observed class a SwingPropertyChangeSupport field so that the listeners will be notified on the Swing event thread and hopefully avoid any Swing concurrency issues.
Here's a brief example:
import java.awt.Dimension;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class ShowPropertyChangeSupport {
#SuppressWarnings("serial")
private static void createAndShowGui() {
final MainGUI mainGui = new MainGUI("Title");
final ObservedClass observedClass = new ObservedClass();
observedClass.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getPropertyName().equals(ObservedClass.BOUND_PROPERTY)) {
mainGui.setTitle(pcEvt.getNewValue().toString());
}
}
});
mainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainGui.pack();
mainGui.setLocationRelativeTo(null);
mainGui.setVisible(true);
int timerDelay = 6000; // every 6 seconds
new Timer(timerDelay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String result = JOptionPane.showInputDialog(mainGui,
"Please enter a String", "Set GUI title", JOptionPane.PLAIN_MESSAGE);
if (result != null) {
observedClass.setBoundProperty(result);
}
}
}){{setInitialDelay(1000);}}.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// ** note that I don't like extending JFrame,
// but will do this for sake of example simplicity
class MainGUI extends JFrame {
public MainGUI(String title) {
super(title);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
}
class ObservedClass {
public static final String BOUND_PROPERTY = "bound property";
private String boundProperty = "";
private SwingPropertyChangeSupport spcSupport = new SwingPropertyChangeSupport(
this);
public SwingPropertyChangeSupport getSpcSupport() {
return spcSupport;
}
public void setSpcSupport(SwingPropertyChangeSupport spcSupport) {
this.spcSupport = spcSupport;
}
public String getBoundProperty() {
return boundProperty;
}
public void setBoundProperty(String boundProperty) {
String oldValue = this.boundProperty;
String newValue = boundProperty;
this.boundProperty = newValue;
spcSupport.firePropertyChange(BOUND_PROPERTY, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
spcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
spcSupport.removePropertyChangeListener(listener);
}
}
The key to all this in my mind is to use the listener so that the class with the bound property -- the String being listened to -- has no knowledge of the GUI, the listener, and the GUI, likewise has no knowledge of the class with the bound property. They are fully decoupled.
I'm not going to go into why you are doing what you are doing, but it is not working as you expect for the following reason:
WindowAdapter is a convenience class so you can create one listener and register it for multiple types of events. You have only registered it for one set of events, you need to also register it for focus events via: Window.addWindowFocusListener()
WindowAdapter adapter = new WindowAdapter() {
#Override
public void windowLostFocus(WindowEvent e) {
System.out.println("Focus Lost");
}
#Override
public void windowClosing(WindowEvent e) {
//some other stuff here that work
}
};
appFrame.addWindowListener(adapter);
appFrame.addWindowFocusListener(adapter);
1) JOptionPane / modal JDialog have got modality issue, but modality could be advantage if all containers have got own owner, for real workaround you need to know (I'll talking about how can I do test that)
numbers of Window[], and if isDisplayable(), then you can use follows
you can get SwingUtilities#getAccessibleIndexInXxx can returns AccessibleState
KeyboardFocusManager (very interesting methods for multi-touch) returns getXxxFocusXxx methods
Focus, FocusSubsystem is pretty asynchronous,
2) Please, with due respect, I don't know why you needed that, for why reasons I need to know about that, there is about business rules, you always need to know ...., and if is done on EDT
Focus, FocusSubsystem is pretty asynchronous,
I'm making an App. in java , in which there is a Button to which I have added an actionlistener. The ActionEvent it(the button) generates executes some code. Now I want this piece of code to run whenever the app. starts and without pressing the button. I mean, I want to generate the Actionevent (without pressing the button) so that the piece of code the ActionPerformed contains gets executed as the app. start. After that, it may run whenever I press the button.
You can create ActionEvents like any other Java Object by just using the constructor. And then you can send them directly to the component with Component.processEvent(..)
However, in this case I think you are better making your code into a separate function which is called both:
By the ActionListener when the button is pressed
Directly by your application startup code (possibility using SwingUtilities.invokeLater() or SwingUtilities.invokeAndWait() if you need it to happen on the event-handling thread)
This way you don't mix up presentation logic with the business logic of whatever the code does....
Yes it can be done, but it doesn't really make sense, since your goal isn't to press a button or to call an ActionListener's code, but rather to have a common behavior on button press and on program start up. To me the best way to achieve this is to have a method that is called by both the actionPerformed method of the ActionListener and by the class at start up.
Here's a simple example. In the code below, a method disables a button, turns the JPanel green, and starts a Timer that in 2 seconds enables the button and resets the JPanel's background color to its default. The method that causes this behavior is called both in the main class's constructor and in the JButton's ActionListener's actionPerformed method:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ActionOnStartUp extends JPanel {
private static final int PANEL_W = 400;
private static final int PANEL_H = 300;
private static final int TIMER_DELAY = 2000;
private JButton turnGreenBtn = new JButton("Turn Panel Green for 2 seconds");;
public ActionOnStartUp() {
turnPanelGreen();
turnGreenBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
turnPanelGreen();
}
});
add(turnGreenBtn);
}
public void turnPanelGreen() {
setBackground(Color.green);
turnGreenBtn.setEnabled(false);
new Timer(TIMER_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
setBackground(null);
turnGreenBtn.setEnabled(true);
((Timer) ae.getSource()).stop(); // stop the Timer
}
}).start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PANEL_W, PANEL_H);
}
public static void createAndShowGui() {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ActionOnStartUp());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Usually, the button action event responds to an external event, to notify the application that the user (or rather something or someone) interacted with the application. If your button executes some code that you want to also execute at application start, why not just place everything at it's proper place?
Example:
public class SomeSharedObject {
public void executeSomeCode() { /*....*/ }
}
Set the button with something like
public void setButtonAction(final SOmeSharedObject obj) {
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
obj.executeSomeCode();
}
});
}
And run at application start with something like
public void initApplication(SomeSharedObject obj) {
obj.executeSomeCode();
}
And, if the code you need to execute takes a while to complete, you might want to use a separate thread inside your actionPerformed button event so your application UI does not freeze up.
Just Call JButton.doClick() it should fire the ActionEvent associated with the JButton.