java - 如何每 2 秒更新 TextArea(Jframe) 中的变量?

标签 java swing timer jframe jsoup

---该项目旨在每 2 秒更新一次由 Jsoup 从网站解析的股票报价列表。


过程:

  1. 使用 JSOUP 提取报价列表(这已经完成并存储在字符串变量 (Stock) 中(完成)

  2. 创建 Jframe 、JPanel 和 TextArea 。将 Stock 粘贴到 TextArea 上。因此,股票行情可以显示在 Jframe-textArea 上。 (完成)

  3. 让 TextArea 每 2 秒更新一次变量 stock(正在执行)


代码:

    public void run() {     // Just conduct the Parsing 

    try {
        Parsing();
    } catch (Exception ex) {
        Logger.getLogger(Stock2.class.getName()).log(Level.SEVERE, null, ex);
    }
}

     public  void Parsing() throws Exception 

    {
    }//Jsoup code .Parsing the element from website and stored in String `Stock`

主要代码在这里工作:主要方法

在main中,在这里创建Jframe、panel、textarea。然后,将 stock 粘贴到 JLabel 上。

public static void main(String[] args)  throws Exception {
//  Timer timer = new Timer();
//timer.schedule(new Stock2(), 2000, 2000); 


// javax.swing.Timer timer = new javax.swing.Timer(1000, new ActionListener() {
//        public void actionPerformed(ActionEvent e) {


Stock2 stock3=new Stock2();
stock3.run();

    final  JFrame frame = new JFrame("Stock");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ///------------------------------

            frame.setLayout(new BorderLayout());

            frame.setSize(500, 500);
            frame.setLocationRelativeTo(null);
                  frame.setVisible(true);
             ///------------------------------

          final JPanel panel = new JPanel();

                 ///------------------------------



      JTextArea textArea = new JTextArea(25,40);
         ///------------------------------
     JScrollPane scroll= new JScrollPane(textArea);

scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         ///------------------------------
                textArea.setFont(new Font("Serif",Font.BOLD,16));
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setOpaque(false);
    textArea.setEditable(false   );
      //  textArea. append("g"); 
      textArea.setSize( textArea.getPreferredSize() );
    textArea.setText(String.valueOf(stock));
      //textArea. insert("               ", 5);
       //    textArea.setTabSize(50);
             ///------------------------------

        frame.add(panel);
     panel.add(scroll);
   //  frame.add(scroll);
        frame.pack();
    //    frame.setVisible(true);
  }

**搜索后,我知道我应该使用 Swing Timer。但我不知道该放在哪里(主要?运行?)。另外,我尝试继续工作并添加到主要方法中。但是出现错误。如何解决? **

最佳答案

您想每 2 秒执行一次任务,因此 Swing Timer 似乎是执行此操作的方法,但由于该任务涉及查询 Internet 的内容,因此此过程需要的时间非常多,如果像 Swing 计时器那样在 GUI 事件线程上运行,可能会卡住您的 GUI。相反,您可能应该使用 SwingWorker,并且在 SwingWorker 内部使用 java.util.Timer ,而不是 Swing Timer,因为您将离开 Swing 事件线程,重复调用代码以获取所需的数据,然后使用 SwingWorker 的发布/处理方法对将信息传递给 GUI。查看教程,Concurrency in Swing有关如何执行此操作的详细信息,事实上,您可能会创建一个 SwingWorker<Void, String>这样发布/处理就会知道您要传输的是文本数据。

另一个不相关的问题是你的代码太多了,静态 main 方法中的 GUI 代码太多了,如果不重构,你的程序将很难调试, 测试和维护。通过为每个职责创建单独的类来解决此问题。

其他问题:

  • 从不设置 JTextArea 的首选大小。这样做,看看当您的文本最终填满可见文本区域时会发生什么。然后再添加一些文本,JScrollPane 将不会滚动,因为您已经固定了文本区域的首选项大小。而是设置它的列和行属性。

例如:

import java.awt.BorderLayout;
import java.awt.Font;
import java.util.List;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class StockEg {

    // main method starts Swing event thread and 
    // calls create and show
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    // create pertinent classes and start them running. that's it
    private static void createAndShowGui() {
        // create and display GUI
        StockGui stockGui = new StockGui();
        JFrame frame = new JFrame("StockEg");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(stockGui.getMainPanel());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        // create worker and hook up with GUI
        MyWorker myWorker = new MyWorker(stockGui);
        myWorker.execute();  // start worker
    }
}

// gui class
class StockGui {
    private static final int TA_ROWS = 20;
    private static final int TA_COLS = 40;
    private static final Font TA_FONT = new Font(Font.SERIF, Font.BOLD, 16);
    private JTextArea textArea = new JTextArea(TA_ROWS, TA_COLS);
    private JPanel mainPanel = new JPanel(new BorderLayout());

    public StockGui() {
        textArea.setFont(TA_FONT);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        mainPanel.add(scrollPane, BorderLayout.CENTER);
    }

    // get main JPanel that holds everything
    public JPanel getMainPanel() {
        return mainPanel;
    }

    // allow outside classes to add text to JTextArea
    public void appendText(String text) {
        textArea.append(text);
    }
}

// SwingWorker to run long-running process
class MyWorker extends SwingWorker<Void, String> {
    private static final long PERIOD = 2000; // for timer
    private StockGui stockGui; // gui reference

    // non-GUI class that parses web page
    private MyJSoupParser myJSoupParser = new MyJSoupParser();

    public MyWorker(StockGui stockGui) {
        this.stockGui = stockGui;  // hook up gui reference
    }

    @Override
    protected Void doInBackground() throws Exception {
        // create java.util.Timer
        java.util.Timer myTimer = new java.util.Timer(true);
        // start timer with task
        myTimer.scheduleAtFixedRate(new MyTask(), 0, PERIOD);
        return null;
    }

    // method to send text to the GUI
    @Override
    protected void process(List<String> chunks) {
        for (String chunk : chunks) {
            stockGui.appendText(chunk + "\n");
        }
    }

    // timer task that extracts text from the JSoup parser
    // and then calls publish to send text to process method and GUI
    private class MyTask extends TimerTask {
        @Override
        public void run() {
            String parsedText = myJSoupParser.getText();
            publish(parsedText);
        }
    }
}

// dummy class just for demo purposes
class MyJSoupParser {
    private int dummyCounter = 0;
    public String getText() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {}
        return "Parsed Text: " + dummyCounter++;
    }
}

关于java - 如何每 2 秒更新 TextArea(Jframe) 中的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38416656/

相关文章:

c++ - 在 Windows 上更改 Qt 的计时器分辨率

c - 我需要知道为什么我的中断在这里不起作用

c# - 线程和单例

java - Spring Rich Client Status Bar 类的替换

java - 通用表模型

java - 如何解决 Caused by : java. lang.ClassNotFoundException : javax. xml.bind.JAXBException migrating to Java 11(Openjdk-11.0.1)

java - 第一次尝试保存数据后,关闭程序后无法打开

java.awt.AWTError : BoxLayout can't be shared 错误

java - 返回与 Java 中参数之一相同的类型

java - 从 ADFS 收到的 SAML 响应中检索声明