What is the best way to validate swing application's input fields such as text fields, comboboxes, etc and let the user to press Save button only if everything is ok. Assume that Search function also in the same interface. So searching for record will also fill up input fields. But Save button should remain disable in that case.
initComponents();
btnSave.setEnabled(false);
txt1.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
}
#Override
public void removeUpdate(DocumentEvent e) {
validate(txt1.getText(),e);
}
#Override
public void insertUpdate(DocumentEvent e) {
validate(txt1.getText(),e);
}
public void validate(String enteredText,DocumentEvent e) {
String currText = "";
try {
Document doc = (Document) e.getDocument();
currText = doc.getText(0, doc.getLength());
} catch (BadLocationException e1) {
}
if(enteredText.equals(currText)){
//if validated successfully
btnSave.setEnabled(false);
}else{
btnSave.setEnabled(true);
}
}
});
did you try like this?
final JTextField textField = new JTextField();
final JButton submitBtn = new JButton();
submitBtn.setEnabled(true);
textField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
validate(e);
}
public void removeUpdate(DocumentEvent e) {
validate(e);
}
public void insertUpdate(DocumentEvent e) {
validate(e);
}
public void validate(String enteredText) {
String currText = "";
try {
Document doc = (Document)e.getDocument();
currText = doc.getText(0, doc.getLength());
} catch (BadLocationException e1) {
e1.printStackTrace();
}
//validation of currText here
//if validated successfully
submitBtn.setEnabled(true);
//else
submitBtn.setEnabled(false);
}
});
Condition the enabled property of your Save button using setEnabled() in two places:
In your implementation of shouldYieldFocus() in an InputVerifier attached to each relevant component. The tutorial and some examples are cited here.
In your component's normal listener.
Create a method to check if all the inputs are completed or/and all the validations are passed and finally return a boolean.
public boolean validate(...){
//some stuff
if(validated){
return true;
}else{
return false;
}
}
then you can use it like.
button.setEnabled(validate(...));
Related
I need to create a editable JComboBox that show data from SqLite database, that matches to typed text in JComboBox. I Used DocumentListener and it worked but I got an Exception like below:
Attempt to mutate in notification
This is my code,
org.jdesktop.swingx.autocomplete.AutoCompleteDecorator.decorate(jComboBox1);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JTextComponent tcA = (JTextComponent) jComboBox1.getEditor().getEditorComponent();
tcA.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
try {
SQDB s = new SQDB();
ResultSet rs = s.getData("SELECT e_word FROM words WHERE e_word LIKE '" + tcA.getText()+ "%'");
while (rs.next()) {
jComboBox1.addItem(rs.getString("e_word"));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
}
});
}
});
How to solve this Exception. Thank you
I am working in java swing in netbeans.
I have a textfield. I would like that a combobox will be enabled only if the text written in the textfield is greatter tahn one.
My code works if I press the enter key. But I would like to make it work just by writting in the textfield. How can I do this?
private void nmrintervTXTActionPerformed(java.awt.event.ActionEvent evt) {
String text = this.nmrintervTXT.getText();
System.out.println(text);
if (!text.isEmpty()) {
if (Integer.parseInt(text) > 1) {
this.evidenceOtherApplicantsTXT.setEnabled(true);
}
}
}
See addCaretListener API.
textfield.addCaretListener(new CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
System.out.println("caretUpdate with new text: "+textfield.getText());
}
});
class MyDocumentListener implements DocumentListener {
#Override
public void insertUpdate(javax.swing.event.DocumentEvent e) {
update(e);
}
#Override
public void removeUpdate(javax.swing.event.DocumentEvent e) {
update(e);
}
#Override
public void changedUpdate(javax.swing.event.DocumentEvent e) {
}
public void update(javax.swing.event.DocumentEvent e) {
String text = nmrintervTXT.getText();
try {
evidenceOtherApplicantsTXT.setEnabled(Integer.parseInt(text) > 1);
} catch (NumberFormatException nfe) {
evidenceOtherApplicantsTXT.setEnabled(false);
}
}
}
public MyClass() {
initComponents();
}
#SuppressWarnings("unchecked")
nmrintervTXT = new javax.swing.JTextField();
nmrintervTXT.getDocument().addDocumentListener(new MyDocumentListener());
I think the parameter e was in fault in update in MyDocumentListener.
Ive been trying a while and cant work out a way to get the text out of a textbox only after the barcode scanner has finished scanning. I am using Swing Framework and Java. My Code works if the text is pasted (Ctrl + V) into the JTextbox but the barcode scanner just does not work as my methods run for every couple of characters of the barcode in turn.
textField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
// warn();
}
public void removeUpdate(DocumentEvent e) {
// warn();
}
public void insertUpdate(DocumentEvent e) {
warn();
}
public void warn() {
input = textField.getText();
SwingUtilities.invokeLater(doUpdate);
}
});
Where input is a variable which I use
The doUpdate method which gets executed is here
final Runnable doUpdate = new Runnable() {
#Override
public void run() {
System.out.println(input + " Is being processed");
textField.setText("");
System.out.println(input.length());
lblStatus.setIcon(new ImageIcon(Main.class
.getResource("/com/daniel/status2.png")));
// frame.getContentPane().add(lblStatus2, BorderLayout.EAST);
if (input.length() <= 4) {
lblStatus.setIcon(new ImageIcon(Main.class
.getResource("/com/daniel/status3.png")));
return;
}
// TODO START
if (!content.containsKey(input)) {
content.put(input, "1");
} else {
Integer i = Integer.valueOf(content.get(input));
i++;
lblStatus.setIcon(new ImageIcon(Main.class.getResource(i
+ ".png")));
playSound(i + "");
if (i.equals(6)) {
i = 0;
}
content.put(input, String.valueOf(i));
}
System.out.println(content.get(input));
Properties properties = new Properties();
for (Entry<String, String> entry : content.entrySet()) {
properties.put((String) entry.getKey(), entry.getValue());
}
try {
properties.store(new FileOutputStream(path
+ "data.properties"), null);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
All Im asking is how do I run a method with a String from the text box only after the barcode reader has finished
It's been a while since I used a barcode reader, but when I did each scan was a line. That is, each scan was a sequence of characters terminated by the new line character. So, you could test the input and only invoke doUpdate when you detect the new line character. That said, you might need to set a property on the text box to allow the new line character and remove it when detected.
You need someway to inject a delay between each update of the DocumentListener and the time your inspect/use the value from the text field.
A simple solution is to use a Swing Timer with a short delay (you can play around with this to find the threashold which is most useful to you). Each time the DocumentListener is notified, you simply reset the timer (start it again), so that it won't trigger until after the delay you specified has occurred, at which time you can read the text from the field.
public class TestPane extends JPanel {
private Timer updateTimer;
private JTextField field;
private JLabel label;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
updateTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(field.getText());
}
});
updateTimer.setRepeats(false);
label = new JLabel("...");
field = new JTextField(14);
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
processUpdate();
}
#Override
public void removeUpdate(DocumentEvent e) {
processUpdate();
}
#Override
public void changedUpdate(DocumentEvent e) {
processUpdate();
}
});
add(field, gbc);
add(label, gbc);
}
protected void processUpdate() {
updateTimer.restart();
}
}
You could test this using Robot, which can be used to inject key strokes into the event queue with a specified delay, or just run your scanner at it.
See How to use Swing Timers for more details
You should also attach a ActionListener to the field and see if the scanner triggers the ActionListener, which would be a simpler solution over all
I want To insert hyperlink in JPanel (so that on clicking i go to web address)
Is it possible ?
If yes, how can i do this?
See the How to Use HTML in Swing Components
tutorial.
We've been using something like this:
public class UrlTextPane extends JTextPane {
private final Pattern urlPattern = Pattern.compile(UrlUtil.URL_REGEX);
public UrlTextPane() {
this.setEditable(false);
this.addHyperlinkListener(new UrlHyperlinkListener());
this.setContentType("text/html");
}
private class UrlHyperlinkListener implements HyperlinkListener {
#Override
public void hyperlinkUpdate(final HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
Desktop.getDesktop().browse(event.getURL().toURI());
} catch (final IOException e) {
throw new RuntimeException("Can't open URL", e);
} catch (final URISyntaxException e) {
throw new RuntimeException("Can't open URL", e);
}
}
}
};
#Override
/**
* Set the text, first translate it into HTML:
*/
public void setText(final String input) {
final StringBuilder answer = new StringBuilder();
answer.append("<html><body style=\"font-size: 8.5px;font-family: Tahoma, sans-serif\">");
final String content = StringEscapeUtils.escapeHtml(input);
int lastIndex = 0;
final Matcher matcher = urlPattern.matcher(content);
while(matcher.find()) {
//Append everything since last update to the url:
answer.append(content.substring(lastIndex, matcher.start()));
final String url = content.substring(matcher.start(), matcher.end()).trim();
if(UrlUtil.isValidURI(url)) {
answer.append(""+url+"");
} else {
answer.append(url);
}
lastIndex = matcher.end();
}
//Append end:
answer.append(content.substring(lastIndex));
answer.append("</body></html>");
super.setText(answer.toString().replace("\n", "<br />"));
}
}
I wrote a simple function that takes the text, link, and the position you want to display and returns a JLabel. When the mouse is over the text, it becomes blue with underline and makes cursor a pointing hand, otherwise it becomes black with no underline and default cursor.
public static JLabel makeHyperLink(final String s, final String link, int x, int y)
{
final JLabel l = new JLabel(s);
l.addMouseListener(new MouseAdapter()
{
#Override
public void mouseExited(MouseEvent arg0)
{
l.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
l.setText(s);
}
#Override
public void mouseEntered(MouseEvent arg0)
{
l.setCursor(new Cursor(Cursor.HAND_CURSOR));
l.setText(String.format("<HTML><FONT color = \"#000099\"><U>%s</U></FONT></HTML>", s));
}
#Override
public void mouseClicked(MouseEvent arg0)
{
try
{
URI uri = new URI(link);
if (Desktop.isDesktopSupported())
Desktop.getDesktop().browse(uri);
} catch (Exception e)
{
}
}
});
l.setBounds(x, y, s.length()*5, 20);
l.setToolTipText(String.format("go to %s", link));
return l;
}
If any part of code is not clear, contact me;)
Yes possible,
Use HTML
Add one JLabel use HTML as text and add it to Panel
I have been trying with no luck to get a JFormattedTextField to highlight on mouse click. I have been able to get it to work fine while tabbing through fields, however I would like to highlight everything on clicking.
I am only able to highlight on mouse click if I click and hold for about 1.5-2 seconds on the text field; I have no idea why.
I've searched and tried a few fixes including extending the class;
class HFTextField extends JFormattedTextField
{
HFTextField(MaskFormatter formatter)
{
super(formatter);
}
#Override
protected void processFocusEvent(FocusEvent e)
{
super.processFocusEvent(e);
if (e.getID() == FocusEvent.FOCUS_GAINED)
{
this.selectAll();
}
}
}
I am also defining a (rather verbose!) FocusListener which uses SwingUtilities.invokelater;
public static FocusListener CreateHighlightTextFieldFocusListener(final JTextField text_field)
{
FocusListener fl =
new FocusAdapter()
{
public void focusGained(FocusEvent evt)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
text_field.selectAll();
}
});
}
};
return fl;
}
and this is the function that creates formatted text fields;
public static JTextField CreateFormattedTextField(int x, int y, int width, int height,
Method action_method, Method changed_method, Method remove_method,
Method update_method, String mask_formatter, String banned_chars)
{
MaskFormatter formatter = null;
try {
formatter = new MaskFormatter(mask_formatter);
} catch (ParseException e) {
assert(false);
}
if(banned_chars != null)
formatter.setInvalidCharacters(banned_chars);
JTextField text_field = new HFTextField(formatter);
text_field.setBounds(x, y, width, height);
if(action_method != null)
{
text_field.addActionListener(CreateTextFieldActionListener(action_method, text_field));
}
text_field.getDocument().addDocumentListener(
CreateTextFieldDocumentListener(changed_method, remove_method,
update_method, text_field));
text_field.addFocusListener(CreateHighlightTextFieldFocusListener(text_field));
return text_field;
Any help would be greatly appreciated!
maybe you have got problems with EDT,
how method you use for/how you added value to JTextField
works with JTextField, JFormateddTextField, with JComboBox too, and with AutoCompleted funcionalies http://www.java2s.com/Code/Java/Swing-JFC/AutocompleteTextField.htm
private FocusListener focsListener = new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
dumpInfo(e);
}
#Override
public void focusLost(FocusEvent e) {
//dumpInfo(e);
}
private void dumpInfo(FocusEvent e) {
//System.out.println("Source : " + name(e.getComponent()));
//System.out.println("Opposite : " + name(e.getOppositeComponent()));
//System.out.println("Temporary: " + e.isTemporary());
Component c = e.getComponent();
if (c instanceof JFormattedTextField) {
((JFormattedTextField) c).requestFocus();
((JFormattedTextField) c).setText(((JFormattedTextField) c).getText());
((JFormattedTextField) c).selectAll();
} else if (c instanceof JTextField) {
((JTextField) c).requestFocus();
((JTextField) c).setText(((JTextField) c).getText());
((JTextField) c).selectAll();
}
}
private String name(Component c) {
return (c == null) ? null : c.getName();
}
};
Try the following code
yourTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
yourTextField.selectAll();
}
});
}
});
I hate to give a simple answer, but have you tried using the MouseListener interface (or MouseAdapter class)?
Have you tried something like this:
fieldName.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
JTextComponent text = (JTextComponent) e.getSource();
text.selectAll();
}
});
Also, I would not recommend doing this asynchronously.
If you want specialized behavior for a mouse click, then add a MouseAdapter to your JTextFiled, and in the mouseClicked event handler, explicitly alter the background.
basically you can use this code (not sure that for each formatter and input masks), but for Number, Date and String you can use following, with ensure that this JFormattedTextField doesn't implements AutoCompleted
myTextField.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
myTextField.requestFocus();
myTextField.setText(myTextField.getText());
myTextField.selectAll();
}
#Override
public void focusLost(FocusEvent e) {
}
});
sure you can pack that into InvokeLate...