我正在制作一个程序,以检查股票市场的符号,我做到了这一点,并添加了一个基本的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?
答案 0 :(得分:1)
你也可以在主线程中使用thread和normal while循环,但是首先,你需要启动线程,并且该线程必须引用你的对象。
在public void buildGui() {
Thread t1 = new Thread(new checkingQuote());
t1.start();
这会启动你的线程,出于测试目的,我修改了checkingQuote
class
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;
}
}
}
}
我在文本框中看到数字更改....同样地,您可以更改逻辑以获取并显示引号..但您必须保留先前引用的值以与最新代码进行比较以显示绿色和红色通知......
答案 1 :(得分:1)
在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
和按钮点击监听器中调用它。
答案 2 :(得分:1)
使用SwingWorker
在后台执行长时间运行的任务,同时根据长时间运行的任务的某些结果更新UI。这意味着,它实际上是两个不同的线程相互通信 - Worker Threads和Event Dispatch Thread (EDT)
但在此之前,我想指出一些关于你的代码的注释。
在EDT中调用UI的初始化。也就是说,而不是直接调用new QuoteTracker().buildGui()
,而是在传递给Runnable
的{{1}}的run方法中调用它(如this)
根据Java标准,类应以大写字母开头。
要在现有代码中应用SwingUtilities.invokeLater
,您可以执行以下操作:
首先,您必须将SwingWorker
方法放在其他类(最好是服务类)中,然后修改checkQuote
方法以返回设置为textfield checkQuote
的{{1}} 1}}。像这样的东西
String
然后,您可以使result
课程主要关注应用程序的UI部分。只需将服务对象创建为实例级别字段,以便您可以在班级中自由调用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 "";
}
}
方法。
单击按钮时调用SwingWorker。
QuoteTracker
请注意,checkQuote
执行完成后将执行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();
}
,这意味着,在我发布的代码中,由于while循环用于定期调用{{1},因此永远不会执行是无限的。只需修改它,以便您可以根据需要中断该循环
进一步阅读:Concurrency in Swing