Java Swing button actionEvent - java

sorry to bother everyone.
Overall problem: I'm trying to open a dialogue box let the user enter something then close it
Issue: - A function is not being called (i think)
- The main problem is when i use debug it works fine so Its difficult for me to track down the problem
I'm having trouble with JButtons,
it works in debug but not in normal run. this was probably because i was using an infinite loop. someone online suggested i used SwingUtilities but that didn't work (at least i don't think.
/**
*
* #author Deep_Net_Backup
*/
public class butonTest extends JFrame {
String name;
boolean hasValue;
//name things
private JLabel m_nameLabel;
private JTextField m_name;
//panel
private JPanel pane;
//button
private JButton m_submit;
//action listener for the button submit
class submitListen implements ActionListener {
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
}
}
//constructor
public butonTest(){
//normal values
name = null;
hasValue = false;
//create the defauts
m_nameLabel = new JLabel("Name:");
m_name = new JTextField(25);
pane = new JPanel();
m_submit = new JButton("Submit");
m_submit.addActionListener(new submitListen());
//
setTitle("Create Cat");
setSize(300,200);
setResizable(false);
//add components
pane.add(m_nameLabel);
pane.add(m_name);
pane.add(m_submit);
add(pane);
//last things
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
//submit
private void submit()
{
System.out.println("submit");
name = m_name.getText();
hasValue = true;
}
//hasValue
public boolean hasValue()
{
return(hasValue);
}
//get the text name
public String getName()
{
return(name);
}
public void close()
{
setVisible(false);
dispose();
}
public static void main(String[] args)
{
/* Test 1
boolean run = true;
String ret = new String();
butonTest lol = new butonTest();
while(run)
{
if(lol.hasValue())
{
System.out.println("Done");
run = false;
ret = new String(lol.getName());
lol.close();
}
}
System.out.println(ret);*/
//Tset 2
/*
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
butonTest lol = new butonTest();
if(lol.hasValue())
{
System.out.println(lol.getName());
}
}
});*/
}
}
Edit:
How its not working: When i run Test the program will print test and submit then it should change the hasValue to true. this will (hopefully) allow the if statement to run to print done. This does not happen.
Edit 2:
I have just added a few more lines for further testing 2 prints and this seems to have solved the issue (but this is bad)
System.out.println("hasValue " + hasValue); -> to the hasValue() function
System.out.println("set to true"); -> submit() function

You are doing something far too complicated than is necessary. Instead of having the listener as a seperate class, you could have it as an anonymous class. That way you can get a handle on the outer class (butonTest.this), and call any method you want on it.
m_submit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
butonTest.this.close();
}
});
I'm not sure what you are trying to do with the infinite loop. It would have run to completion before you show the dialog anyway.
It would help to read up a bit on how Event-Handling works in Swing :)

I am afraid your constructor butonTest() and submit() method are out of your
class (public class butonTest extends JFrame).
you need to get them inside your class:

Related

Why is my boolean value preemptively being returned?

