-2

是否可以像这样在 JTextField 中分发字符串:(蓝色文本字段中的“布鲁诺”)。

JTextField 自动划分为许多等间距的位置作为最大列值。
在此处输入图像描述

我编写这段代码来解释为什么字体跟踪对我不起作用:

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.font.TextAttribute;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class SpacedFieldTest extends JFrame{

    Map<TextAttribute, Object> fontAttributes = new HashMap<TextAttribute,     Object>();
    int maxColumn;
    String text;
    public SpacedFieldTest(String text, int maxColumn) {
        this.text = text;
        this.maxColumn = maxColumn;
        addContent();
        pack();
    }

    private void addContent() {
        setLayout(new FlowLayout());
        final SpacedField field = new SpacedField();
        configureField(field, "Arial", 20f);
        getContentPane().add(field);

        JSpinner spinner = createSpinner(field);
        getContentPane().add(spinner);

        JLabel tracking = new JLabel("Tracking");
        getContentPane().add(tracking);
    }

    private JSpinner createSpinner(final SpacedField field) {
        float min = 0.0f;
        float value = 0.1f;
        float max = 3.0f;
        float stepSize = 0.1f;
            SpinnerNumberModel model = new SpinnerNumberModel(value, min,     max, stepSize);
            JSpinner spinner = new JSpinner(model){
                @Override
                public Object getValue() {
                    fontAttributes.put(TextAttribute.TRACKING,     super.getValue());
                        field.setFont(field.getFont().deriveFont(fontAttributes));
                    return super.getValue();
                }

            };
        spinner.setPreferredSize(new Dimension(50,25));
        JSpinner.NumberEditor editor =     (JSpinner.NumberEditor)spinner.getEditor();
        DecimalFormat format = editor.getFormat();
        format.setMinimumFractionDigits(1);
        return spinner;
    }

    private void configureField(JTextField field, String family, float     fontSize) {

        fontAttributes.put(TextAttribute.SIZE, fontSize);
        fontAttributes.put(TextAttribute.FAMILY, family);
        Font font = Font.getFont(fontAttributes);
        field.setFont(font);
        field.setText(text);
    }

    class SpacedField extends JTextField{
        final int WIDTH = 300;
        final int HEIGHT = 25;
        int gridWidth;
        public SpacedField() {

            gridWidth = WIDTH/maxColumn;
            setPreferredSize(new Dimension(WIDTH, HEIGHT));
            setDocument(new SpacedFieldDocument());
        }
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            paintGrid(g);
        }
        private void paintGrid(Graphics g) {
            for(int i=1; i<=maxColumn; i++){
                g.drawLine(i*gridWidth, HEIGHT/2, i*gridWidth, HEIGHT);
            }

        }
    }

    class SpacedFieldDocument extends PlainDocument{
        public void insertString(int offs, String str, AttributeSet a)
                throws BadLocationException {

            if(getLength()>maxColumn)
                return;
            super.insertString(offs, str, a);
        }
    }

    public static void main(String args[]){

        final SpacedFieldTest sf = new SpacedFieldTest("abcde", 5);
        sf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                sf.setVisible(true);
            }
        });
    }
}
4

1 回答 1

0

可能的。

您要做的是为每个可用字符设置一个单独的 JTextField。最好将其实现为一个独立的类,一个扩展 JComponent 的类,但这取决于您。

我建议将这些放入您的初始化程序中:

private final LinkedList<JTextField> fields = new LinkedList<>();
private KeyListener fieldKeyListener = new KeyListener(){

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() != KeyEvent.VK_BACK_SPACE && e.getKeyCode() != KeyEvent.VK_DELETE) {
            System.out.println("Key code: " + e.getKeyCode());
            int index = fields.indexOf(e.getSource());
            int newIndex = index + 1;
            if(newIndex < fields.size()) fields.get(newIndex).requestFocus();
            else
                System.out.println(gatherString());
                //or use whichever action should retrieve the string
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

};

对于它的肉,你会想要这样做。我继续在 JFrame 的中间动态构建它,但如果你可以想象不止一次这样做,你会想要将它调整为构造函数的初始化程序。

private JComponent getDistField() {
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(1, charCount));

    for(int i = 0; i < charCount; i++) {
        fields.add(new JTextField(1));

        /* All customizations to look and feel, for each component, go here */

        //document must be unique for each field, or text will duplicate.
        fields.getLast().setDocument(new PlainDocument(){
            @Override
            public void insertString(int offs, String str, AttributeSet a)
                    throws BadLocationException {
                if(getLength() + str.length() <= 1)
                    super.insertString(offs, str, a);
            }
        });
        fields.getLast().addKeyListener(fieldKeyListener);
        panel.add(fields.getLast());
    }

    return panel;
}

我假设该字段接受的字符数较早地设置了“charCount”(甚至作为参数传入)。该迭代器创建一系列子文本字段;每个都将处理一个字符并立即更新插入符号的位置。请注意,文档需要对每个字段都是唯一的,否则文本将在整个过程中重复!

理论上,您也可以使用插入符号侦听器而不是关键侦听器来执行此操作;但是,它们与按键无关,并且完全不知道哪个键刚刚按下。并不意味着不可能弄清楚,但我找不到一个干净的方法来做到这一点。

当您准备好输入字符串的全部内容时,请调用如下内容:

public String gatherString() {
    StringBuilder builder = new StringBuilder();
    for(JTextField field : fields) {
        builder.append(field.getText());
    }
    return builder.toString();
}

它从每个字段的内容中组装字符串。值得庆幸的是,空白字段没有任何贡献;如果您希望它们也无法编辑,您可以尝试将它们设置为禁用并使用它们之前的字段的填充来触发它们的启用;甚至添加一个鼠标侦听器来查找最后一个未编辑的字段并在任何单击时突出显示它。这一切都与听众(/observers)有关。

希望这会为你做这件事,我相信你会明白为什么你可能希望它成为它自己的模块。祝你好运!

此外,如果您将来研究问题的正确格式,这将非常有帮助。在目前的情况下,我无法对其进行投票,并且社区会更好地接受它。它将帮助您了解“我如何提出一个好问题?” .

于 2015-05-29T16:22:38.477 回答