当前位置: 首页 > 知识库问答 >
问题:

防止出现JComboBox弹出窗口。传递输入验证器

薄哲
2023-03-14

给定以下方案:

  • 一个有一个JComboBox和一个JTextField
  • 后者有一个InputVerifier提供自己的错误消息。
  • text Field是当前焦点所有者,其输入不满足inputVerifier(此处:小于3个字符)。
  • 现在您单击组合,它将触发InputVerifier。
  • InputVerifier反过来将显示其错误消息。
  • 您确认错误消息,瞧,组合的弹出窗口出现,准备接受选择。

对我来说,这是一种不需要的行为,我宁愿在满足输入Verifier之前没有其他组件更改其输入。在所描述的场景中,JComboBox可以有自己的ActionListener,以便在有新选择的情况下改变整个情况。

下面的代码通过应用PopupMenuListener解决了这个问题,它检查验证器中的一个告诉它状态的布尔值,然后决定是否显示弹出窗口。

我现在想做的是编写一个扩展的JComboBox类,实现这个功能并接受各种(扩展的)输入验证器。但我已经陷入了测试html" target="_blank">代码中,因为我看不到一种方法可以让PopupMenuListener访问verifers的布尔值“满足”。仅将InputVerifier作为参数传递需要稍后进行转换,这将破坏通用性。-或者是否存在“可变”铸造?

任何想法都是受欢迎的,即使它是解决初始问题的完全不同的方法。

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();
        });
      }
    }
  }

}

共有1个答案

杜曜灿
2023-03-14

由于没有更好的主意,我在MyMinLenVerifier中重写了toString()

    @Override
    public String toString() {
      return "satisfied:"+satisfied;
    }

MyPopupListener类现在看起来像这样:

  class MyPopupListener implements PopupMenuListener {
    InputVerifier verifier;

    public MyPopupListener(InputVerifier verifier) {
      this.verifier= verifier;
    }

.
.
.
    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
      if (verifier.toString().endsWith("false")) {
...
 类似资料:
  • 我有一个蓝牙条形码扫描仪附在Android平板电脑上。硬件键盘在Android设置中被禁用。这让我既可以扫描条形码,又可以使用软键盘打字。 当我扫描条形码时,我的活动按预期捕获所有键。但是软键盘出现了。 但什么都没起作用。当应用程序按下硬件键时,软键盘就会出现。

  • 问题内容: 基本上是弹出用于JComboBox中显示其衍生的JTextField下面,如何从怒吼取向为JcomboBox的弹出改变方向并在顶/显示JcomboBox的弹出超过该 编辑:基本JComboBox的代码示例 编辑第二。MacOX的代码 问题答案: 尝试在“ 组合框弹出”中找到的setPopupAbove()方法。

  • 当我从Eclipse(selenium)启动网站时,会弹出一个身份验证框,如下所示: 这里我无法输入用户名和密码,以下是我尝试过的: 1)将句柄切换到弹出窗口并识别Xpath 2)在URL中发送用户名和密码(如何使用Selenium WebDriver处理登录弹出窗口?) 3)Sikuli(但在不同系统中执行时需要图像捕获) 4)使用机器人功能 到目前为止,上述操作都不起作用,只是在到达网站(dr

  • 请看下面的脸书评论模态框。我试图实现一个类似的效果,即用户点击一个按钮,然后它会打开一个弹出/模态框。此框将允许在新框中滚动(因为它可能是许多页的文本),但不允许在主页上的模态之外滚动。当模态允许在模态窗口内滚动而不允许在其他地方滚动时,如何实现类似的效果?谢谢。

  • 问题内容: 我想使用Firefox浏览器,使用RSelenium从网站下载文件。我正确地完成了所有操作(导航,选择正确的元素并写下我想要的内容);现在,我单击“下载”按钮,然后打开一个Firefox弹出窗口,并询问我是否要下载文件或“用…打开”。 不幸的是,由于隐私限制,我无法编写示例。 我的问题是:如何在需要时切换到弹出窗口/警报并单击“确定”? 我尝试了以下方法,但均未成功: 我也试过了 但是

  • Popup 是一种可以包含任何Html内容的弹出窗口,从App的主内容区域上弹出。 Popup 和其他所有的遮罩图层一样,是所谓的“临时视图”的一部分。 Popup 布局 Popup 布局相当简单. 你所需要做的就是将放到 body 里正确的位置上: <div class="modal modal-no-buttons"> ... <div class="popup"> An