I am working on a login validator and have a class that checks username and password validity. After checking, a boolean variable (isValidLoginCredentials) is updated in the LoginProxy class, which can be fetched by a get method and used for another purpose. However, the value that is returned by the get method is always the default value that I assigned to isValidLoginCredentials when the class was created. I think the issue is that I am calling the getter method in main() before I have a chance to update isValidLoginCredentials, but I don't understand what changes I should make to stop this. Here is the relevant part of the class and main program.
public class LoginProxy implements ActionListener
{
private JLabel usernameLabel;
private JTextField usernameText;
private JLabel passwordLabel;
private JPasswordField passwordText;
private JButton loginButton;
private boolean isValidLoginCredentials = false;
public void createLogin()
{
/*Here was code irrelevant to the problem I removed*/
loginButton.addActionListener(new LoginProxy());
loginButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String user = usernameText.getText();//get the username
String pass = passwordText.getText();//get the password
String credentials = user +":"+pass;//creates the string I compare to other valid
//credentials
ConcreteLoginValidator validator = new ConcreteLoginValidator(credentials);
try
{
isValidLoginCredentials = validator.checkLogin();
System.out.println("The credentials are "+isValidLoginCredentials);
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}
});
}
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
}
public boolean getValidity()
{
return isValidLoginCredentials;
}
And here is the main method
public static void main(String[] args)
{
boolean isValidLogin = false;
LoginProxy proxy = new LoginProxy();
proxy.createLogin();
isValidLogin = proxy.getValidity();
if(isValidLogin == true)
{
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
}
What should I add so that isValidLogin=proxy.getValidity(); returns a value only after I have already entered and checked whether the login credentials are correct?
Going straight to the point, a quick fix is to put the code below:
if(isValidLoginCredentials) {
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
After this part:
System.out.println("The credentials are "+isValidLoginCredentials);
The code you call on createLogin() just sets the action listener to the button in the UI, hence the code will be executed just when you click on the button.
On the top of that, when you open a window, it starts a separated thread. I don't know the rest of the code, but assuming that when you instantiate the LoginProxy, it opens the login window. But the way you wrote, it will open the window and check the isValidLogin straight away (it doesn't wait you to click the button).
If you want to prove that, you can simply put a System.out.println before and after the proxy.createLogin(). You will realise that both lines will be reached while the UI is rendered.
Using a modal dialog that blocks until it is closed.
Very simplified example:
public class Dialog { // LoginProxy in questions code
private String value = null;
public void show(Window owner) {
var dialog = new JDialog(owner, JDialog.DEFAULT_MODALITY_TYPE);
var field = new JTextField(40);
var okButton = new JButton("OK");
okButton.addActionListener(ev -> {
value = field.getText();
dialog.dispose();
});
var panel = new JPanel();
panel.add(field);
panel.add(okButton);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(owner);
dialog.setVisible(true); // this will be blocked until JDialog is closed
}
public String getValue() {
return value;
}
}
called like
public static void main(String[] args) {
var dialog = new Dialog();
dialog.show(null);
System.out.println(dialog.getValue()); // check if valid and open JFrame in questions code
}
Advantage of this solution IMHO: the dialog class (LoginProxy) does not need to know about the main class and main JFrame. It has a clear single function: ask for user input.
the dialog creation is even easier using JOptionPane
In order to guarantee reading a value written in another thread, you must make the field volatile:
private volatile boolean isValidLoginCredentials;
You must also wait until the other completes before reading it. That aspect I leave to the reader.

Java Swing: 'java.awt.AWTEventMulticaster.mouseMoved' error

I have been trying to create a 'catch me if you can' game: when I start it, it randomly chooses where to allocate a 'click me' button. I am not supposed to be able to click the button, the text should be re-assigned to another button before I am able to do that.
It works for a while but then it throws the following error: "java.awt.AWTEventMulticaster.mouseMoved".
I have been trying to fix the problem with removeListener() method but I don't seem to be able to find a solution. Any comments?
Here's my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.*;
public class Game extends JFrame {
//Panels
private JPanel mainPanel = new JPanel();
// Buttons
private JButton[] buttons = new JButton[9];
private JButton theChosenButton = new JButton();
// other
private int random = 0;
public Game() {
this.setTitle("Catch me if you can");
mainPanel.setLayout(new GridLayout(3, 3));
// creates buttons
for(int i = 0; i < 9 ; i++) {
buttons[i] = new JButton();
mainPanel.add(buttons[i]);
}
// Add everything to frame
this.getContentPane().add(mainPanel);
this.setSize(400, 400);
this.setVisible(true);
}
// generates random number between 1 and 9 to be used
public int clickMeGenerator(){
random = (int) Math.floor(Math.random() * 9);
return random;
}
// randomly assigns clickMeGenerator to a button
// add mouseMoved listener to the chosen button
public void assign(){
int randomButton = this.clickMeGenerator();
theChosenButton = buttons[randomButton];
theChosenButton.addMouseMotionListener(new MouseHover());
theChosenButton.setText("Click me");
}
public void removeListener() {
theChosenButton.removeMouseMotionListener(new MouseHover());
//}
}
// inner class
class MouseHover implements MouseMotionListener {
public void mouseMoved(MouseEvent e) {
theChosenButton.setText("");
Game.this.assign();
}
public void mouseDragged(MouseEvent e) {
}
}
} // end of class
Test class:
public class GameTest {
public static void main (String args[]) {
Game myGame = new Game();
myGame.assign();
}
}
Thank you so much for your help!
Just for clarity, the "actual" error is ...
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.desktop/java.awt.AWTEventMulticaster.mouseMoved(AWTEventMulticaster.java:337)
at java.desktop/java.awt.AWTEventMulticaster.mouseMoved(AWTEventMulticaster.java:337)
So looking through the code...
public void assign() {
int randomButton = this.clickMeGenerator();
theChosenButton = buttons[randomButton];
theChosenButton.addMouseMotionListener(new MouseHover());
theChosenButton.setText("Click me");
}
You are repeatedly add a new MouseMotionListener to you buttons, over and over again, and...
public void removeListener() {
theChosenButton.removeMouseMotionListener(new MouseHover());
//}
}
is pointless, as you're trying to remove a new instance of MouseHover from the button, but it will never have been applied in the first place.
The first thing I would do is create an instance of MouseHover as an instance field in Game
private MouseHover mouseHover = new MouseHover();
and use it when calling addMouseMotionListener and removeMouseMotionListener.
I would then, remove the listener from the "currently" active button before adding it to the next one.
Personally, I would do this in the assign method
public void assign() {
int randomButton = this.clickMeGenerator();
if (theChosenButton != null) {
theChosenButton.removeMouseMotionListener(mouseHover);
}
theChosenButton = buttons[randomButton];
theChosenButton.addMouseMotionListener(mouseHover);
theChosenButton.setText("Click me");
}
I would also ensure that assign is called from within the Event Dispatching Thread when the class is first created, as the UI has been realised by the end of the constructor of Game, meaning the first call to assign is outside of the context of the EDT, which is not recommended.
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Game myGame = new Game();
myGame.assign();
}
});
}

