计算时在 JTextArea 中显示文本

发布于 2024-11-09 04:54:17 字数 272 浏览 4 评论 0原文

我正在编写的应用程序由 JButton 和 JTextArea 等组成。单击该按钮会导致长时间计算,从而在 JTextArea 中显示文本。即使计算很长,我也可以随时得到中间结果(例如,想象一个将 pi 近似为 100 位数字的应用程序 - 每隔几秒我就可以写另一个数字)。问题是,即使我编写(在 ActionListener 类中,因为按钮调用了计算)将 JTextArea 的文本设置为某些内容,计算完成时也不会显示它,我只能看到结尾计算结束后的结果。

为什么会这样,我该如何解决?

先感谢您。

An application I am writing consists, among others, a JButton and a JTextArea. A click on the button leads to a long calculation, resulting in a text shown in the JTextArea. Even though the calculation is long, I can have middle-results on the go (think, for example, of an application which approximates pi up to 100 digits - every few seconds I could write another digit). The problem is, that even if I write (being in the ActionListener class because the button invoked the calculation) to set the text of the JTextArea to something, it isn't shown while the calculation is done, and I can only see the end result, after the calculation is over.

Why is it so, and how can I fix it?

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤芳又自赏 2024-11-16 04:54:17

您的问题是您正在主 Swing 线程(EDT)中进行长时间计算,这将冻结您的整个 GUI,直到该过程自行完成。解决方案是使用后台线程进行计算,一种简单的方法是使用 SwingWorker 创建主 Swing 线程、EDT 的线程后台,并将临时结果发布/处理到 JTextArea 中。有关 SwingWorkers 和 EDT 的更多信息,请查看此处:Swing 中的并发

,如果您提供一个不错的sscce,我们甚至可以为您提供更详细的回复,甚至可以提供示例代码。

SSCCE 示例:

import java.awt.event.*;
import java.text.DecimalFormat;
import java.util.List;
import javax.swing.*;

public class InterimCalc {
   private JPanel mainPanel = new JPanel();
   private JTextField resultField = new JTextField(10);
   private JButton doItBtn = new JButton("Do It!");
   private DecimalFormat dblFormat = new DecimalFormat("0.0000000000");
   private SwingWorker<Void, Double> mySwingWorker = null;

   public InterimCalc() {
      mainPanel.add(doItBtn);
      mainPanel.add(resultField);
      displayResult(0.0);

      doItBtn.addActionListener(new DoItListener());
   }

   public void displayResult(double result) {
      resultField.setText(dblFormat.format(result));
   }

   public JPanel getMainPanel() {
      return mainPanel;
   }

   private class DoItListener implements ActionListener {

      public void actionPerformed(ActionEvent e) {
         if (mySwingWorker != null && !mySwingWorker.isDone()) {
            mySwingWorker.cancel(true);
         }
         displayResult(0.0);
         mySwingWorker = new MySwingWorker();
         mySwingWorker.execute();
      }
   }

   private class MySwingWorker extends SwingWorker<Void, Double> {

      private static final int INTERIM_LENGTH = 10000; // how many loops to do before displaying

      @Override
      protected Void doInBackground() throws Exception {
         boolean keepGoing = true;
         long index = 1L;
         double value = 0.0;
         while (keepGoing) {
            for (int i = 0; i < INTERIM_LENGTH; i++) {
               int multiplier = (index % 2 == 0) ? -1 : 1;
               value += (double)multiplier / (index);
               index++;
            }
            publish(value);
         }
         return null;
      }

      @Override
      protected void process(List<Double> chunks) {
         for (Double dbl : chunks) {
            displayResult(dbl);
         }
      }

   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Decay Const");
      frame.getContentPane().add(new InterimCalc().getMainPanel());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

Your problem is that you're doing a long calculation in the main Swing thread, the EDT, and this will freeze your entire GUI until the process has completed itself. A solution is to use a background thread for your calculation, and an easy way to do this it to use a SwingWorker to create a thread background to the main Swing thread, the EDT, and publish/process the interim results into the JTextArea. For more on SwingWorkers and the EDT, please look here: Concurrency in Swing

Also, if you provide a decent sscce we can probably give you a more detailed response perhaps even with sample code.

An example SSCCE:

import java.awt.event.*;
import java.text.DecimalFormat;
import java.util.List;
import javax.swing.*;

public class InterimCalc {
   private JPanel mainPanel = new JPanel();
   private JTextField resultField = new JTextField(10);
   private JButton doItBtn = new JButton("Do It!");
   private DecimalFormat dblFormat = new DecimalFormat("0.0000000000");
   private SwingWorker<Void, Double> mySwingWorker = null;

   public InterimCalc() {
      mainPanel.add(doItBtn);
      mainPanel.add(resultField);
      displayResult(0.0);

      doItBtn.addActionListener(new DoItListener());
   }

   public void displayResult(double result) {
      resultField.setText(dblFormat.format(result));
   }

   public JPanel getMainPanel() {
      return mainPanel;
   }

   private class DoItListener implements ActionListener {

      public void actionPerformed(ActionEvent e) {
         if (mySwingWorker != null && !mySwingWorker.isDone()) {
            mySwingWorker.cancel(true);
         }
         displayResult(0.0);
         mySwingWorker = new MySwingWorker();
         mySwingWorker.execute();
      }
   }

   private class MySwingWorker extends SwingWorker<Void, Double> {

      private static final int INTERIM_LENGTH = 10000; // how many loops to do before displaying

      @Override
      protected Void doInBackground() throws Exception {
         boolean keepGoing = true;
         long index = 1L;
         double value = 0.0;
         while (keepGoing) {
            for (int i = 0; i < INTERIM_LENGTH; i++) {
               int multiplier = (index % 2 == 0) ? -1 : 1;
               value += (double)multiplier / (index);
               index++;
            }
            publish(value);
         }
         return null;
      }

      @Override
      protected void process(List<Double> chunks) {
         for (Double dbl : chunks) {
            displayResult(dbl);
         }
      }

   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Decay Const");
      frame.getContentPane().add(new InterimCalc().getMainPanel());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}
指尖微凉心微凉 2024-11-16 04:54:17

您可能还想显示某种旋转的 gif 或“进度条”来显示正在计算答案;给用户的反馈很好。

(一旦你使用了 Swingworker,那么 GUI 就不会冻结,并且在计算过程中 GUI 可以做自己的事情)

you may also want to display some sort of spinning gif or "progress bar" to show that the answer is being calculated; feedback to the user is good.

(once you are using a swingworker, then the gui won't freeze and the gui can do its own thing while the calculation is taking place)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文