JTextField,其中可以将不可编辑但其他文本的预定义文本追加到其中?

时间:2013-04-30 07:59:35

标签: java swing jtextfield

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

5 个答案:

答案 0 :(得分:2)

  

我有一个JTextField,它有预定义的,不可编辑的文本。该   用户应该能够将其他文本附加到它但不编辑   预定义文本。是否有任何方法可以获得此解决方案或任何   其他

使用

  1. JComboBox (non_editable)

  2. JSpinnerSpinnerListModel

  3. 最初由@camickr

    制作

    enter image description here

    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);
        }
    }
    
    • 我建议使用OverlayLayout(JLabel over JTextField),通过在JTextField中为JLabels区域更改Insets(输入区域),否则JTextField中的任何格式都会使此线程中的代码和建议毫无用处且输出奇怪到Swing GUI

    • e.g。 JTextField.setHorizontalAlignment(JTextField.RIGHT);


    修改

    • 把JLabel& JTextField到JPanel,非常简单,没有副作用

    • 更改内置在FlowLayout中的JPanel

    • 在JLabel中的文本发生变化时需要调用revalidate()和repaint()

    enter image description here

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

答案 1 :(得分:2)

您只需使用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();
            }
        });
    }

}

答案 2 :(得分:1)

看看DocumentFilter。它应该允许你定义一个受保护的&#34;文本区域。

示例herehere

答案 3 :(得分:1)

虽然我相信DocumentFilter是合乎逻辑的多功能解决方案,但这里只是一个简短的解决方案。它只是创建一个内部左边距的JTextField,其中写入了固定文本。

public class PrefixTextField extends JTextField {
    private String prefix;
    private JLabel label;

    public PrefixTextField(String prefix) {
        this.prefix = prefix;
        label = new JLabel(prefix + '\u00a0');
    }

    @Override
    protected void paintComponent(Graphics g) {
        int w = SwingUtilities.computeStringWidth(
                getFontMetrics(getFont()), prefix);
        setMargin(new Insets(3, 3 + w, 3, 3));
        super.paintComponent(g);
        SwingUtilities.paintComponent(g, label, this.getParent(),
                2 + 3, 0, getWidth(), getHeight());
    }
}

答案 4 :(得分:-1)

替代解决方案:
1.将$ symbole放在JTextField中 2.当JTextField获得焦点时,删除美元符号 3.让用户修改全文
4.当他完成输入(see here)后,再添加$ symbole

但是在JTextField

旁边添加标签会更容易