Handling editing events in a JTextField - java

I have a login form where a user can enter his credentials to login. I have a JLabel that serves to display the text telling the user that the user name cannot be empty. This label is display after a user click the login button when the text field is empty.
I want that the moment the user starts typing in the text field the label with the information should disappear.How do I achieve this behavior?
Here is the code:
public class JTextFiledDemo {
private JFrame frame;
JTextFiledDemo() {
frame = new JFrame();
frame.setVisible(true);
frame.setSize(300, 300);
frame.setLayout(new GridLayout(4, 1));
frame.setLocationRelativeTo(null);
iniGui();
}
private void iniGui() {
JLabel error = new JLabel(
"<html><font color='red'> Username cannot be empty!<></html>");
error.setVisible(false);
JButton login = new JButton("login");
JTextField userName = new JTextField(10);
frame.add(userName);
frame.add(error);
frame.add(login);
frame.pack();
login.addActionListener((ActionEvent) -> {
if (userName.getText().equals("")) {
error.setVisible(true);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JTextFiledDemo tf = new JTextFiledDemo();
}
});
}
}

You have to create DocumentListener:
DocumentListener dl = new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent de)
{
error.setVisible(false);
}
#Override
public void removeUpdate(DocumentEvent de)
{
//
}
#Override
public void changedUpdate(DocumentEvent de)
{
error.setVisible(false);
}
};
then for your text fields:
login.getDocument().addDocumentListener(dl);

For that purposes you need to use DocumentListener on your JTextField, here is tutorial.
As example:
userName.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent de){
event(de);
}
#Override
public void removeUpdate(DocumentEvent de) {
event(de);
}
#Override
public void changedUpdate(DocumentEvent de){
event(de);
}
private void event(DocumentEvent de){
error.setVisible(de.getDocument().getLength() == 0);
// as mentioned by nIcE cOw better to use Document from parameter
frame.revalidate();
frame.repaint();
}
});
error must be final(for java lower than 8 version).
Also at start your field is empty, so may be need to use setVisible(true) on error label.

You can add a keyListener in the input filed
userName.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent arg0) {
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyPressed(KeyEvent arg0) {
error.setVisible(false);
}
});

Related

Cant use dispose(); method, Java Gui form

I have some problems with using dispose() method in my GUI project.
I' am making a GUI swing application for some kind of Elections in IntelliJ.
My problem is, by clicking a button(Confirm1, or 2 or 3) I want to open new JFrame which is checking the age of voter and closes the current JFrame where this button is located by calling dispose().
But frame.dispose(); doesn't work.
I have my JFrame declared in public static main().
Should I make reference for it in my ActionListener? I have been looking for solution, but I couldn't find any.
Here is a code:
import javax.swing.*; //another libraries
public class ElectionGUI {
private JPanel labelElection; // another texfields or etc.
private JButton Confirm1;
private JButton Confirm3;
private JButton Confirm2;
private JPanel Elections;
public VotesGUI(){
Votes votes = new Votes("...","...",0);
listX.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrX.setText(listX.getSelectedValue().toString());
}
}
});
listY.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrY.setText(listY.getSelectedValue().toString());
}
}
});
listZ.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrZ.setText(listZ.getSelectedValue().toString());
}
}
});
Confirm1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesX();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check(); /// referention, to my next //Jframe called psvm Check();
}
});
Confirm2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesY();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check();
}
});
Confirm3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesZ();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check();
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame("Elentions");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setContentPane(new ElectionGUI().labelElection);
frame.pack();
}
}

How can i wait for a frame to perform an action before the code execute the next line?

I want to initialize a Graphical User Interface (GUI) for the user to input a form. After this is accomplished i want to open a new GUI, but as soon as the first GUI pops-up the next one is initialized to.
Is there any way to solve this without using waits and notifies?
here is an example of my code:
public static void main(String[] args) {
new GUIForm();
// wait until the user inputs the complete form
new GUIWelcome();
}
It is really simple I woild like to keep it that way.
Create an Interface OnActionListener
public interface OnActionListener {
public void onAction();
}
Add these code in GUIForm class
private OnActionListener listener;
private JButton action;
public GUIForm(OnActionListener listener) {
this.listener = listener;
action = new JButton("Action");
action.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
GUIForm.this.listener.onAction();
}
});
}
Now you can achieve that
new GUIForm(new OnActionListener() {
#Override
public void onAction() {
new GUIWelcome();
}
});
You need to use some sort pub/sub mechanism. This in a nutshell is what you need:
public class PubSub {
public static void main(String[] args) {
JFrame frame1 = new JFrame("GUIForm");
frame1.setSize(640, 480);
JButton button = new JButton("User Input");
JFrame frame2 = new JFrame("Welcome");
frame2.setSize(320, 240);
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
#Override
public void mouseExited(MouseEvent e) {
button.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
#Override
public void mouseClicked(MouseEvent e) {
frame2.setVisible(true);
}
});
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.add(button);
frame1.setVisible(true);
}
}
This version uses JFrame's listeners, but you could implement your on callback mechanism to accomplish the same

changing the value of a text field as another is changed and the same but reversed causing an error

