防止Jcombobox弹出窗口出现。通过输入器
给定以下方案:
- 一个具有JCombobox,而JTEXTFIELD
- 则具有输入器提供自己的错误消息。
- TextField是当前的焦点所有者,其输入不满足输入器(此处:少于3个字符)。
- 现在,您单击组合,该组合将启动输入器。
- 输入器依次将显示其错误消息。
- 您确认错误消息,瞧瞧,出现了组合的弹出窗口,准备接受选择。
对我来说,这是一种不希望的行为,我宁愿没有其他 组件更改其输入,直到满足输入器为止。务实 在描述的情况下,Jcombobox可以拥有自己的动作列表 在新选择的情况下改变整个情况。
以下代码通过应用PopupMenulistener来解决此问题, 检查验证者告诉其状态的布尔值,然后决定是否 是否显示弹出窗口。
我现在想做的是编写一个扩展的Jcombobox类,该类实现此功能并接受各种(扩展的)输入器。但是我 我已经在我的测试代码中陷入困境,因为我看不到一种方法 PopupMenulistener以一般方式访问验证者的“布尔值”。 仅通过一个输入器作为参数以后需要施放, 取消一般性。 - 还是有任何“变量”铸件?
欢迎任何想法,即使这是针对初始问题的完全不同的方法。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
public class DisableComboPopupByVerifier extends JFrame {
public static final long serialVersionUID = 100L;
JComboBox<String> cmb;
public DisableComboPopupByVerifier() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(450, 240);
setLocationRelativeTo(null);
setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
cmb= new JComboBox<>(new String[]{"AA", "BB", "CC"});
cmb.setPreferredSize(new Dimension(43, 20));
MyMinLenVerifier verifier= new MyMinLenVerifier(this, 3);
MyPopupListener popupListener= new MyPopupListener(verifier);
cmb.addPopupMenuListener(popupListener);
add(cmb);
JTextField tf1= new JTextField(5);
tf1.setInputVerifier(verifier);
add(tf1);
JTextField tf2= new JTextField(5);
tf2.setInputVerifier(verifier);
add(tf2);
SwingUtilities.invokeLater(() -> tf1.requestFocusInWindow());
setVisible(true);
}
static public void main(String args[]) {
EventQueue.invokeLater(DisableComboPopupByVerifier::new);
}
class MyMinLenVerifier extends InputVerifier {
boolean satisfied;
int minlen;
Component parent;
public MyMinLenVerifier(Component parent, int minlen) {
this.minlen= minlen;
this.parent= parent;
}
public boolean verify(JComponent input) {
String s= ((JTextField)input).getText();
if (s.length()>=minlen) {
satisfied= true;
}
else {
satisfied= false;
JOptionPane.showMessageDialog(parent,
"Enter at least "+minlen+" characters.",
"Error", JOptionPane.ERROR_MESSAGE);
}
return satisfied;
}
}
class MyPopupListener implements PopupMenuListener {
//** To accept all kinds of verifiers the specific one here needs to be replaced
by the super class InputVerifier, which, however, makes casting necessary to access the boolean 'satisfied' below.
**//
MyMinLenVerifier verifier;
public MyPopupListener(MyMinLenVerifier verifier) {
this.verifier= verifier;
}
public void popupMenuCanceled(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//** boolean 'satisfied' is a requirement in all passed verifiers. **//
if (!verifier.satisfied) {
BasicComboPopup popup= (BasicComboPopup)cmb.getUI()
.getAccessibleChild(cmb, 0);
SwingUtilities.invokeLater(() -> {
popup.setVisible(false);
// This restauration of the button background is not reliable!
MetalComboBoxButton btn= (MetalComboBoxButton)cmb.getComponent(0);
btn.getModel().setPressed(false);
btn.repaint();
((JComboBox)e.getSource()).repaint();
});
}
}
}
}
Given the following scenario:
- one has a JComboBox and a JTextField
- the latter has an InputVerifier providing its own error message.
- the textField is the current focus owner and its input does not satisfy the inputVerifier (Here: Less than 3 characters).
- Now you click on the combo, which will fire the InputVerifier.
- The InputVerifier in turn will show its error message.
- You acknowledge the error message and, lo and behold, the combo's popup appears, ready to accept a selection.
To me this is an undesired behaviour, and I would prefer to have no other
component change its input until the inputVerifier is satisfied. Paticularly
in the described scenario the JComboBox could have its own ActionListener
changing the whole situation in case of a new selection.
The following code solves this problem by applying a PopupMenuListener, which
checks a boolean in the verifier telling its state, and then decides whether to
show the popup or not.
What I would like to do now is to write an extended JComboBox class implementing this functionality and accepting all kinds of (extended) InputVerifiers. But I
am already stuck in my test code here, for I don't see a way how to give the
PopupMenuListener access to the verifers' boolean 'satisfied' in a general way.
Passing just an InputVerifier as parameter would need casting later, which
unmakes the generality. - Or is there any "variable" casting?
Any idea is welcome, even if it is a completely different approach to the initial problem.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
public class DisableComboPopupByVerifier extends JFrame {
public static final long serialVersionUID = 100L;
JComboBox<String> cmb;
public DisableComboPopupByVerifier() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(450, 240);
setLocationRelativeTo(null);
setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
cmb= new JComboBox<>(new String[]{"AA", "BB", "CC"});
cmb.setPreferredSize(new Dimension(43, 20));
MyMinLenVerifier verifier= new MyMinLenVerifier(this, 3);
MyPopupListener popupListener= new MyPopupListener(verifier);
cmb.addPopupMenuListener(popupListener);
add(cmb);
JTextField tf1= new JTextField(5);
tf1.setInputVerifier(verifier);
add(tf1);
JTextField tf2= new JTextField(5);
tf2.setInputVerifier(verifier);
add(tf2);
SwingUtilities.invokeLater(() -> tf1.requestFocusInWindow());
setVisible(true);
}
static public void main(String args[]) {
EventQueue.invokeLater(DisableComboPopupByVerifier::new);
}
class MyMinLenVerifier extends InputVerifier {
boolean satisfied;
int minlen;
Component parent;
public MyMinLenVerifier(Component parent, int minlen) {
this.minlen= minlen;
this.parent= parent;
}
public boolean verify(JComponent input) {
String s= ((JTextField)input).getText();
if (s.length()>=minlen) {
satisfied= true;
}
else {
satisfied= false;
JOptionPane.showMessageDialog(parent,
"Enter at least "+minlen+" characters.",
"Error", JOptionPane.ERROR_MESSAGE);
}
return satisfied;
}
}
class MyPopupListener implements PopupMenuListener {
//** To accept all kinds of verifiers the specific one here needs to be replaced
by the super class InputVerifier, which, however, makes casting necessary to access the boolean 'satisfied' below.
**//
MyMinLenVerifier verifier;
public MyPopupListener(MyMinLenVerifier verifier) {
this.verifier= verifier;
}
public void popupMenuCanceled(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//** boolean 'satisfied' is a requirement in all passed verifiers. **//
if (!verifier.satisfied) {
BasicComboPopup popup= (BasicComboPopup)cmb.getUI()
.getAccessibleChild(cmb, 0);
SwingUtilities.invokeLater(() -> {
popup.setVisible(false);
// This restauration of the button background is not reliable!
MetalComboBoxButton btn= (MetalComboBoxButton)cmb.getComponent(0);
btn.getModel().setPressed(false);
btn.repaint();
((JComboBox)e.getSource()).repaint();
});
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于缺乏更好的主意,所以我在myminlenverifier
和mypopuplistener class中覆盖了ToString(),现在看起来像这样:
For lack of a better idea I overrode toString() in MyMinLenVerifier
And the MyPopupListener class looks now like this: