![](/img/trans.png)
[英]How do I make a GUI that looks like the attached picture of a simple stock market app?
[英]how do I make my program check the stock market value every hour[java]
我正在编写一个程序来检查股票市场中的代码,到此为止,并添加了基本的GUI。 我对如何每小时检查一次感到困惑,如果增加则创建绿色向上箭头,如果减少则创建红色向下箭头。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class QuoteTracker {
JFrame frame;
JPanel mainPanel;
JLabel enterLabel;
JLabel resultLabel;
JTextField text;
JTextField result;
JButton query;
JButton redArrow;
JButton greenArrow;
String url;
public static void main(String[] args) {
new QuoteTracker().buildGui();
}
public class checkingQuote implements Runnable {
@Override
public void run() {
while (true) {
try {
checkQuote(url);
//if increase in value green button
System.out.println("Sleeping");
Thread.sleep(1000 * 60 * 60);
System.out.println("Waking");
} catch (InterruptedException ie) {
ie.printStackTrace();
break;
}
}
}
}
public void checkQuote(String symbol) {
try {
String url = "http://finance.yahoo.com/q?s=" + symbol + "&ql=0";
this.url = url;
Document doc = Jsoup.connect(url).get();
Elements css = doc.select("p > span:first-child > span");
result.setText(css.text());
} catch (IOException e) {
}
}
public void buildGui() {
frame = new JFrame("QuoteTracker");
mainPanel = new JPanel();
enterLabel = new JLabel("enter symbol ");
resultLabel = new JLabel("result ");
text = new JTextField(4);
result = new JTextField(8);
query = new JButton("query");
query.addActionListener(new queryListener());
mainPanel.add(enterLabel);
mainPanel.add(text);
mainPanel.add(query);
mainPanel.add(resultLabel);
mainPanel.add(result);
frame.getContentPane().add(mainPanel);
frame.setSize(300, 400);
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class queryListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ev) {
checkQuote(text.getText());
}
}
}
我甚至需要线程吗? 我从来没有做过一个尝试添加有意义的东西。 我在想我是否需要线程或使用Java的Timer?
您也可以在主线程中使用线程和普通的while循环,但是首先,您需要启动线程,并且该线程必须引用您的对象。
在public void buildGui() {
添加以下行public void buildGui() {
Thread t1 = new Thread(new checkingQuote());
t1.start();
这将启动您的线程,出于测试目的,我修改了checkingQuote
类
public class checkingQuote implements Runnable {
int count = 0;
@Override
public void run() {
System.out.println("Inside Runner");
while (true) {
try {
count++;
checkQuote(url);
//if increase in value green button
result.setText(""+count);
System.out.println("Sleeping");
Thread.sleep(1000);
System.out.println("Waking");
} catch (InterruptedException ie) {
ie.printStackTrace();
break;
}
}
}
}
我在文本框中看到数字更改。...您可以更改获取和显示引号的逻辑。.但是您必须保留前一个引号的值,以与最新代码进行比较以显示绿色和红色通知。 ..
在gui应用程序中,最好使用Timer ,也可以使用ScheduledThreadPoolExecutor 。 但是在第二种情况下,您计划的任务可能会在非GUI线程中运行。 由于无法直接从另一个线程调用ATW / Swing,因此应将对Swing的所有调用包装到SwingUtilities.invokeLater()方法中。
还要注意,当您在GUI线程中执行持久的操作时,整个GUI会变得毫无干扰。 因此,为了获得更好的响应性,您可以在单独的线程中进行查询,并在检查引号后通过invokeLater
将结果公开给Swing。 因此,您的checkQuote
方法可以通过以下方式重写:
public void checkQuote(String symbol) {
try {
final String url = "http://finance.yahoo.com/q?s=" + symbol + "&ql=0";
Document doc = Jsoup.connect(url).get();
Elements css = doc.select("p > span:first-child > span");
final String text = css.text();
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
this.url = url;
result.setText(text);
}
}
} catch (IOException e) {
// Don't swallow exceptions
logger.error("Something gone wrong", e);
}
}
public void checkQuote() {
final String symbol = text.getText();
new Thread(new Runnable() {
@Override public void run() {
checkQuote(symbol);
}
}).start();
}
并从Timer
和按钮单击侦听器中调用它。
使用SwingWorker
在后台执行长时间运行的任务,同时根据该长时间运行任务的一些结果更新UI。 这意味着,实际上是两个相互通信的不同线程- 工作者线程和事件调度线程(EDT)
但是在此之前,我想指出一些有关您的代码的注释。
在EDT中调用UI的初始化。 也就是说,而不只是笔直地调用new QuoteTracker().buildGui()
叫它的run方法里面Runnable
传递给SwingUtilities.invokeLater
(像这样 )
按照Java标准,类应以大写字母开头。
要在现有代码中应用SwingWorker
,可以执行以下操作:
首先,必须将checkQuote
方法放置在其他某个类(最好是服务类)中,然后修改checkQuote
方法以返回设置为textfield result
的String
。 像这样
public Class QuoteService{
public String checkQuote(String symbol) {
try {
String url = "http://finance.yahoo.com/q?s=" + symbol + "&ql=0";
this.url = url;
Document doc = Jsoup.connect(url).get();
Elements css = doc.select("p > span:first-child > span");
return css.text();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
然后,您可以使QuoteTracker
类主要集中在应用程序的UI部分。 只需将服务对象创建为实例级别字段,即可在类中自由调用checkQuote
方法。
单击该按钮时,调用SwingWorker。
public void actionPerformed(ActionEvent ev) {
new SwingWorker<Void, String>() {
@Override // this method is done in the Worker Thread
protected Void doInBackground() throws Exception {
while(true){
String res = checkQuote(text.getText());
publish(res); //will call the process method
Thread.sleep(1000 * 60 * 60); //1 hour
}
}
@Override // this method is done in the EDT
protected void process(List<String> resultList){
String res = resultList.get(0);
if(!"".equals(res)){
result.setText(res);
}
}
@Override // this method is done in the EDT. Executed after executing the doInBackground() method
protected void done() {
//... clean up
}
}.execute();
}
请注意, done()
将在doInBackground()
执行完成后执行,这意味着,在我发布的代码中,由于用于定期调用checkQuote
的while循环是无限的,因此它将永远不会执行。 只需对其进行修改,以便您可以根据需要中断该循环
进一步阅读: Swing中的并发
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.