Access static variable from another class

I have two classes in same package. i have declared a static variable in one class and want to access that variable in another class.
Here is my code in which i have declared the static variable
public class wampusGUI extends javax.swing.JFrame {
static String userCommand;
public wampusGUI() {
initComponents();
}
public void setTextArea(String text) {
displayTextArea.append(text);
}
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
userCommand = commandText.getText();
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
wampusGUI w = new wampusGUI();
w.setVisible(true);
Game g = new Game(w);
g.play();
}
});
}
}
Here is the code in which i want to access variable
public class Game {
private wampusGUI gui;
public Game(wampusGUI w) {
world = new World();
world.start();
gui = w;
}
public void play() {
gui.setTextArea(welcome());
gui.setTextArea(describe());
for (;;) {
String s = userCommand; // here value should come should
System.out.println(userCommand);
Command c = Command.create(s);
String r = c.perform(world);
// is game over?
if (r == null) {
break;
}
System.out.println(r);
}
System.out.println("Game over");
}
}
However, i can pass the variable from first class as a argument. but the problem is that, when i will run program the value is going null first time, which i dont want. i want when i enter value in textfield then it should go to another class.
Thank you.
Looking at your code, it seems you want to show dialogs to your user with a certain text
gui.setTextArea(welcome());
gui.setTextArea(describe());
and sometimes, that dialog should capture user input which is handled afterwards.
Those setTextArea calls are not what you want to use. The user will never see the welcome message as it will immediately be replaced by the describe message.
Make sure you do not block the Event Dispatch Thread (EDT) or nothing will be shown at all. I do not know what your Command class will do, but I see an infinite loop on the Event Dispatch Thread which is never a good thing. Take a look at the Concurrency in Swing tutorial for more information
Thanks to that for loop, the user will simply not be capable to input any command as the EDT is busy handling your loop. What you need is a blocking call allowing the user to provide input (not blocking the EDT, but just blocking the execution of your code). The static methods in the JOptionPane class are perfectly suited for this (e.g. the JOptionPane#showInputDialog). These methods also have a mechanism to pass the user input back to the calling code without any static variables, which solves your problem.
I suggest that you use a listener of one sort or another to allow the Game object to listen for and respond to changes in the state of the GUI object. There are several ways to do this, but one of the most elegant and useful I've found is to use Swing's own innate PropertyChangeSupport to allow you to use PropertyChangeListeners. All Swing components will allow you to add a PropertyChangeListener to it. And so I suggest that you do this, that you have Game add one to your WampusGUI class (which should be capitalized) object like so:
public Game(WampusGUI w) {
gui = w;
gui.addPropertyChangeListener(new PropertyChangeListener() {
// ....
}
This will allow Game to listen for changes in the gui's state.
You'll then want to make the gui's userCommand String a "bound property" which means giving it a setter method that will fire the property change support notifying all listeners of change. I would do this like so:
public class WampusGUI extends JFrame {
public static final String USER_COMMAND = "user command";
// ....
private void setUserCommand(String userCommand) {
String oldValue = this.userCommand;
String newValue = userCommand;
this.userCommand = userCommand;
firePropertyChange(USER_COMMAND, oldValue, newValue);
}
Then you would only change this String's value via this setter method:
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
setUserCommand(commandText.getText());
}
The Game's property change listener would then respond like so:
gui.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// is the property being changed the one we're interested in?
if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) {
// get user command:
String userCommand = pcEvt.getNewValue().toString();
// then we can do with it what we want
play(userCommand);
}
}
});
One of the beauties of this technique is that the observed class, the GUI, doesn't have to have any knowledge about the observer class (the Game). A small runnable example of this is like so:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class WampusGUI extends JFrame {
public static final String USER_COMMAND = "user command";
private String userCommand;
private JTextArea displayTextArea = new JTextArea(10, 30);
private JTextField commandText = new JTextField(10);
public WampusGUI() {
initComponents();
}
private void setUserCommand(String userCommand) {
String oldValue = this.userCommand;
String newValue = userCommand;
this.userCommand = userCommand;
firePropertyChange(USER_COMMAND, oldValue, newValue);
}
private void initComponents() {
displayTextArea.setEditable(false);
displayTextArea.setFocusable(false);
JButton enterButton = new JButton("Enter Command");
enterButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
enterButtonActionPerformed(evt);
}
});
JPanel commandPanel = new JPanel();
commandPanel.add(commandText);
commandPanel.add(Box.createHorizontalStrut(15));
commandPanel.add(enterButton);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(new JScrollPane(displayTextArea));
mainPanel.add(commandPanel, BorderLayout.SOUTH);
add(mainPanel);
}
public void setTextArea(String text) {
displayTextArea.append(text);
}
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
setUserCommand(commandText.getText());
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
WampusGUI w = new WampusGUI();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.pack();
w.setLocationRelativeTo(null);
w.setVisible(true);
Game g = new Game(w);
g.play();
}
});
}
}
class Game {
private WampusGUI gui;
public Game(WampusGUI w) {
gui = w;
gui.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// is the property being changed the one we're interested in?
if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) {
// get user command:
String userCommand = pcEvt.getNewValue().toString();
// then we can do with it what we want
play(userCommand);
}
}
});
}
public void play() {
gui.setTextArea("Welcome!\n");
gui.setTextArea("Please enjoy the game!\n");
}
public void play(String userCommand) {
// here we can do what we want with the String. For instance we can display it in the gui:
gui.setTextArea("User entered: " + userCommand + "\n");
}
}
I agree with Jon Skeet that this is not a good solution...
But in case u want an dirty solution to ur problem then u can try this:
public class wampusGUI extends javax.swing.JFrame
{
private static wampusGUI myInstance;
public wampusGUI( )
{
myInstance = this;
initComponents();
}
public static void getUserCommand()
{
if(myInstance!=null)
{
return myInstance.commandText.getText();
}
else
{
return null;
}
}
......
......
}
in the other class use:
public void play()
{
.....
//String s = userCommand; // here value should come should
String s = wampusGUI.getUserCommand();
.....
}
This kind of code is there in some of our legacy projects... and I hate this.

