2013-04-05 44 views
2

这是我在这里的第一篇文章,所以希望它没有问题。尝试使用线程时程序锁定

我在netbeans。我用纽扣等做了一个窗口。

我有一个叫SimpleThread类,看起来像这样:

public class SimpleThread extends Thread { 

public SimpleThread() 
{ 

} 

@Override 
public void run() 
{ 

} 

而且我有各种不同的子类的线程扩展simplethread(TimerThread,MouseGrabThread)。

public class MouseGrabThread extends SimpleThread{ 

private Point pt; 
private JTextField x, y; 

public MouseGrabThread(JTextField x, JTextField y) 
{ 
    super(); 
    this.x = x; 
    this.y = y; 
} 

@Override 
public void run() 
{ 
    while(this.isAlive()) 
    { 
     int[] xyVal = new int[2]; 
     xyVal = getCoords(); 
     x.setText("" + xyVal[0]); 
     y.setText("" + xyVal[1]); 
    } 
} 

public int[] getCoords() 
{ 
    Point pt = MouseInfo.getPointerInfo().getLocation(); 

    int[] retArr = new int[2]; 
    retArr[0] = (int)pt.getX(); 
    retArr[1] = (int)pt.getY(); 

    return retArr; 

} 



public class TimerThread extends SimpleThread { 

private JTextArea label; 
private int time; 

public TimerThread(JTextArea label, int time) 
{ 
    super(); 
    this.label = label; 
    this.time = time; 
} 

@Override 
public void run() 
{ 
    int counter = time; 
    while(counter != -1) 
    { 

     label.setText("You have: " + counter + " seconds until the timer ends!\n"); 
     counter--; 
     try { 
      this.sleep(1000); 
     } catch (InterruptedException ex) { 
      System.out.println("Thread Interrupted"); 
     } 

    } 
    stop(); 
} 

在我的UI窗口类,我有这样的:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread timer = new TimerThread(jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 
    timer.start(); 
    if(timer.isAlive()) 
    { 
     mouseGrab.start(); 
    } 
    while(timer.isAlive())//###### 
    { 
     if(!mouseGrab.isAlive()) 
     { 
      mouseGrab.start(); 
     } 
    } 

}

程序冻结10秒钟时,我按下按钮。

我猜我已标记的行(// #####)是导致UI在定时器的持续时间内冻结的行,导致它在主线程中运行。我不知道如何解决这个问题。

请原谅我对编程知识的缺乏,现在我正在进入自己的线程,而我正在大学学习关于数据结构的非常简单的课程。如果可能的话,你能尽可能地“减弱”答案吗?另外,我知道我做这件事很糟糕,但我称之为stop()函数,即使它不好(不要为此拍摄我,我不知道该怎么办!)如果有人能够很好地回答这个问题,那太棒了!

回答

1

,你可能想在倒计时结束时结束mouseGrab什么:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread timer = new TimerThread(jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 

    mouseGrab.start(); 
    timer.start(); 

    // Wait until countdown finishes 
    while(timer.isAlive()) {} 

    mouseGrab.stop(); 
} 

在您粘贴代码,你不停地开始你的mouseGrabtimer正在运行。您可能更希望在定时器打开时让鼠标抓取运行。

编辑:的确,stop()已被弃用,你真的应该在你的TimerThread使用boolean running属性,并在一些

while (running) { 
    /* stuff */ 
} 

包裹其run()方法的内容,然后从外部“停止”这个帖子一些二传手。那么正确答案将是例如:

mouseGrab.start(); 
    timer.start(); 

    // Wait until countdown finishes 
    while(timer.isAlive()) {} 

    mouseGrab.setRunning(false); 
} 

EDIT2:这最终似乎是你想要什么:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 
    SimpleThread timer = new TimerThread(mouseGrab, jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 

    mouseGrab.start(); 
    timer.start(); 
} 

有了:

public class MouseGrabThread extends SimpleThread { 

    private Point pt; 
    private JTextField x, y; 
    private boolean running; 

    public MouseGrabThread(JTextField x, JTextField y) { 
     super(); 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public void run() { 
     running = true; 
     while(running) { 
      int[] xyVal = new int[2]; 
      xyVal = getCoords(); 
      x.setText("" + xyVal[0]); 
      y.setText("" + xyVal[1]); 
     } 
    } 

    public int[] getCoords() { 
     Point pt = MouseInfo.getPointerInfo().getLocation(); 

     int[] retArr = new int[2]; 
     retArr[0] = (int)pt.getX(); 
     retArr[1] = (int)pt.getY(); 

     return retArr; 

    } 

    public void break() { 
     this.running = false; 
    } 
} 


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


public class TimerThread extends SimpleThread { 

    private MouseGrabThread mouseGrab; 
    private JTextArea label; 
    private int time; 

    public TimerThread(MouseGrabThread mouseGrab, JTextArea label, int time) 
    { 
     super(); 
     this.label = label; 
     this.time = time; 
     this.mouseGrab = mouseGrab; 
    } 

    @Override 
    public void run() 
    { 
     int counter = time; 
     while(counter != -1) 
     { 
      label.setText("You have: " + counter + " seconds until the timer ends!\n"); 
      counter--; 
      try { 
       this.sleep(1000); 
      } catch (InterruptedException ex) { 
       System.out.println("Thread Interrupted"); 
      } 

     } 

     mouseGrab.break(); 
    } 
} 
+0

如果我想继续GUI在倒计时时可用吗?现在,整个程序冻结,并且它不更新timerThread输出的文本框或鼠标坐标的X和Y textAreas。 – Pilapodapostache 2013-04-05 18:31:54

+0

您的'TimerThread'可以引用'mouseGrab',因此'timer'本身可以决定何时打破它。请参阅我的(传入)** Edit2 **的插图。 – blint 2013-04-05 18:55:01

+0

就是这样,谢谢! :) – Pilapodapostache 2013-04-06 19:31:26

0

还有a better way to cancel a thread than calling stop,但是在你的TimerThread代码中线程正在退出,所以我没有看到这一点。一旦你的执行结束了run方法,那么你的线程就完成了。对于MouseGrabThread,blint's answer是正确的,你应该结束该线程,但我不同意使用标志,canceling the thread using interrupt是一个更好的解决方案。

另外在Swing中,您不应该更新除AWT线程外的Swing组件。请参阅this question。更改您的代码是这样的:

while(counter != -1) 
{ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      label.setText("You have: " + counter 
      + " seconds until the timer ends!\n"); 
     } 
    }); 
    counter--; 
    // etc. 

这种方式,你都在不断下降的AWT队列该事件线程可以把它捡起来,并运行新的任务。您可能也需要为MouseInfo代码执行此操作。

考虑使用Executor而不是启动自己的线程。

我不确定您的响应问题在哪里。不要太快地假设你的代码卡在哪里,添加一些printlns来确认发生了什么(意识到在某些情况下添加它们可能会改变事物的时间)。也删除这些线程中的一些,并逐渐添加它们以查看会发生什么。