第一:InputVerifier的所有實現其打開驗證對話框()是無效。他們違反了他們的合同,API文檔:
這種方法應該沒有副作用。
與「應該」真正的含義「不得」。副作用的正確位置是shouldYieldFocus。
二:移動副作用(顯示信息對話框)正確地插入shouldYieldFocus不工作,以及...由於bug (THEY call it feature request ;-),這比十年老,in the top 10 RFEs
身爲hack-圍繞一個錯誤,@ dareurdrem的MouseListener的一樣好,因爲任何可行的黑客可以得到:-)
更新
打了一下,有不同的選項來破解周圍的錯誤後,這裏的另一個黑客 - 這是脆性像所有黑客一樣E(並且不生存LAF肘節,具有如果需要動態反覆重新安裝)
對於黑客鼠標行爲的基本方法是將鉤到由UI安裝在聽者:
- 發現,原來
- 實現自定義的監聽器,代表大多數事件直接以原
- 表示按下事件要求首先關注:如果產生代表原始,如果不是什麼都不做
因爲焦點事件可能是異步的,所以最後一個項目符號稍微有點牽扯,所以我們必須調用檢查以便集中。反過來,調用需要發送一個釋放,以防無人反對。
另一個怪癖是爲rootPane的壓制作用(其defaultButton):它不受無條件調用doClick尊重任何inputVerifiers完成。
- 找到的rootPane的壓制作用
- 實現哪些檢查潛在的否決inputVerifier自定義操作:可以掛接到行動,按照相同的模式鉤住的MouseListener被攻破委託給原如果沒有,什麼也不做,否則
沿着這些線路的修改的例子:
public class VerifierTest implements Runnable {
private static final long serialVersionUID = 1L;
@Override
public void run() {
InteractiveTestCase.setLAF("Win");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
JTextField tf = new JTextField("TextField1");
tf.setInputVerifier(new PassVerifier());
frame.add(tf, BorderLayout.NORTH);
final JButton b = new JButton("Button");
frame.add(b);
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked");
}
});
// hook into the mouse listener
replaceBasicButtonListener(b);
frame.add(new JTextField("not validating, something else to focus"),
BorderLayout.SOUTH);
frame.getRootPane().setDefaultButton(b);
// hook into the default button action
Action pressDefault = frame.getRootPane().getActionMap().get("press");
frame.getRootPane().getActionMap().put("press", new DefaultButtonAction(pressDefault));
frame.setVisible(true);
}
protected void replaceBasicButtonListener(AbstractButton b) {
final BasicButtonListener original = getButtonListener(b);
if (original == null) return;
Hacker l = new Hacker(original);
b.removeMouseListener(original);
b.addMouseListener(l);
}
public static class Hacker implements MouseListener {
private BasicButtonListener original;
/**
* @param original the listener to delegate to.
*/
public Hacker(BasicButtonListener original) {
this.original = original;
}
/**
* Hook into the mousePressed: first request focus and
* check its success before handling it.
*/
@Override
public void mousePressed(final MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
if(e.getComponent().contains(e.getX(), e.getY())) {
// check if we can get the focus
e.getComponent().requestFocus();
invokeHandleEvent(e);
return;
}
}
original.mousePressed(e);
}
/**
* Handle the pressed only if we are focusOwner.
*/
protected void handlePressed(final MouseEvent e) {
if (!e.getComponent().hasFocus()) {
// something vetoed the focus transfer
// do nothing
return;
} else {
original.mousePressed(e);
// need a fake released now: the one from the
// original cycle might never has reached us
MouseEvent released = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_RELEASED,
e.getWhen(), e.getModifiers(),
e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger()
);
original.mouseReleased(released);
}
}
/**
* focus requests might be handled
* asynchronously. So wrap the check
* wrap the block into an invokeLater.
*/
protected void invokeHandleEvent(final MouseEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
handlePressed(e);
}
});
}
@Override
public void mouseClicked(MouseEvent e) {
original.mouseClicked(e);
}
@Override
public void mouseReleased(MouseEvent e) {
original.mouseReleased(e);
}
@Override
public void mouseEntered(MouseEvent e) {
original.mouseEntered(e);
}
@Override
public void mouseExited(MouseEvent e) {
original.mouseExited(e);
}
}
public static class DefaultButtonAction extends AbstractAction {
private Action original;
/**
* @param original
*/
public DefaultButtonAction(Action original) {
this.original = original;
}
@Override
public void actionPerformed(ActionEvent e) {
JRootPane root = (JRootPane) e.getSource();
JButton owner = root.getDefaultButton();
if (owner != null && owner.getVerifyInputWhenFocusTarget()) {
Component c = KeyboardFocusManager
.getCurrentKeyboardFocusManager()
.getFocusOwner();
if (c instanceof JComponent && ((JComponent) c).getInputVerifier() != null) {
if (!((JComponent) c).getInputVerifier().shouldYieldFocus((JComponent) c)) return;
}
}
original.actionPerformed(e);
}
}
/**
* Returns the ButtonListener for the passed in Button, or null if one
* could not be found.
*/
private BasicButtonListener getButtonListener(AbstractButton b) {
MouseMotionListener[] listeners = b.getMouseMotionListeners();
if (listeners != null) {
for (MouseMotionListener listener : listeners) {
if (listener instanceof BasicButtonListener) {
return (BasicButtonListener) listener;
}
}
}
return null;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new VerifierTest());
}
public static class PassVerifier extends InputVerifier {
/**
* Decide whether or not the input is valid without
* side-effects.
*/
@Override
public boolean verify(JComponent input) {
final JTextField tf = (JTextField) input;
String pass = tf.getText();
if (pass.equals("Manish"))
return true;
return false;
}
/**
* Implemented to ask the user what to do if the input isn't valid.
* Note: not necessarily the best usability, it's mainly to
* demonstrate the different effects on not/agreeing with
* yielding focus transfer.
*/
@Override
public boolean shouldYieldFocus(final JComponent input) {
boolean valid = super.shouldYieldFocus(input);
if (!valid) {
String message = "illegal value: " + ((JTextField) input).getText();
int goAnyWay = JOptionPane.showConfirmDialog(input, "invalid value: " +
message + " - go ahead anyway?");
valid = goAnyWay == JOptionPane.OK_OPTION;
}
return valid;
}
}
}
請嘗試將showMessageDialog調用包裝到Runnable中,並將它提供給SwingUtilities :: invokeLater(Runnable) – gd1
@ gd14嗨,我試過了你陳述的方法,但它似乎不起作用。修改後的代碼如下: - final String message =「illegal value:」+ tf.getText(); \t javax.swing.SwingUtilities.invokeLater(新的Runnable(){ \t \t公共無效的run(){ \t \t \t JOptionPane.showMessageDialog(空,消息, \t \t \t \t \t 「非法值」,JOptionPane.ERROR_MESSAGE ); \t \t} \t}); \t return false; – dareurdream
我明白了。什麼是您的操作系統和Java版本?我在OSX上使用Java 1.6,它工作得很好。 – gd1