How to make a String not-deletable in JTextarea? - java

Basically, I have a dropdown menu containing templates. For example:
apple( )
banana( )
Once one of them is selected, it pastes onto a JTextArea. My problem is if "apple( )" is selected, I want "apple" and the two brackets non-deletable in the TextArea, and user can enter anything inside the brackets.
Can anyone give me any direction/ideas here? I have been searching on the internet and found very little about this.

Check out the Proctected Text Component. It allows you to mark individual pieces of text as protected so that it can't be changed or deleted.
It uses a DocumentFilter as well as a NavigationFilter.
For a simpler solution you might be able to just use a NavigationFilter. The example below shows how you can prevent the selection of text at the beginning of the Document. You should be able to customize it to also prevent selection of text at the end of the document as well.
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class NavigationFilterPrefixWithBackspace extends NavigationFilter
{
private int prefixLength;
private Action deletePrevious;
public NavigationFilterPrefixWithBackspace(int prefixLength, JTextComponent component)
{
this.prefixLength = prefixLength;
deletePrevious = component.getActionMap().get("delete-previous");
component.getActionMap().put("delete-previous", new BackspaceAction());
component.setCaretPosition(prefixLength);
}
#Override
public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.setDot(Math.max(dot, prefixLength), bias);
}
#Override
public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.moveDot(Math.max(dot, prefixLength), bias);
}
class BackspaceAction extends AbstractAction
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextComponent component = (JTextComponent)e.getSource();
if (component.getCaretPosition() > prefixLength)
{
deletePrevious.actionPerformed( null );
}
}
}
private static void createAndShowUI()
{
JTextField textField = new JTextField("Prefix_", 20);
textField.setNavigationFilter( new NavigationFilterPrefixWithBackspace(7, textField) );
JFrame frame = new JFrame("Navigation Filter Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(textField);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

You'll have to do this yourself. I'd suggest you to make an event handler that fires every time the text changes (Click here to find out how). And inside that handler check if the JTextArea still starts with "apple(" and ends with ")".

Related

How to make the end of a JTextArea editable

Is there a way to make the end of a JTextArea editable and make anything that has already been printed to it not editable?
What I mean by this is if I've written "Hello World" for example to a JTextArea, how could I make it so that the user can type in whatever they want after "Hello World" but they cannot type before that or delete the already printed text?
Below is a small program to demonstrate my troubles...
public class Test {
public static void main(String[] args) {
//Here I create a simple JFrame with JTextArea
JTextArea textArea = new JTextArea();
JFrame frame = new JFrame();
JFrame.setDefaultLookAndFeelDecorated(true);
frame.setSize(250, 250);
textArea.setEditable(true);
textArea.setVisible(true);
frame.add(textArea);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/*Here I print "Hello World" onto the text area.. after the ">>" I want the
the user to be able to type whatever they want.. however I don't want them
to be able to edit the "Hello World"*/
textArea.append("Hello World\n>>");
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}
In the example the user is able to enter whatever text they want.. which is what I want.. however they are also able to edit the text that I printed using append.. which I don't want..
How can I solve this?
Yes, a DocumentFilter will work. Create one that only allows addition of text if the addition is at the end of the document -- that is if the offset equals the document's length. Also totally inactivate the remove method. Something like so:
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
public class MyFilter extends DocumentFilter {
#Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
// only insert text if at the end of the document
// if offset == document length
if (offset == fb.getDocument().getLength()) {
super.insertString(fb, offset, string, attr);
}
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
// only replace text if at the end of the document
// if offset == document length
if (offset == fb.getDocument().getLength()) {
super.replace(fb, offset, length, text, attrs);
}
}
#Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
// do nothing. Totally inactivate this
}
}
And you could test it like so:
import javax.swing.*;
import javax.swing.text.PlainDocument;
#SuppressWarnings("serial")
public class LimitedTextArea extends JPanel {
private JTextArea textArea = new JTextArea(15, 50);
public LimitedTextArea() {
// get textArea's Document and cast to PlainDocument:
PlainDocument document = (PlainDocument) textArea.getDocument();
// set the document's filter with "MyFilter"
document.setDocumentFilter(new MyFilter());
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
private static void createAndShowGui() {
LimitedTextArea mainPanel = new LimitedTextArea();
JFrame frame = new JFrame("LimitedTextArea");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
You could also use a NavigationFilter:
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class NavigationFilterPrefix extends NavigationFilter
{
private int prefixLength;
private Action deletePrevious;
public NavigationFilterPrefix(int prefixLength, JTextComponent component)
{
this.prefixLength = prefixLength;
deletePrevious = component.getActionMap().get("delete-previous");
component.getActionMap().put("delete-previous", new BackspaceAction());
component.setCaretPosition(prefixLength);
}
#Override
public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.setDot(Math.max(dot, prefixLength), bias);
}
#Override
public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.moveDot(Math.max(dot, prefixLength), bias);
}
class BackspaceAction extends AbstractAction
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextComponent component = (JTextComponent)e.getSource();
if (component.getCaretPosition() > prefixLength)
{
deletePrevious.actionPerformed( null );
}
}
}
private static void createAndShowUI()
{
JTextField textField = new JTextField("Prefix_", 20);
textField.setNavigationFilter( new NavigationFilterPrefix(7, textField) );
JFrame frame = new JFrame("Navigation Filter Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(textField);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
This will allow the user to edit the text they add to the text field.
This will prevent the fixed text from being selected.
For more advanced features, check out the Protected Document which allows you to protect multiple areas of the Document from being changed.

How to change the background color of a JSpinner dependent on the current edited content of the field?

I have a GUI with a JSpinner using a SpinnerNumberModel using double values.
As soon as I change the content of the Editor of the JSpinner, I want the background to change to yellow (to show that the currently displayed value is not the one "saved" in the JSpinner respectively its Model.
If that content is not valid (e.g. out of the allowed range specified by my SpinnerNumberModel or a text as "abc") the background should change to red.
I tried to achieve what I want with a FocusListener already but yet have not been successful, also I am not sure if It could work anyway, as I need to check the content somewhere between focussing and defocussing.
I checked Tutorials for all Listeners that exist for Swing components, but could not find a right one that suits the job. (here I informed myself)
I am new to the concept of Listeners and would really appreciate any help that gets me closer to solving the problem but also helps generally understanding Listeners and how to use them in this context better!
My really basic code example with the mentioned poor attempt using a focus listener:
public class test implements FocusListener{
JFrame frame;
SpinnerNumberModel model;
JSpinner spinner;
JComponent comp;
JFormattedTextField field;
public test() {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
model = new SpinnerNumberModel(0., 0., 100., 0.1);
spinner = new JSpinner(model);
comp = spinner.getEditor();
field = (JFormattedTextField) comp.getComponent(0);
field.addFocusListener(this);
frame.getContentPane().add(spinner);
frame.getContentPane().add(new JButton("defocus spinner")); //to have something to defocus when testing :)
frame.pack();
frame.setVisible(true);
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
//when the values of the field and the spinner don't match, the field should get yellow
if(!field.getValue().equals(spinner.getModel().getValue())) {
field.setBackground(Color.YELLOW);
}
}
#Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
//if they match again, reset to white
if(!field.getValue().equals(spinner.getModel().getValue())) {
field.setBackground(Color.RED);
}
}
}
A JSpinner uses a text field as the editor for the spinner
So, you can add a DocumentListener to the Document of the text field that is used as the editor.
Something like:
JTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField());
textField.getDocument.addDocumentListener(...);
Then when text is added/removed a DocumentEvent will be generated and you can do your error checking. Read the section from the Swing tutorial on Listener For Changes on a Document for more information and working examples.
You can use CaretListener , here is a start:
import java.awt.Color;
import java.awt.Component;
import javax.swing.BoxLayout;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class SpinerTest{
JSpinner spinner;
public SpinerTest() {
JFrame frame = new JFrame("frame");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
SpinnerNumberModel model = new SpinnerNumberModel(0., 0., 100., 0.1);
spinner = new JSpinner(model);
setCaretListener();
frame.getContentPane().add(spinner);
frame.pack();
frame.setVisible(true);
}
private void setCaretListener() {
for(Component c : spinner.getEditor().getComponents()) {
JFormattedTextField field =(JFormattedTextField) c;
field.addCaretListener(new CaretListener(){
#Override
public void caretUpdate(CaretEvent ce) {
if (field.isEditValid()) {
//add aditional test as needed
System.out.println("valid Edit Entered " + field.getText());
field.setBackground(Color.WHITE);
}
else {
System.out.println("Invalid Edit Entered" + field.getText());
field.setBackground(Color.PINK);
}
}
});
}
}
public static void main(String[] args) {
new SpinerTest();
}
}
I was able to fulfill the task with a combination of a KeyListener, a DocumentListener and a FocusListener. The solution might not be the easiest, but finally I coded sth. that works. Comments in the file appended should explain how I dealt with the problem.
I expanded the original task with a CommaReplacingNumericDocumentFilter expands DocumentFilter class that was not written by me, I got the code from my professor and edited it to my needs only. Now only digits, minus and e, E are accepted as entries in the JSpinner.
Commas are replaced with dots also.
Code:
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class test implements DocumentListener, ChangeListener, KeyListener{
boolean keyPressed;
JFrame frame;
SpinnerNumberModel model;
JSpinner spinner;
JComponent comp;
JFormattedTextField field;
public test() {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
model = new SpinnerNumberModel(0., 0., 100000., .1);
spinner = new JSpinner(model);
//disable grouping for spinner
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner);
editor.getFormat().setGroupingUsed(false);
spinner.setEditor(editor);
comp = spinner.getEditor();
field = (JFormattedTextField) comp.getComponent(0);
field.getDocument().addDocumentListener(this);
field.addKeyListener(this);
spinner.addChangeListener(this);
frame.getContentPane().add(spinner);
frame.pack();
frame.setVisible(true);
}
#Override
public void insertUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
public static boolean isNumeric(String str)
{
try
{
double d = Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
public static void main(String[] args) {
//to get the right format for double precision numbers
Locale.setDefault(Locale.US);
test test = new test();
}
#Override
public void stateChanged(ChangeEvent e) {
System.out.println("valuechanged: " + spinner.getValue().toString());
if(keyPressed) {
field.setBackground(Color.WHITE);
}
keyPressed = false;
}
public void DocumentEventHandler(DocumentEvent e) {
//as soon as update is inserted, set background to yellow
if (keyPressed) {
field.setBackground(Color.YELLOW);
//check if input is numeric and in bounds
String text = field.getText();
if (isNumeric(text)) {
double value = Double.parseDouble(text);
if (value < (Double)model.getMinimum() || value > (Double)model.getMaximum()) {
field.setBackground(Color.RED);
}
}
else { //set background to red
field.setBackground(Color.RED);
}
}
keyPressed = false;
//System.out.println(e.toString());
//System.out.println("Text: " + field.getText());
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
/** If not done yet, replaces the DocumentFilter with one replacing commas by decimal points.
* This can't be done at the very beginning because the DocumentFilter would be changed to a
* javax.swing.text.DefaultFormatter$DefaultDocumentFilter when setting up the JSpinner GUI. */
public void keyPressed(KeyEvent e) {
PlainDocument document = (PlainDocument)(field.getDocument());
if(!(document.getDocumentFilter() instanceof CommaReplacingNumericDocumentFilter))
document.setDocumentFilter(new CommaReplacingNumericDocumentFilter());
/*Tell the other handlers that a key has been pressed and the change in the document does
* not come from using the JSpinner buttons or the MouseWheel.
*/
keyPressed = true;
}
}
/** A javax.swing.text.DocumentFilter that replaces commas to decimal points
* and ignores non-numeric characters except 'e' and 'E'. This is called before
* modi */
class CommaReplacingNumericDocumentFilter extends DocumentFilter {
#Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr)
throws BadLocationException {
text = filter(text);
if (text.length() > 0)
super.insertString(fb, offset, text, attr);
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
text = filter(text);
if (text.length() > 0)
super.replace(fb, offset, length, text, attrs);
}
String filter(String text) {
return text.replace(',', '.').replaceAll("[^0-9eE.-]","");
}
}

How to make part of a JTextField uneditable

I wanted to develop a console-like interface, similar to IDLE. That involved determining how to prevent a certain part of the text in a JTextField from being edited. For example:
>>> help
Where the ">>> " is uneditable. The caret must never move behind a certain position, and the text behind that position cannot be edited in any way.
I looked at NavigationFilter, but it doesn't seem to prevent keyboard driven manipulation of the caret.
This shows how to do it with a NavigationFilter:
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class NavigationFilterPrefixWithBackspace extends NavigationFilter
{
private int prefixLength;
private Action deletePrevious;
public NavigationFilterPrefixWithBackspace(int prefixLength, JTextComponent component)
{
this.prefixLength = prefixLength;
deletePrevious = component.getActionMap().get("delete-previous");
component.getActionMap().put("delete-previous", new BackspaceAction());
component.setCaretPosition(prefixLength);
}
#Override
public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.setDot(Math.max(dot, prefixLength), bias);
}
#Override
public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
fb.moveDot(Math.max(dot, prefixLength), bias);
}
class BackspaceAction extends AbstractAction
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextComponent component = (JTextComponent)e.getSource();
if (component.getCaretPosition() > prefixLength)
{
deletePrevious.actionPerformed( null );
}
}
}
private static void createAndShowUI()
{
JTextField textField = new JTextField("Prefix_", 20);
textField.setNavigationFilter( new NavigationFilterPrefixWithBackspace(7, textField) );
JFrame frame = new JFrame("Navigation Filter Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(textField);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Spent a little while figuring this out, so I thought I would share my solution for anyone else with the same dilemma. I don't know if it's optimal, but it does seem to work.
It prevents the user from using backspace behind the postion n. It also moves the caret back to n for any other events, such as (illegally) changing the caret position with the arrow keys or mouse. Finally, it resets the text and caret position after a entry is processed.
EDIT: While I'm leaving this answer here for posterity, see the accepted answer for the best way to solve this problem.
JTextField in = new JTextField();
final String protectMe = ">>> "; //protect this text
final int n = protectMe.length();
in.setText(protectMe);
in.setCaretPosition(n);
in.addCaretListener(new CaretListener()
{
#Override
public void caretUpdate(CaretEvent e)
{
if (e.getDot() < n)
{
if (!(in.getText().length() < n))
in.getCaret().setDot(n);
}
}
});
in.addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent arg0)
{
if (in.getCaret().getDot() <= n)
{
in.setText(protectMe + in.getText().substring(n));
arg0.consume();
}
}
#Override
public void keyReleased(KeyEvent arg0){}
#Override
public void keyTyped(KeyEvent arg0){}
});
in.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
String input = in.getText().substring(n).trim();
//do something
in.setText(protectMe);
in.setCaretPosition(n);
}
});
As usual, let me know if there's anything I missed!

In Java how do you trap the event before the new JTab is switched to?

how do you trap the event before the new tab is switched to?
In every Tab I have JTable and i do something with it's data(delete, add , update). I would like to do data validation(save or cancel changes) before switching to the new tab. I use Java 1.5.
class ViewPanel extends JPanel
{
private void Components() {
setPreferredSize(new Dimension(700, 400));
tabbedPane.addTab("DC", ANSFER.getIcon(),new DcTabPanel(this), "DC");
tabbedPane.addTab("PC", THUMB4.getIcon(),new PcTabPanel(this), "PC");
tabbedPane.addChangeListener(this);
add(tabbedPane);
}
public void stateChanged(ChangeEvent e) {
}
}
JTabbedPane is backed by a SingleSelectionModel. If you extend DefaultSingleSelectionModel, you can override the setSelectedIndex method and implement your logic.
// in new selection model:
public void setSelectedIndex(int index) {
// do pre-switch things here
super.setSelectedIndex(index);
}
// in ViewPanel, on tabbedPane create:
tabbedPane.setModel(newSelectionModel);
The reason you can't simply use a ChangeListener is because that fires on change. By extending the selection model, you fire before the tab change.
You can prevent tab switching by extending JTabbedPane and override setSelectedIndex(int). Here is a small example illustrating that. It simply prevents from switching between non-contiguous tabs:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class Test2 {
private static class BlockingTabbedPane extends JTabbedPane {
public static interface TabSwitchAllower {
public boolean allowTabSwitch(int from, int to);
}
private TabSwitchAllower allower;
public BlockingTabbedPane(TabSwitchAllower allower) {
super();
this.allower = allower;
}
#Override
public void setSelectedIndex(int index) {
if (allower == null || allower.allowTabSwitch(getSelectedIndex(), index)) {
super.setSelectedIndex(index);
}
}
}
protected static void initUI() {
final JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BlockingTabbedPane.TabSwitchAllower allower = new BlockingTabbedPane.TabSwitchAllower() {
#Override
public boolean allowTabSwitch(int from, int to) {
if (Math.abs(from - to) == 1) {
return true;
} else {
JOptionPane.showMessageDialog(frame, "You can only switch between contiguous tabs");
}
return false;
}
};
JTabbedPane tabbedPane = new BlockingTabbedPane(allower);
for (int i = 0; i < 10; i++) {
tabbedPane.addTab("Tab-" + i, new JLabel("Hello tab " + i));
}
frame.add(tabbedPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
}
java actionlistener on a tab
How to Write a Change Listener (Oracle Docs)
JTabbedPane API (Oracle Docs)
Those two links should help you out. I haven't really worked with tabbedPanes, but I am assuming that the getSelectedComponent() will return the current selected tab. So you can have a handle to the currentTab which will be set during instantiation. Then you can have something like this.
class TabListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
// Replace JSlider with whatever your tab's data type is
JSlider source = (JSlider)e.getSource();
// Use the 'currentTab' handle to do what you want.
currentTab = getSelectedComponent();
// I'm assuming that the 'selected component' by the time this stuff
// runs is going to be the new selected tab.
}
}
I am not too confident about my answer, but I certainly hope that this will point you towards the right direction! Please say if you need any clarification or anything! If I happen to discover anything that I think might be useful, I'll be certain to edit my answer!

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