JTextField 中的预定义文本不可编辑但可以附加其他文本?

san*_*eda 7 java swing jtextfield

在经历 Java Swing 时,我遇到了这个问题。我有一个 JTextField,它具有预定义且不可编辑的文本。用户应该能够向其附加其他文本,但无需编辑预定义的文本。是否有任何方法可以获得此解决方案或任何其他解决方案?

Gui*_*let 5

您可以简单地使用DocumentFilter

import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class TestDocumentFilter {

    private static final String TEXT_NOT_TO_TOUCH = "You can't touch this!";

    private void initUI() {
        JFrame frame = new JFrame(TestDocumentFilter.class.getSimpleName());
        frame.setLayout(new FlowLayout());
        final JTextField textfield = new JTextField(50);
        textfield.setText(TEXT_NOT_TO_TOUCH);
        ((AbstractDocument) textfield.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
                if (offset < TEXT_NOT_TO_TOUCH.length()) {
                    return;
                }
                super.insertString(fb, offset, string, attr);
            }

            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                if (offset < TEXT_NOT_TO_TOUCH.length()) {
                    length = Math.max(0, length - TEXT_NOT_TO_TOUCH.length());
                    offset = TEXT_NOT_TO_TOUCH.length();
                }
                super.replace(fb, offset, length, text, attrs);
            }

            @Override
            public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
                if (offset < TEXT_NOT_TO_TOUCH.length()) {
                    length = Math.max(0, length + offset - TEXT_NOT_TO_TOUCH.length());
                    offset = TEXT_NOT_TO_TOUCH.length();
                }
                if (length > 0) {
                    super.remove(fb, offset, length);
                }
            }
        });
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(textfield);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestDocumentFilter().initUI();
            }
        });
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 令人惊讶的是,当谈到 Java 时,使用“简单”这个词实际上很好,即使代码可能有 100 行长...... (2认同)
  • @sanjeeda您不必获取整个代码,只需获取“DocumentFilter”的部分即可。其余代码仅用于显示完整工作的示例,以避免诸如“我尝试过但它不起作用”之类的评论。 (2认同)

mKo*_*bel 2

我有一个 JTextField,它具有预定义且不可编辑的文本。用户应该能够向其附加其他文本,但无需编辑预定义文本。有没有办法获得这个解决方案或其他解决方案?

使用

  1. JComboBox(不可编辑)

  2. JSpinnerSpinnerListModel

最初由@camickr 制作

在此输入图像描述

import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class NavigationFilterPrefixWithBackspace extends NavigationFilter {

    private int prefixLength;
    private Action deletePrevious;

    public NavigationFilterPrefixWithBackspace(int prefixLength, JTextComponent component) {
        this.prefixLength = prefixLength;
        deletePrevious = component.getActionMap().get("delete-previous");
        component.getActionMap().put("delete-previous", new BackspaceAction());
        component.setCaretPosition(prefixLength);
    }

    @Override
    public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) {
        fb.setDot(Math.max(dot, prefixLength), bias);
    }

    @Override
    public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) {
        fb.moveDot(Math.max(dot, prefixLength), bias);
    }

    class BackspaceAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent e) {
            JTextComponent component = (JTextComponent) e.getSource();
            if (component.getCaretPosition() > prefixLength) {
                deletePrevious.actionPerformed(null);
            }
        }
    }

    public static void main(String args[]) throws Exception {
        JTextField textField = new JTextField(" $ ", 20);
        textField.setNavigationFilter(new NavigationFilterPrefixWithBackspace(textField.getDocument().getLength(), textField));
        JFrame frame = new JFrame("Navigation Filter Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(textField);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 我建议使用 OverlayLayout(JLabel over JTextField),通过更改 JTextField 中 JLabels 区域的 Insets(输入区域),否则 JTextField 中的任何格式都会使该线程中的代码和建议变得毫无用处,并且 Swing GUI 的输出会很奇怪

  • 例如JTextField.setHorizontalAlignment(JTextField.RIGHT);


编辑

  • 将 JLabel & JTextField 放到 JPanel 中,非常简单且无副作用

  • 更改 JPanel 的 FlowLayout 内置内容

  • 当 JLabel 中的文本发生更改时,需要调用 revalidate() 和 repaint()

在此输入图像描述

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class NavigationFilterBias {

    private JFrame frame = new JFrame("Navigation Filter Example");
    private JPanel panel = new JPanel();
    private JLabel label = new JLabel(" $ ");
    private JTextField textField = new JTextField();

    public NavigationFilterBias() {
        panel.setBorder(textField.getBorder());
        panel.setBackground(textField.getBackground());
        panel.setLayout(new BorderLayout());
        panel.add(label,BorderLayout.WEST);
        textField.setBorder(null);
        panel.add(textField,BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String args[]) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                NavigationFilterBias exam = new NavigationFilterBias();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)