如何在Java Swing for Hangman游戏中获取从监听器更新的文本字段?

时间:2013-10-15 23:14:57

标签: java swing jtextfield

我正在尝试从Hangman程序编写代码。我不确定这个想法是否正确。我想在文本字段中使用短划线(_ _ _ _ _),当用户按下按钮时必须动态更改。例如,如果用户在下面的代码中按下按钮“A”,则破折号应改为(A _ _ _ _)。那是用户已经猜到字母A是正确的。

我仍然对如何实现这一点感到困惑。附加eventListeners将是我的下一个部分。 但是现在,我必须得到基本的GUI工作,为此我需要一个关于如何实现整个事情的想法。

让这项工作更好的方法是什么? 这是我现在的代码。

import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class HangmanGUI {

public HangmanGUI() {
    JFrame myframe= new JFrame();
    myframe.getContentPane().setLayout(new BorderLayout());
    JPanel myPanel = new JPanel();
    myPanel.setLayout(new GridLayout(2,15));
    myframe.setSize(600,600);

    for (char alphabet = 'A';alphabet<='Z';alphabet++){
        myPanel.add(new JButton(alphabet+""));
    }

    myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
    myframe.setTitle("Hangman Game");
    myframe.setVisible(true);
    myframe.setLocationRelativeTo(null);
    myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args){
    new HangmanGUI();
}
}

3 个答案:

答案 0 :(得分:4)

您可以使用DocumentFilter API,以便您实时过滤来自用户的传入结果。

这个例子有点棘手,因为它隐藏了插入符号,因此它允许文本以您想要的任何顺序出现。

例如,该示例使用Duck作为秘密(算法不区分大小写)。如果用户键入 c ,则该字段将显示为__c_。当然,你可以简单地将传入的角色插入到下一个位置,但那里的乐趣在哪里。

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.DefaultCaret;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;

public class HangManField {

    public static void main(String[] args) {
        new HangManField();
    }

    public HangManField() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private String secret = "Duck";
        private String guesses = secret;

        public TestPane() {

            setLayout(new GridBagLayout());

            Caret blank = new DefaultCaret() {

                @Override
                public void paint(Graphics g) {
                }

                @Override
                public boolean isVisible() {
                    return false;
                }

                @Override
                public boolean isSelectionVisible() {
                    return false;
                }

            };

            JTextField field = new JTextField("____");
            field.setCaretPosition(0);
            field.setCaret(blank);
            ((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {

                @Override
                public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {

                    replace(fb, offset, offset, string, attr);

                }

                @Override
                public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                    System.out.println("rplace");
                    StringBuilder sb = new StringBuilder(guesses.toLowerCase());
                    for (int index = 0; index < text.length(); index++) {
                        String at = text.substring(index, index + 1).toLowerCase();
                        int subIndex = sb.indexOf(at);
                        if (subIndex > -1) {
                            super.replace(fb, subIndex, 1, at, attrs);
                            sb.delete(index, index);
                        }
                    }
                }

                @Override
                public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException {
                    StringBuilder sb = new StringBuilder(length);
                    while (sb.length() < length) {
                        sb.append("_");
                    }
                    replace(fb, offset, length, sb.toString(), null);
                }
            });

            add(field);
        }
    }

}

此算法不能做的事情,目前支持多个重复出现的字符,例如characters。你做这项工作不会花费太多时间;)

答案 1 :(得分:3)

是使用JFromattedTextFeildMaskFormatterMaskFormattersetPlaceholderCharacter('_')功能可以帮助您。您可能还需要使用InputVerifier来验证用户输入的有效性。 JFormattedTextFeild的文档中有一个示例,说明如何使用InputVerifier

答案 2 :(得分:1)

我不推荐使用破折号的文字字段,但你可以这样做。尝试一下,看看它的外观然后创造更好的东西:-)例如,您可以使用带有图像,程式化按钮的面板或标签,或者只使用带有字符的大标签。画一幅你希望你的游戏看起来像什么的图片,然后开始编码。这是代码之前的设计: - )