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

时间:2016-07-16 23:50:46

标签: java swing timer jframe jsoup

---此项目旨在更新Jsoup每2秒从网站解析的股票报价清单。

程序:

  1. 使用JSOUP提取价格报价清单(已经完成并存储在String变量(Stock)中(已完成)

  2. 创建Jframe,JPanel,TextArea。在TextArea上粘贴Stock。因此,stockquote可以显示在Jframe-textArea上。 (完成)

  3. 让TextArea每2秒(做一次)更新变量stock

  4. 代码:

        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。但是我知道要放在哪里(主要?运行?)。此外,我尝试工作并添加到主要方法。但是发生错误。如何解决? **

1 个答案:

答案 0 :(得分:3)

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

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

其他问题:

  • 从不设置JTextArea的首选大小。执行此操作,看看当文本最终填充可见文本区域时会发生什么。然后添加更多文本,并且由于您已修复文本区域的pref大小,因此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++;
    }
}