在Java/Swing中,有没有一种方法可以合法地“尝试在通知中进行变异”?

发布于 2024-09-16 16:11:08 字数 2147 浏览 6 评论 0原文

我想知道是否有某种魔法可以用来绕过 IllegalStateException 并允许 JTextField “尝试在通知中发生变化”,或者换句话说,如果触发其侦听器,则设置自己的文本。

供您参考,我正在尝试编写一个自动完成函数,该函数返回 12 个枚举范围内最有可能的匹配项,以响应用户在 JTextField 中的输入。

这是代码示例。您必须原谅我笨拙的算法,它会产生枚举结果。我用注释突出显示了产生异常的代码:

jtfElement1.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {                    
                String s = jtfElement1.getText();
                int[] attributes = new int[13];
                // iterate through each enum
                for (BaseEnumAttributes b: BaseEnumAttributes.values()) {
                    // iterate through the length of the current text in jtfElement1
                    for (int i = 0; i < s.length(); i++) {
                        if (s.length() <= b.toString().length()) {                                
                            if (b.toString().charAt(i) == s.charAt(i)) {
                                // increase the number of "hits" noted for that enum
                                attributes[b.ordinal()] = attributes[b.ordinal()] + 1;
                            }                                
                        }
                    }                        
                }
                int priorC = 0;
                int rightC = 0;                    
                // iterate through the "array" of enums to find the highest score
                for (int j = 0; j < attributes.length; j++) {
                    if (attributes[j] > priorC) {
                        priorC = attributes[j];
                        rightC = j;
                    }
                }                    
                if (!s.equals("")) {
                    // assign to b the Enum corresponding to the "array" with highest score
                    BaseEnumAttributes b = BaseEnumAttributes.values()[rightC];
                    iController.updateInputElement1String(b.toString());                        
                    // THIS TRIGGERS EXCEPTION 
                    jtfElement1.setText(b.toString());
                }

            }
        });

I was wondering if there is some sort of magic I can use to get around an IllegalStateException and allow a JTextField to "attempt to mutate in notification", or in other words to set its own text if its listener is triggered.

For your information, I am trying to program an auto-complete function which returns the most likely match in a range of 12 enums in response to a user's input in the JTextField.

Here is the code sample. You'll have to pardon my clumsy algorithm which creaks out enum results. I've highlighted the code which produces the exception with a comment:

jtfElement1.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {                    
                String s = jtfElement1.getText();
                int[] attributes = new int[13];
                // iterate through each enum
                for (BaseEnumAttributes b: BaseEnumAttributes.values()) {
                    // iterate through the length of the current text in jtfElement1
                    for (int i = 0; i < s.length(); i++) {
                        if (s.length() <= b.toString().length()) {                                
                            if (b.toString().charAt(i) == s.charAt(i)) {
                                // increase the number of "hits" noted for that enum
                                attributes[b.ordinal()] = attributes[b.ordinal()] + 1;
                            }                                
                        }
                    }                        
                }
                int priorC = 0;
                int rightC = 0;                    
                // iterate through the "array" of enums to find the highest score
                for (int j = 0; j < attributes.length; j++) {
                    if (attributes[j] > priorC) {
                        priorC = attributes[j];
                        rightC = j;
                    }
                }                    
                if (!s.equals("")) {
                    // assign to b the Enum corresponding to the "array" with highest score
                    BaseEnumAttributes b = BaseEnumAttributes.values()[rightC];
                    iController.updateInputElement1String(b.toString());                        
                    // THIS TRIGGERS EXCEPTION 
                    jtfElement1.setText(b.toString());
                }

            }
        });

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

酷炫老祖宗 2024-09-23 16:11:08

您最好使用文档过滤器或自定义文档。

如果文档在事件分派期间不保持不变,其他侦听器期望看到什么?

You are probably better off using a document filter or a custom document.

What are other listeners expected to see if the document doesn't stay the same during event dispatch?

人心善变 2024-09-23 16:11:08

使用 SwingUtilities.invokeLater() 将所有修改放在那里

Use SwingUtilities.invokeLater() placing all the modifications there

浅听莫相离 2024-09-23 16:11:08

也许您可以在 caretUpdate() 终止后使用线程来延迟 setText() 运行。

Maybe you can delay the setText() with a Thread to run after caretUpdate() has terminated.

看轻我的陪伴 2024-09-23 16:11:08

我发现了同样的问题,但我找到了一个简单的解决方案:

当您将文本设置为 jTextField 时,通过布尔值 if(false) 锁定 caretUpdate() ,然后解锁它。 。像这样的东西:

布尔插入符= true;

私有无效 listValueChanged(javax.swing.event.ListSelectionEvent evt) {
插入符号=假;
name.setText((String)list.getSelectedValue());
插入符号=真;
}

private void nameCaretUpdate(javax.swing.event.CaretEvent evt) {
   if(caret){
    model = new DefaultListModel();
    this.fillList(name.getText());
    list.setModel(model);
    }
}

i'm found on the same problem but i found an easy solution:

lock the caretUpdate() by a boolean if(false) while u'r setting the text to the jTextField than unlock it after . . something like this:

boolean caret = true;

private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {
caret = false;
name.setText((String)list.getSelectedValue());
caret = true;
}

private void nameCaretUpdate(javax.swing.event.CaretEvent evt) {
   if(caret){
    model = new DefaultListModel();
    this.fillList(name.getText());
    list.setModel(model);
    }
}
天涯离梦残月幽梦 2024-09-23 16:11:08

创建自定义文档并覆盖 insertString()

filenameText = new JTextField(new FilenameDocument(), "", 0);

...

 /**
 * document which adds .xml extension if not specified
 *
 */
private class FilenameDocument extends PlainDocument {

    @Override
    public void insertString(int offset, String insertedText, AttributeSet set)
    throws BadLocationException {
        if (offset == 0) {
        insertedText = insertedText.trim( );
        }
        super.insertString(offset, insertedText, set);
        if (filenameText != null) {
            final int caretPos = filenameText.getCaretPosition();
            String text = filenameText.getText().trim();
            if (text.indexOf('.') == -1) {
                filenameText.setText(text + ".xml");
                filenameText.setCaretPosition(caretPos);
            }

        }
    }
}

请注意,调用 setText 将导致递归调用 insertString(),因此请确保有停止条件。

Create a custom Document and override insertString( )

filenameText = new JTextField(new FilenameDocument(), "", 0);

...

 /**
 * document which adds .xml extension if not specified
 *
 */
private class FilenameDocument extends PlainDocument {

    @Override
    public void insertString(int offset, String insertedText, AttributeSet set)
    throws BadLocationException {
        if (offset == 0) {
        insertedText = insertedText.trim( );
        }
        super.insertString(offset, insertedText, set);
        if (filenameText != null) {
            final int caretPos = filenameText.getCaretPosition();
            String text = filenameText.getText().trim();
            if (text.indexOf('.') == -1) {
                filenameText.setText(text + ".xml");
                filenameText.setCaretPosition(caretPos);
            }

        }
    }
}

Note that calling setText will result in a recursive call to insertString( ), so make sure you have a stopping condition.

月亮是我掰弯的 2024-09-23 16:11:08

我很惊讶没有人回答这个问题,但是您最好实现一个可编辑的 JSpinnerSpinnerListModel

I'm surprised no one has answered this, but would'nt you have been better off implementing an editable JSpinner with a SpinnerListModel?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文