Hot questions for Using JTextField in methods

Question:

Method FourOfAKind is supposed to test 4 JTextFields and check if they all equal each other. Each JTextField excepts one number. When I press the ButtonListener the boolean method FourOfAKind doesn't respond, even if it returns false, when I enter numbers 5555 ex.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
 */
public class MyPanel extends JPanel
{
    private JLabel inputLabel, outputLabel;
    private JButton button;
    private JTextField digit1, digit2, digit3, digit4;

    public MyPanel()
    {
        inputLabel = new JLabel ("Enter four one digit numbers between zero and 9");
        button = new JButton ("Result");
        outputLabel = new JLabel ("---");

        digit1 = new JTextField(1);
        digit1.addActionListener (new ButtonListener());

        digit2 = new JTextField(1);
        digit2.addActionListener (new ButtonListener());

        digit3 = new JTextField(1);
        digit3.addActionListener (new ButtonListener());

        digit4 = new JTextField(1);
        digit4.addActionListener (new ButtonListener());

        add(inputLabel);
        add(digit1);
        add(digit2);
        add(digit3);
        add(digit4);
        add(button);
        add(outputLabel);

        setPreferredSize(new Dimension(300,100));
        setBackground(Color.yellow);
    }

    private class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent even)
        {
            int num1, num2, num3, num4;

            String text = digit1.getText();
            num1 = Integer.parseInt(text);

            String text2 = digit2.getText();
            num2 = Integer.parseInt(text2);

            String text3 = digit3.getText();
            num3 = Integer.parseInt(text3);

            String text4 = digit4.getText();
            num4 = Integer.parseInt(text4);

            if (fourOfAKind(num1, num2, num3, num4))
            outputLabel.setText ("four of a kind");
        }
    }

    public boolean fourOfAKind(int a, int b, int c, int d)
    {
        return (a == b && b == c && c == d);
    }
}

Answer:

The ButtonListener needs to be added to the button only, so that it will be activated when you press the button and trigger the event.

You can remove 'digitN.addActionListener(new ButtonListener());` and instead use:

button.addActionListener(new ButtonListener());

Like that, you are instructing Java to listen to the button being pressed and not the text field (which will trigger it when pressing the Enter key)

Question:

I'm looking for a way to set the display of a JTextField to take up the entire width of the JPanel that contains it.

The only method I've been able to find to do this is the setColumns() method combined with a getWidth() method called on the JPanel after the pack() and setVisible() methods are called. But when I do this the JTextField ends up much larger than the JPanel that encloses it. My assumption on why this happens is that the getWidth() returns that size of the JPanel in pixels, and the columns in the JTextField are all larger than a pixel.

I'm not even looking for the field to dynamically resize, just to be as wide as the JPanel at the start of the program

Any help greatly appreciated


Answer:

Make use of an appropriate layout manager...

Remember, it's not the responsibility of the component to decide how big it should, that's the responsibility of the layout manager, the component can only provide hints about how big it would like to be...

For example, you could do this with a GridBagLayout...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {

            JTextField field = new JTextField(10);
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(field, gbc);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

Take a look at Laying Out Components Within a Container for more details

Question:

I have an ActionListener connected to a JTextField and want to type something so that it will exit the method the ActionListener is in.

Code:

main() {
    Security(x,x,x);
}
public void Security(JTextArea out, JTextField in) {
        in.setText("");
        in.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (in.getText().contains("exitsys")) {
                    out.append("Security:Security System Deactivated\n");
                    return;
                }
                in.setText("");
            }
        });
        out.append("Security:Security System Activated\n");
        fileWrite(":SYSTEM_INITIATED@" + time(), out);
    }

I want to type "exitsys" and return to the main class method "main()".

The fileWrite method uses a PrintWriter to output data.

QUESTION SUMMARY: I try calling return; but it does not return to the method main(), how do i fix this?


Answer:

Basically what you need is some kind of modal dialog, which will allow you to, effectively, halt the execution of your program at the point the dialog is made visible until the dialog is dismissed (closed), when the execution will continue...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JDialog dialog = new JDialog();
                dialog.setTitle("Testing");
                dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                dialog.add(new TestPane());
                dialog.pack();
                dialog.setLocationRelativeTo(null);
                dialog.setVisible(true);

                System.out.println("Now back in the main...");
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextField field;

        public TestPane() {

            setLayout(new GridBagLayout());

            field = new JTextField(10);
            field.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if ("exitsys".equals(field.getText())) {
                        SwingUtilities.getWindowAncestor(field).dispose();
                    }
                }
            });

            add(field);

        }

    }

}

See How to Make Dialogs for more details

Question:

What is the best / common practise to start running methods from a running JFrame according to user input?

Scenario The background is that I would like to have a JFrame running and a bar-code scanner attached. This bar-code scanner would scan not predefined (no fixed length) bar-codes (alpha numerical with special characters) and than look for special character like * and start an action.

The problem The format of the Bar-code is: * First Name * Surname * Birth-year. I was thinking of running my "analysing" method each time the contents of the JTextField changes but I believe that is necessary work there.

Lets say this is scanned * John * Doe * 1988 The characters from a bar-code scanner come in "one by one" and this would result in 13 unnecessary "content checks" .. And this is where I am stuck. I want my solution to be as efficient as is can :)

Note: Yes a solution could be letting the USER "confirm his input" after he scanned, by a button or some action and than "analyse the input" - but this is what I would like to avoid and make it fully automatic (and efficient)

How would your approach or tips and tricks be please?


Answer:

SwingWorker is appropriate for this. Read the data in your implementation of doInBackground() and publish() the result when a complete record is available. Your implementation of process() can then safely update a view component's model on the event dispatch thread. As shown in this related example, you can cancel() and restart the worker as required. You may also need to reset your scanning state if there's been no input for some empirically determined time, e.g. 300 ms.

Question:

I've the following problem: I need to read a integer from my JTextField and use it again in a painting method (paintComponent). With this integer I need to set the size of the square. I've added a listener to the textfield and created a class for it to get the value as an integer, followed by repaint. But the square stays the same size.

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

class MouseDemoOld extends JPanel implements MouseListener 
  {
  int x, y; // location of mouse
  int sx, sy; // size of shape 
 JFrame frame;
 JTextField tf;

 void buildIt() 
 {     
   frame = new JFrame("MouseDemo");
   tf = new JTextField("100");
   frame.add(this);
   frame.add(tf, BorderLayout.SOUTH);
   this.x = 150;
   this.y = 150;
   this.sx = 10;
   this.sy = sx;

    HandlerClass handler = new HandlerClass();
    tf.addActionListener(handler);

    this.addMouseListener(this); // MouseDemo is its own MouseListener!  
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.setLocation(200, 200);
    frame.setVisible(true);
    }

  public void paintComponent(Graphics g) 
  {
    super.paintComponent(g);
    g.setColor( Color.blue );
    g.fillRect(x - sx/2, y - sy/2, sx, sy);
  }    

  // the method from MouseListener we're interested in this time
  public void mousePressed( MouseEvent e) 
  {
    // add code to update x and y 
    x = e.getX();
    y = e.getY();
    repaint();
  }   

  public void mouseReleased( MouseEvent e) { }
  public void mouseClicked( MouseEvent e) { }
  public void mouseEntered( MouseEvent e) { }
  public void mouseExited( MouseEvent e) { }

  private class HandlerClass implements ActionListener
  {
    public void actionPerformed(ActionEvent event)
    {
      if(event.getSource()==tf)
      {
        int text = Integer.parseInt(tf.getText());
        int sx = text;
        int sy = text;
        repaint();
      }
    }
  }

  public static void main(String[] args) 
  {
    new MouseDemoOld().buildIt(); 
  }
}  

Answer:

Do not redefine sx and sy in HandlerClass. Since HandlerClass is an inner class it can access the sx and sy fields of the outer class. So, just remove the int keyword from both variables in HandlerClass. Also, you want to catch NumberFormatException when calling Integer.parseInt in case a non-integer is entered into the text field.