I have a public class JdbDateTextField extends JTextField and in the constructor I add this.setInputVerifier(new ValidDateOrEmptyVerifier());.
I use class ValidDateOrEmptyVerifier extends InputVerifier to verify the format of the input.
If the input is in the wrong format and the user looses the focus of the JdbDateTextField, I return false in the ValidDateOrEmptyVerifier and the focus is gained again to the JdbDateTextField again.
This works if the user switches from the JdbDateTextField to another textField or presses a Button. If pressing a button and the format of the input in the is wrong then no action for the button is performed and the focus is still at the JdbDateTextField.
This is exactly what I want. The user can not leave the JdbDateTextField until he enters a valid string.
The problem is that the JdbDateTextField is in a JPanel which is in a JTabbedPane so I have a GUI with several tabs.
If I have the JdbDateTextField selected, enter a invalid input and then directly click on another tab it still switches the tab. So I was able to provide a wrong input.
My Question is:
Is there a way to perform an Input Verification which does not allow to execute any other event before it is true
The best solution I can think of is to assign the JTabbedPane a custom selection model which refuses to allow changing tabs unless the current InputVerifier succeeds:
int index = tabbedPane.getSelectedIndex();
tabbedPane.setModel(new DefaultSingleSelectionModel() {
#Override
public void setSelectedIndex(int index) {
Component focusOwner =
FocusManager.getCurrentManager().getFocusOwner();
if (focusOwner instanceof JComponent) {
JComponent c = (JComponent) focusOwner;
InputVerifier verifier = c.getInputVerifier();
if (verifier != null && !verifier.shouldYieldFocus(c)) {
return;
}
}
super.setSelectedIndex(index);
}
});
tabbedPane.setSelectedIndex(index);
I hope that I can do this as an answer:
The solution above works for the JTabbedPane
But I can still select other GUI elements.
My Application is build like this:
For every Person ID I show other Birthdate values in the JTabbedPane
and I can still switch to another Person ID if the ValidDateOrEmptyVerifier returns false.
So is there a way to disallow all events in the Main Frame until the ValidDateOrEmptyVerifier returns true.
So Basically what I want is that the user can only exit the "Birthdate" JdbDateTextField if he enters a valid Date or the field is empty.
Related
I would like to know the best way to approach what I am trying to achieve, I can't figure out the logical path I should take.
I have a JTextField and a JTextButton, when input is added to the JTextField and either enter or the button is pressed, it will display on the JTextArea. Now, what I want is to choose when and what the JTextArea and Button do.
For example I want default Enter & Button to display next append text in my code. Then when a case is presented I want the JTextField to only accept either int or string and then once completed, I want it to go back to default.
I don't know if what I am trying to do is logical or best practice...
The idea behind this is, I have a story text based gui game. I want it to display text to the JTextArea and when Enter or button is pressed to display the next line of text and when in the story it requires user input, the JTextArea will look for that input.
So far I have an EventListener and ActionListener which submits what I type from JTextField to JTextArea, but that is about it.
Thanks for your assistance! I have solved my issue, not sure if this is the "Best Solution". I combined your solution with a bit of tweaking.
In this instance, buttonState is an int which can be changed throughout my code by calling a constructor "setButtonState". I could have made buttonState a static to make things easier, but thought I could keep things clean.
enterButton.addActionListener(new ActionListener()
{ //This is used so when the enter screen button is pressed, it will submit text from text field to text area.
public void actionPerformed(ActionEvent e) {
String text = inputTextField.getText();
InputTextFieldEvent event = new InputTextFieldEvent(this, text);
if (buttonState == 0) //Displays all text in JTextField to JTextArea, mostly for testing purposes.
{
if (textInputListener != null) {
textInputListener.setInputListenerOccurred(event);
}
}
if (buttonState == 1) //Only accepts string for answer
{
if (inputTextField.getText().matches("[a-zA-Z]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only letters are allowed.");
}
}
if (buttonState == 2) //Only accepts int for answer
{
if (inputTextField.getText().matches("[0-9]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only numbers are allowed.");
}
}
}
});
Ok, I'm new to listeners (still learning the language), and this is my first full-scale attempt to implement them (ie more than just a practice problem in a textbook).
So far, everything is working fine except one big bug: the checkboxes don't stay checked. The ItemListener I assign them runs perfectly (I have a JOptionPane set up to trigger to let me know if it's working or not), but the box itself doesn't stay checked.
I went even further and added conditional logic for if it's state is checked versus unchecked, and found that when I click the box BOTH states get triggered. So I get both JOptionPane popups, the one with the message for if the box is checked and the one for if the box isn't checked.
I'm including my code here. What am I doing wrong?
PS. You'll notice that the code has conditional logic to either add a radio button or a checkbox. When the program finally runs, this component is generated in multiple locations in both formats. The radio button works fine, it's the checkbox ones that I'm having the above issue with.
CODE THAT CREATES THE CHECKBOXES AND ASSIGNS THE LISTENERS:
public OtherField(int voteFor){
this.voteFor = voteFor;
otherPanel = new JPanel();
otherPanel.setLayout(new GridLayout(1, 3));
otherField = new JTextField(10);
otherField.setHorizontalAlignment(SwingConstants.CENTER);
JLabel otherLabel;
otherLabel = new JLabel("Other", SwingConstants.CENTER);
otherRadio = new JRadioButton("", false);
otherRadio.setHorizontalAlignment(SwingConstants.CENTER);
otherRadio.addActionListener(new OtherFieldRadioListener());
otherCheckBox = new JCheckBox("");
otherCheckBox.setHorizontalAlignment(SwingConstants.CENTER);
otherCheckBox.addItemListener(new OtherFieldCheckBoxListener());
otherPanel.add(otherLabel);
otherPanel.add(otherField);
if(voteFor == 1){
otherPanel.add(otherRadio);
}else{
otherPanel.add(otherCheckBox);
}
}
LISTENER CODE (it's a private class in the same class as the code above):
private class OtherFieldCheckBoxListener implements ItemListener{
public void itemStateChanged(ItemEvent e){
String name = otherField.getText();
if(e.getStateChange() == ItemEvent.SELECTED){
JOptionPane.showMessageDialog(null, name);
}else{
JOptionPane.showMessageDialog(null, "Not Selected");
}
}
}
First thing I would try is to set the checkbox either to true or false when you initialize it, i.e
otherCheckBox.setSelected(false)
If this does not work I would check whether OtherField gets called from somewhere else everytime the checkbox is selected and thus the components are redrawn/ the selection is reset (use the debugger and set a breakpoint at the beginning of OtherFields)
so I have this part of my code (I cannot post everything because it's just too long and so far this is the only problem with it). Our professor assigned us to make our own Assembler just like MARIE and we are having a trouble with these lines of code:
else if(get.charAt(0)=='B')//input
{
inputfield.setEditable(true);
//INSERT LISTENER HERE!
AC.setText(inputfield.getText());
System.out.println(""+col);
//insert action here - HALP
}
The entire thing gets a value from a table sort of like an Instruction in Hex and if the Intruction starts with B like B000 then it will toggle the input textbox which is named inputfield. It works fine but we need to add a key listener in the part where it says //INSERT LISTENER HERE! for when the user will press enter the AC.setText(inputfield.getText()); will be executed. How should we do it? I mean we tried actionListener but it sort of stops the loop unless another button is clicked. We need another way that when the user presses enter it automatically resumes the execution.
Thank you.
Add action listener to textfield. ActionEvent will occur when you press Enter while editing in textfield.
JTextField field = new JTextField();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// action to perform when one hits "Enter"
}
});
I am looking for a way to put example text into a swing JTextField and have it grayed out. The example text should then disappear as soon as any thing is entered into that text field. Some what similar to what stackoverflow does when a user is posting a question with the title field.
I would like it if it was already a extended implementation of JTextField so that I can just drop it in as a simple replacement. Anything from swingx would work. I guess if there is not an easy way to do this my option will probably be to override the paint method of JTextField do something that way maybe.
Thanks
The Text Prompt class provides the required functionality without using a custom JTextField.
It allows you to specify a prompt that is displayed when the text field is empty. As soon as you type text the prompt is removed.
The prompt is actually a JLabel so you can customize the font, style, colour, transparency etc..:
JTextField tf7 = new JTextField(10);
TextPrompt tp7 = new TextPrompt("First Name", tf7);
tp7.setForeground( Color.RED );
Some examples of customizing the look of the prompt:
If you can use external librairies, the Swing components from Jide software have what you are looking for; it's called LabeledTextField (javadoc) and it's part of the JIDE Common Layer (Open Source Project) - which is free. It's doing what mklhmnn suggested.
How about initialize the text field with default text and give it a focus listener such that when focus is gained, if the text .equals the default text, call selectAll() on the JTextField.
Rather than overriding, put a value in the field and add a KeyListener that would remove the value when a key stroke is registered. Maybe also have it change the foreground.
You could wrap this up into your own custom JTextField class that would take the default text in a constructor.
private JLabel l;
JPromptTextField(String prompt) {
l = new JLabel(prompt, SwingConstants.CENTER);
l.setForeground(Color.GRAY);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.getText().length() == 0) {
// Reshape the label if needed, then paint
final Rectangle mine = this.getBounds();
final Rectangle its = l.getBounds();
boolean resized = (mine.width != its.width) || (mine.height != its.height);
boolean moved = (mine.x != its.x) || (mine.y != its.y);
if (resized || moved)
l.setBounds(mine);
l.paint(g);
}
}
You can't do that with a plain text field, but you can put a disabled JLabel on top of the JTextField and hide it if the text field gets the focus.
Do it like this:
Define the string with the initial text you like and set up your TextField:
String initialText = "Enter your initial text here";
jTextField1.setText(initialText);
Add a Focus Listener to your TextField, which selects the entire contents of the TextField if it still has the initial value. Anything you may type in will replace the entire contents, since it is selected.
jTextField1.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
if (jTextField1.getText().equals(initialText)) {
jTextField1.selectAll();
}
}
});
I have a JTextField represents a day in a week, such as "Friday", when I click on it, I want to have a choice such as "1st of month, 3rd of month or last of month", so I came up with two options :
<1> Hold down a number or letter, let's say "2" or "L", then click on "Friday" means 2nd (or last) Friday of the month, in this case, how to get the number while mouse clicks on the JTextField ?
<2> Right mouse click on the "Friday" JTextField, drop down a menu, with either buttons or checkboxes that let me choose, then close the menu and get the value.
My code look like this so far :
private final JTextField[] dayHeadings=new JTextField[]{new JTextField("Su"),
new JTextField("Mo"),
new JTextField("Tu"),
new JTextField("We"),
new JTextField("Th"),
new JTextField("Fr"),
new JTextField("Sa")};
......
for (int ii=0; ii < dayHeadings.length; ii++)
{
dayHeadings[ii].setEditable(false);
dayHeadings[ii].setFocusable(false);
dayHeadings[ii].addMouseListener(new MouseAdapter() { public void mouseClicked(final MouseEvent evt) { onHeadingClicked(evt); } });
add(dayHeadings[ii],new AbsoluteConstraints(x,38,X_Cell_Size+1,Y_Cell_Size+1));
}
......
void onHeadingClicked(final java.awt.event.MouseEvent evt)
{
final javax.swing.JTextField fld=(javax.swing.JTextField) evt.getSource();
...
}
How to do either of the above, are they doable in Java ?
getModifiers is actually that what I needed. a sample for the modifiers can be found
here
Option 1:
There is no way to do this in one step. You would need to add a KeyListner to track whenever a key is pressed and then save the character value. Then you would need to add a MouseListener to listener for mousePressed events. When the mousePressed event fires you would need to to check which character is saved and then do your processing. Therefore your listener would to implement both the KeyListener and MouseListener interfaces.
Option 2:
You need to add a mouse listener and listen for a right mouse click, then display a popup menu.
I think option 2 is more intuitive and more easily done. Its always easier to work with one hand then be forced to use two hands.
Another, lazier way to do it would be using getModifiers() on the mouseclick event. It shows which modifier keys (ctrl, alt, shift, etc), if any, were pressed during the mouse click. Using these buttons isn't as intuitive as a drop down menu or numbers in my opinion, but could work.
Read more here