问题
I have JFrame
with 3 JPanel
(basically three tabs). one of the panel has a textbox. there is value restriction on textbox. it means, user can enter only 1-1000 number in it. If he enters number >1000, it throws the warning message.
Now I am using focuslistener to save the entered number as soon as it looses the focus. But if the user enters 1200 and click on another tab(panel), it gives me expected warning message but also goes to the another tab. I need to remain in same panel if there is warning box. I don't want to loose the focus from the current panel.
mMaxLabelLength = new JTextField();
mMaxLabelLength.addActionListener(this);
public void focusGained(FocusEvent fe)
{
// do NOTHING
}
@Override
public void focusLost(FocusEvent fe)
{
saveActions();
}
public void actionPerformed(ActionEvent e)
{
//Do something
}
private void saveActions()
{
// error message
JOptionPane.showMessageDialog(this,
"Please enter an integer value between 1 and 1000.",
"Invalid Entry", JOptionPane.INFORMATION_MESSAGE);
SwiftApplication APP = SwiftApplication.getInstance();
int nMaxLabel = APP.getMaxPieLabel();
mMaxLabelLength.setText(new Integer(nMaxLabel).toString());
mMaxLabelLength.requestFocus();
}
回答1:
The code block in the question does not offer too many details, but as far as I understand it, you need to use a VetoableChangeListener
to prohibit focus change.
Here an example from Java2s:
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
public class Main {
public static void main(String[] argv) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addVetoableChangeListener(
new FocusVetoableChangeListener());
}
}
class FocusVetoableChangeListener implements VetoableChangeListener {
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
Component oldComp = (Component) evt.getOldValue();
Component newComp = (Component) evt.getNewValue();
if ("focusOwner".equals(evt.getPropertyName())) {
if (oldComp == null) {
System.out.println(newComp.getName());
} else {
System.out.println(oldComp.getName());
}
} else if ("focusedWindow".equals(evt.getPropertyName())) {
if (oldComp == null) {
System.out.println(newComp.getName());
} else {
System.out.println(oldComp.getName());
}
}
boolean vetoFocusChange = false;
if (vetoFocusChange) {
throw new PropertyVetoException("message", evt);
}
}
}
But, the more I think about it, maybe using InputVerifier
and public boolean shouldYieldFocus(JComponent input) is more appropriate. See "Validating Input" in the "How to Use the Focus Subsystem" of the Java Tutorial.
回答2:
Looks like you are looking for an InputVerifier.
Abstract class that allows input validation via the focus mechanism. When an attempt is made to shift the focus from a component containing an input verifier, the focus is not relinquished until the verifier is satisfied.
As the oracle page describes, it can be used to write own verifiers, which reject invalid inputs and keeps the focus meanwhile on the associated JComponent
.
Therefore you just need to do two things:
- Write your own
InputVerifier
, e.g.MyVerifier
or take one of the already existing ones and create an instance of it. (See below for a small complete verifiable example) - Register your verifier instance on the target
JComponent
using calls to the Input Verification API.
This means, to register an...
InputVerifier
call thesetInputVerifier
method of theJComponent
class. For example, theInputVerificationDemo
has the following code:
private MyVerifier verifier = new MyVerifier();
...
amountField.setInputVerifier(verifier);
Note For some reason I can't find a source for the java8 InputVerifier right now, it seems that the link is broken.
Small Verifiable Complete Example (from here)
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
// This program demonstrates the use of the Swing InputVerifier class.
// It creates two text fields; the first of the text fields expects the
// string "pass" as input, and will allow focus to advance out of it
// only after that string is typed in by the user.
public class VerifierTest extends JFrame {
public VerifierTest() {
JTextField tf1 = new JTextField ("Type \"pass\" here");
getContentPane().add (tf1, BorderLayout.NORTH);
tf1.setInputVerifier(new PassVerifier());
JTextField tf2 = new JTextField ("TextField2");
getContentPane().add (tf2, BorderLayout.SOUTH);
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(l);
}
class PassVerifier extends InputVerifier {
public boolean verify(JComponent input) {
JTextField tf = (JTextField) input;
return "pass".equals(tf.getText());
}
}
public static void main(String[] args) {
Frame f = new VerifierTest();
f.pack();
f.setVisible(true);
}
}
来源:https://stackoverflow.com/questions/34726674/java-restrict-switching-of-window-jpanel