【问题标题】:JFrame; starts by displaying array element [1] from for loop, rather than [0]框架;首先显示来自 for 循环的数组元素 [1],而不是 [0]
【发布时间】:2023-04-10 00:39:01
【问题描述】:

我已经起草了以下应用程序,以循环遍历字符串数组(我是初学者)。目的是使用 JLabel 在 JFrame 上显示数字 1 到 5;每秒都在变化。

当 JFrame 在屏幕上弹出时,它会奇怪地显示位于数组位置一的数字“二”。这与我的预期相反,我不知道为什么。

i 初始化为 1;存储在“temp”中;然后将其添加到 JLabel 并因此添加到 JFrame。使用这种方法是否有延迟;即到 JLabel 更新时; for循环已经推进了?或者,我知道 Java.swing 有线程问题...?

非常感谢您的帮助。

J

package testApplication;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Count {

    public static void main (String args[]){

        String[] numbers = {"one","two","three","four","five"};
        JLabel numToDisplay = new JLabel("");
        String temp;

        //Initiate JFrame
        JFrame frame = new JFrame("Counting Application");
        frame.setSize(275,100);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        for (int i=0; i < numbers.length; i++){
            temp = numbers[i];
            numToDisplay.setText(temp);
            frame.add(numToDisplay);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

【问题讨论】:

  • 您正在阻塞事件调度线程 - 请改用 Swing 计时器

标签: java arrays for-loop jframe jlabel


【解决方案1】:

不要使用 Thread.sleep 而是使用 Swing Timer 以免让您的 GUI 进入睡眠状态。

例如,

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

public class Count {
   private static int index = 0;

   public static void main(String args[]) {

      final String[] numbers = { "one", "two", "three", "four", "five" };
      final JLabel numToDisplay = new JLabel("", SwingConstants.CENTER);
      String temp;

      // Initiate JFrame
      JFrame frame = new JFrame("Counting Application");
      frame.setSize(275, 100);
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(numToDisplay);
      numToDisplay.setText(numbers[index]);
      frame.setVisible(true);
      int delay = 1000;
      new Timer(delay, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            index++;
            if (index >= numbers.length) {
               ((Timer) e.getSource()).stop();
            } else {
               numToDisplay.setText(numbers[index]);
            }
         }
      }).start();

   }
}

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

@SuppressWarnings("serial")
public class Count2 extends JPanel {
   private static final String[] NUMBERS = { "one", "two", "three", "four", "five" };
   private static final int PREF_W = 300;
   private static final int PREF_H = 100;
   private static final int TIMER_DELAY = 1000;
   private JLabel numToDisplay = new JLabel("", SwingConstants.CENTER);
   private int index = 0;

   public Count2() {
      numToDisplay.setFont(numToDisplay.getFont().deriveFont(Font.BOLD, 60f));
      setLayout(new BorderLayout());
      numToDisplay.setText(NUMBERS[index]);
      add(numToDisplay);
      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   public Dimension getPreferredSize() {
      Dimension superSize = super.getPreferredSize();
      if (isPreferredSizeSet()) {
         return superSize;
      }
      int w = Math.max(PREF_W, superSize.width);
      int h = Math.max(PREF_H, superSize.height);
      return new Dimension(w, h);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         index++;
         if (index >= NUMBERS.length) {
            ((Timer) e.getSource()).stop();
         } else {
            numToDisplay.setText(NUMBERS[index]);
         }
      }
   }

   private static void createAndShowGui() {
      Count2 mainPanel = new Count2();

      JFrame frame = new JFrame("Count2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

【讨论】:

  • 可能会切换 add/setVisible 语句,但 setText 无论如何都会使容器无效
  • 1+,用于使用定时器。但不确定问题是让 GUI 进入睡眠状态,因为代码没有在事件调度线程上执行。该代码适用于我在 Windows 7 上使用 JDK7,因此它必须是其他平台上的某种线程问题。 @jake,阅读 Concurrency in Swing 以更好地了解这些 cmets。
猜你喜欢
  • 2014-01-08
  • 2017-03-26
  • 2021-02-23
  • 2012-06-15
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
  • 2023-02-08
相关资源
最近更新 更多