Infinite focus loop on textFields

I have 2 JTextFields:
JTextField txtJobType, txtPriorityCode;
This is the functionality I need:
When user types in 'administration' in txtJobType and hits tab (or clicks away) an error check is done to see whether the field is empty or if the text entered exists in database. The way I have done that is:
private void txtJobTypeFocusLost(java.awt.event.FocusEvent evt) {
System.out.println("JobType Focus Lost");
if (!checkFieldExists(txtJobType.getText(), "jobType", "jobCode",
JobType.class) || txtJobType.getText().isEmpty()) {
txtJobType.requestFocusInWindow();
txtJobType.selectAll();
} else {
}
}
So if the field doesn't exist or the text is empty, then return focus to the txtJobType and highlight all the text (if any)
That works without a problem. However, I have the txtPriorityCode field which needs to have the exact same behaviour. So I did:
private void txtPriorityCodeFocusLost(java.awt.event.FocusEvent evt) {
System.out.println("PriorityCode Focus Lost");
if (!checkFieldExists(txtPriorityCode.getText(), "priority", "priorityCode",
Priority.class) || txtPriorityCode.getText().isEmpty()) {
txtPriorityCode.requestFocusInWindow();
txtPriorityCode.selectAll();
}
}
This is where the problem starts: if user leaves jobType and tabs to Priority then the code attempts to return focus back to jobtype, but because priority is also blank at that point, it will attempt to get focus back from jobtype, resulting in this output:
PriorityCode Focus Lost
JobType Focus Lost
PriorityCode Focus Lost
JobType Focus Lost
Any help on how I could implement this behaviour is appreciated, as I have to do this for at least 10 other textfields.
Thank You!
You shouldn't be fiddling with focus lost or other low-level constructs. Instead, why not simply use an InputVerifier as per this example and this one too?
For example, it could look something like this:
import javax.swing.*;
public class InputVerifierEg {
private JPanel mainPanel = new JPanel();
private JTextField txtJobType = new JTextField(10);
private JTextField txtPriorityCode = new JTextField(10);
public InputVerifierEg() {
txtJobType.setInputVerifier(new MyInputVerifier("jobType", "jobCode",
JobType.class));
txtPriorityCode.setInputVerifier(new MyInputVerifier("priority", "priorityCode",
Priority.class));
mainPanel.add(new JLabel("Job Type:"));
mainPanel.add(txtJobType);
mainPanel.add(Box.createHorizontalStrut(15));
mainPanel.add(new JLabel("Priority Code:"));
mainPanel.add(txtPriorityCode);
}
public JPanel getMainPanel() {
return mainPanel;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("InputVerifierEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new InputVerifierEg().getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyInputVerifier extends InputVerifier {
private String fieldName;
private String codeName;
private Class<?> classType;
public MyInputVerifier(String fieldName, String codeName, Class<?> classType) {
this.fieldName = fieldName;
this.codeName = codeName;
this.classType = classType;
}
#Override
public boolean verify(JComponent input) {
JTextField tField = (JTextField) input;
// assuming that the checkFieldExists is a static method of a utility class
if (!FieldCheckerUtil.checkFieldExists(tField.getText(), fieldName,
codeName, classType)) {
return false;
}
if (tField.getText().trim().isEmpty()) {
return false;
}
return true;
}
#Override
public boolean shouldYieldFocus(JComponent input) {
JTextField tField = (JTextField) input;
if (verify(input)) {
return true;
} else {
tField.selectAll();
// show JOptionPane error message?
return false;
}
}
}
Personally, I hate it when validation is done like this and prevents me from moving around fields in a form as I see fit. Why not do validation on all the fields when the form is submitted and highlight the invalid ones at that time?
Maybe do one check of:
txtPriorityCode.getText().isEmpty()
And then on the other, test if:
!txtPriorityCode.getText().isEmpty() && txtJobType.getText().isEmpty()
i.e. only do the check on the second one if the first one isn't empty.

A simple question regarding ActionListener and 'enter' key

I am working on an assignment, and I need to enter an SQL Query in a textfield. The user can either press the custom 'execute query' button, or they can press the enter key. When either of these are used, it is to trigger an ActionListener (no other listener is allowed). Is it as simple as writing:
if (e.getSource()=='querybutton' || e.getSource=='enter')
Or is there more to it than this?
As I said, it is a simple question (I know).
edit:
I would write this bit in my ActionPerformed as:
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==gui.executeQueryButton || e.getSource()==gui.enter)
{
String query = gui.queryText.getText();
//more code to follow
}
}
e.getSource() actually returns the object responsible for firing the event (not the name of the variable you used when creating the control). In this case, your button. You could in principle compare e.getSource() with the actual button instances. However, are you actually adding this action listener to buttons other than those two? Presumably you'd only have to add this listener to the two buttons for which you want this behavior -- in which case you wouldn't have to have this if check.
" Is it as simple as writing:
if (e.getSource()=='querybutton' || e.getSource=='enter')"
It's not simple to write this, but rather it is wrong to write it.
For one you don't want to compare Strings with ==, for another, you don't declare Strings with single quotes, and for a third, the enter key is not obtained in this way, but rather by adding the appropriate ActionListener object to the JTextField itself, and finally there should be in a single ActionListener class that handles this action, so the if block is completely unnecessary. This can probably be best done with a small inner private ActionListener class. You'd then create one object of this class and add it as an ActionListener for the querybutton and for the JTextField.
edit 1:
A more complete example of what I mean is shown below, a demo class that has a private inner handler class:
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerEg extends JPanel {
private JButton queryButton = new JButton("Query");
private JTextField textField = new JTextField("hello", 20);
public ActionListenerEg() {
QueryListener qListener = new QueryListener();
queryButton.addActionListener(qListener);
textField.addActionListener(qListener);
add(queryButton);
add(textField);
}
private class QueryListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
String textInField = textField.getText();
System.out.println("Use text in field, \"" + textInField + "\" to call SQL query in a background SwingWorker thread.");
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("ActionListenerEg");
frame.getContentPane().add(new ActionListenerEg());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
The ActionListener is fired either by pressing the button or by pressing enter from within the JTextField. I'd then have in my control class, code that is called inside of the actinoPerformed method.
edit 2: Having most handler or "control" code in its own Handler or Control class can be a good idea, but it doesn't have to implement ActionListener interface itself, but rather just have the code that will be called from within the ActionListener codes. For example, here I try to put all the handler code in its own class. It will have different methods that are called for various situations. e.g.,
import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerEg extends JPanel {
private ActionListenerHandler handler;
private JButton queryButton = new JButton("Query");
private JButton displayButton = new JButton("Display");
private JTextField textField = new JTextField("hello", 20);
// pass in handler or handler
public ActionListenerEg(final ActionListenerHandler handler) {
this.handler = handler;
QueryListener qListener = new QueryListener();
queryButton.addActionListener(qListener);
textField.addActionListener(qListener);
displayButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (handler != null) {
handler.displayActionPerformed(e);
}
}
});
add(queryButton);
add(textField);
add(displayButton);
}
private class QueryListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (handler != null) {
String textInField = textField.getText();
handler.doQueryAction(e, textInField);
}
}
}
private static void createAndShowUI() {
ActionListenerHandler handler = new ActionListenerHandler();
JFrame frame = new JFrame("ActionListenerEg");
frame.getContentPane().add(new ActionListenerEg(handler));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class ActionListenerHandler {
public void displayActionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog((Component) e.getSource(), "Display things!");
}
public void doQueryAction(ActionEvent e, String textInField) {
String text = "We will use \"" + textInField + "\" to help create and run the SQL Query";
JOptionPane.showMessageDialog((Component) e.getSource(), text);
}
}
Please ask questions if it's clear as mudd, or if anything is wrong.

Categories