I am making a simple Miles-Kilometers converter that updates automatically as you type. The problem is that is that an error is thrown somewhere. I believe that this is because as i change one of the fields it handles the event and changes the other field but since that also has an event handler for when it is changed it tries to change the other field itself and they keep firing events back and forth until something somewhere explodes. Any idea how I can fix this or is there a different problem completely ?
Here's my code:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
public class Book extends JFrame{
private JTextField jtfKilometers = new JTextField(10);
private JTextField jtfMiles = new JTextField(10);
public Book(){
setLayout(new BorderLayout(10, 0));
JPanel jlblPanel = new JPanel(new GridLayout(2, 0, 50, 5));
jlblPanel.add(new JLabel("Kilometers"));
jlblPanel.add(new JLabel("Miles"));
add(jlblPanel, "West");
JPanel jtfPanel = new JPanel(new GridLayout(2, 0, 5, 5));
jtfPanel.add(jtfKilometers);
jtfPanel.add(jtfMiles);
add(jtfPanel, "Center");
jtfKilometers.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
if(jtfKilometers.getText().equals("")){
jtfMiles.setText("");
}else{
jtfMiles.setText(Double.parseDouble(jtfKilometers.getText()) * 0.621371 + "");
}
}
#Override
public void removeUpdate(DocumentEvent e) {
insertUpdate(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
insertUpdate(e);
}
});
jtfMiles.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
if(jtfMiles.getText().equals("")){
jtfKilometers.setText("");
}else{
jtfKilometers.setText(Double.parseDouble(jtfMiles.getText()) * 1.60934 + "");
}
}
#Override
public void removeUpdate(DocumentEvent e) {
insertUpdate(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
insertUpdate(e);
}
});
}
public static void main(String[] args){
Book f = new Book();
f.setDefaultCloseOperation(MyFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
You need to add additional guard on the focus of the text fields, so that you will be modifying only the other text field, not recursively both of them.
jtfKilometers.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
if (jtfKilometers.hasFocus()) { // ADD THIS LINE
if (jtfKilometers.getText().equals("")) {
jtfMiles.setText("");
} else {
jtfMiles.setText(Double.parseDouble(jtfKilometers.getText()) * 0.621371 + "");
}
}
}
and similarly
jtfMiles.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
if (jtfMiles.hasFocus()) { // ADD THIS LINE
if (jtfMiles.getText().equals("")) {
jtfKilometers.setText("");
} else {
jtfKilometers.setText(Double.parseDouble(jtfMiles.getText()) * 1.60934 + "");
}
}
}
An easy fix for this is checking if the frame has focus when the event is triggered. This will prevent the event from triggering back and forth like is happening to you now.
See the adjusted code snippet from your sample below...
public void insertUpdate(DocumentEvent e) {
if(jtfMiles.hasFocus()){//Check for focus here....repeat same check on your other "insertUpdate" method for your other frame.
if(jtfMiles.getText().equals("")){
jtfKilometers.setText("");
}else{
jtfKilometers.setText(Double.parseDouble(jtfMiles.getText()) * 1.60934 + "");
}
}
}
Hope this helps!

setEnabled(true) when radioButton.isSelected()

as I said in other posts I'm new in Java and I'm having some dumb problems, here's the deal:
I have a radioButton (radioStock) and a textField (stockField). I want stockField to be setEnabled(false) by default, no problem with that, and whenever the radioStock is checked, set the stockField enabled on true. I wrote this code, but it doesn't work.
if (radioStock.isSelected()) {
stockField.setEnabled(true);
}else{
stockField.setEnabled(false);
}
That code needs to be in a listener that is attached to the JRadioButton such as an ActionListener or ItemListener. And you don't even need the if blocks since all you'd need is one line of code inside of the listener:
radioStock.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent itemEvent) {
stockField.setEnabled(itemEvent.getStateChange() == ItemEvent.SELECTED);
}
});
For more on use of JRadioButtons, please check out the tutorial: button tutorial.
Edit my SSCCE
import java.awt.event.*;
import javax.swing.*;
public class ItemListenereg {
private static void createAndShowGui() {
final JRadioButton radioStock = new JRadioButton("Stock", true);
final JTextField stockField = new JTextField(10);
JPanel panel = new JPanel();
panel.add(radioStock);
panel.add(stockField);
radioStock.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent itemEvent) {
stockField.setEnabled(itemEvent.getStateChange() == ItemEvent.SELECTED);
}
});
JOptionPane.showMessageDialog(null, panel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
This should work
radioStock.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(radioStock == e.getSource())
{
stockField.setEnabled(radioStock.isSelected());
}
}
});

Simultaneously update text area while typing in text field

I want to update my text area along with typing in the text field but i get a delay of 1 keystroke while typing i.e when i press a key the previous key is displayed.Here is my snippet
private void jTextField1KeyTyped(java.awt.event.KeyEvent evt)
{
String a = jTextField1.getText();
jTextArea1.setText(a);
}
I would not recommend using KeyListeners
Simply add a DocumentListener to your JTextField via:
textField.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent de) {
}
#Override
public void removeUpdate(DocumentEvent de) {
}
#Override
public void changedUpdate(DocumentEvent de) {
}
});
Inside each of the methods ( insertUpdate,removeUpdate and changedUpdate) simply put in a call to set the text of your JTextArea via setText():
textArea.setText(textField.getText());
Here is an example I made:
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().createAndShowUI();
}
});
}
private void createAndShowUI() {
final JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(JFrame frame) {
final JTextField jtf = new JTextField(20);
final JTextArea ta = new JTextArea(20,20);
ta.setEditable(false);
jtf.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent de) {
ta.setText(jtf.getText());
}
#Override
public void removeUpdate(DocumentEvent de) {
ta.setText(jtf.getText());
}
#Override
public void changedUpdate(DocumentEvent de) {
//Plain text components don't fire these events.
}
});
frame.getContentPane().add(jtf, BorderLayout.WEST);
frame.getContentPane().add(ta, BorderLayout.EAST);
}
}
You should do that under the keyReleased event instead of the keyTyped and it will work as you need.
You need to wait till the event on your TextField is processed before updating the TextArea. Your code update the TextArea before the TextField is done processing the new typed character. Hence the text set in the TextArea is one keystroke behind.
You could try using recursion by referencing the method inside the method (avoid loops though).

Categories