【问题标题】:After inserting values in JTextField, their random value is not shown. How can I fix it?在 JTextField 中插入值后,不会显示它们的随机值。我该如何解决?
【发布时间】:2021-03-18 15:14:55
【问题描述】:

我编写了这个 Java 应用程序,它用于在启动计数器后从 JTextFields 中输入的值中提取随机值。编译并没有给出错误,但 ("" +randomElement) 值不显示。

我在启动计数器的actionPerformed() 方法中的TimerListener 类中创建了randomElement 属性。在计数结束时,必须显示取自四个 JTextField 的随机值(如下面的代码所示)。

你能告诉我哪里错了吗?我该如何解决?

public class Merge extends JPanel {
    public static final int TIMER_DELAY = 1000;
    public static final String TEST_TEXT = "123456";
    public JTextField textField = new JTextField(16);
    public JButton button = new JButton(new ButtonAction());
    public Timer timer;
    JTextField t1Text = new JTextField();
    JTextField t2Text = new JTextField();
    JTextField t3Text = new JTextField();
    JTextField t4Text = new JTextField();
    JLabel f1Label = new JLabel("Filippo film 1");
    JLabel f2Label = new JLabel("Filippo film 2");
    JLabel l1Label = new JLabel("Laura film 1");
    JLabel l2Label = new JLabel("Laura film 2");

    public Merge() {
        add(button);
        add(textField);
    }

    public static void main(String[] args) {
        Merge me = new Merge();
        me.createAndShowGui();
    }

    public void createAndShowGui() {
        Merge mainPanel = new Merge();
        JFrame frame = new JFrame("Film roulette");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.setLayout(new GridLayout(11, 4));
        frame.pack();
        frame.setBounds(100, 10, 400, 400);
        frame.add(f1Label);
        frame.add(t1Text);
        frame.add(f2Label);
        frame.add(t2Text);
        frame.add(l1Label);
        frame.add(t3Text);
        frame.add(l2Label);
        frame.add(t4Text);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class ButtonAction extends AbstractAction {

        public ButtonAction() {
            super("The movie you will see...");
            putValue(MNEMONIC_KEY, KeyEvent.VK_P);
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            if (timer != null && timer.isRunning()) {
                return;
            }
            textField.setText("");
            timer = new Timer(TIMER_DELAY, new TimerListener());
            timer.start();
        }
    }

    private class TimerListener implements ActionListener {
        private String text = "";
        private int counter = 0;

        @Override
        public void actionPerformed(ActionEvent e) {
            
            String filmFilippo1, filmFilippo2, filmLaura1, filmLaura2;

            filmFilippo1 = t1Text.getText();
            filmFilippo2 = t2Text.getText();
            filmLaura1 = t3Text.getText();
            filmLaura2 = t4Text.getText();

            List<String> givenList = Arrays.asList(filmFilippo1, filmFilippo2, filmLaura1, filmLaura2);
            Random rand = new Random();
            String randomElement = givenList.get(rand.nextInt(givenList.size()));
            
            text += TEST_TEXT.charAt(counter);
            textField.setText(text);
            counter++;
            if (counter >= TEST_TEXT.length()) {
                timer.stop();
                textField.setText("" +randomElement);
            }
        }
    }
}

【问题讨论】:

  • 定时器可能没有在 Swing 线程上运行。你可能想做两件事。 1)在 timer.stop() 调用之后,打印到控制台以显示它正在工作,2)使用 InvokeLater() 之类的东西来确保你的 textField.setText() 发生在 Swing 线程上。
  • @NomadMaker 这是不正确的javax.swing.Timer 保证分配的ActionListeneractionPerformed 方法在EDT 的上下文中被调用
  • @DavidKroukamp 对此感到抱歉。但是,我仍然认为 print 语句对于调试来说是一个好主意。
  • 同意还是断点????

标签: java swing random jtextfield


【解决方案1】:

要回答您的实际问题,它为空的原因是您在createAndShowGui 中执行此操作:

Merge mainPanel = new Merge();
// ...
frame.getContentPane().add(mainPanel);

您创建Merge 类的新实例,然后将其添加到您已经在main(string[] args) 中所做的JFrame

public static void main(String[] args) {
    Merge me = new Merge();
    me.createAndShowGui();
}

所以现在您有 2 个 Merge 类实例,其中一个对用户不可见。您只需在createAndShowGui 中执行此操作:

frame.getContentPane().add(this);

但是

  1. 不要不必要地扩展JPanel
  2. 通过 SwingUtilities.invokeLater 在 EDT 上创建所有 Swing 组件
  3. 使用JFrame#setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 让它完全退出应用程序,除非您只想处置?
  4. 仅在添加所有组件后调用JFrame#pack()
  5. 不要自己打电话给setBounds,你正在使用LayoutManager,就这样吧!
  6. 无需拨打JFrame#getContentPane()#add 只需拨打JFrame#add
  7. 您为计时器的每一个刻度选择一个随机数,为什么不在计时器结束时选择一次呢?
  8. 您可能还想禁用您的 textField,因为人们可能会在那里输入输入并弄乱您的代码逻辑,哈哈
  9. 除非在不同的方法中需要,否则不要全局声明或初始化变量

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Merge {

    public static final int TIMER_DELAY = 1000;
    public static final String TEST_TEXT = "12345";
    private int counter = 1;
    private Random rand = new Random();
    private Timer timer;

    public Merge() {
        createAndShowGui();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Merge::new);
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame("Film roulette");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create components
        JTextField textField = new JTextField(16);
        JButton button = new JButton("The movie you will see...");
        button.setMnemonic(KeyEvent.VK_P);
        JPanel mergePanel = new JPanel();
        JTextField t1Text = new JTextField();
        JTextField t2Text = new JTextField();
        JTextField t3Text = new JTextField();
        JTextField t4Text = new JTextField();
        JLabel f1Label = new JLabel("Filippo film 1");
        JLabel f2Label = new JLabel("Filippo film 2");
        JLabel l1Label = new JLabel("Laura film 1");
        JLabel l2Label = new JLabel("Laura film 2");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (timer != null && timer.isRunning()) {
                    return;
                }

                // gather user input
                List<String> givenList = Arrays.asList(t1Text.getText(), t2Text.getText(), t3Text.getText(), t4Text.getText());

                // reset fields (if button is clicked more then once)
                textField.setText("");
                counter = 0;

                // start a timer
                timer = new Timer(TIMER_DELAY, (ActionEvent ev) -> {
                    if (counter >= TEST_TEXT.length()) {
                        ((Timer) ev.getSource()).stop();
                        String randomElement = givenList.get(rand.nextInt(givenList.size()));
                        textField.setText(randomElement);
                    } else {
                        textField.setText(textField.getText() + TEST_TEXT.charAt(counter));
                        counter++;
                    }
                });

                timer.start();
            }
        });

        // layout components
        mergePanel.add(button);
        mergePanel.add(textField);
        frame.add(mergePanel);
        frame.setLayout(new GridLayout(11, 4));
        frame.add(f1Label);
        frame.add(t1Text);
        frame.add(f2Label);
        frame.add(t2Text);
        frame.add(l1Label);
        frame.add(t3Text);
        frame.add(l2Label);
        frame.add(t4Text);
        frame.setLocationByPlatform(true);

        frame.pack();
        frame.setVisible(true);
    }
}

【讨论】:

    猜你喜欢
    • 2013-12-08
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2011-10-31
    • 2017-02-24
    • 1970-01-01
    • 2016-10-16
    相关资源
    最近更新 更多