2017-08-20 34 views
0

我有一個GUI(其EDT線程)和另一個線程被稱爲「記錄」由GUI的事件監聽創建如果按下按鈕:EDT和其他線程Java之間的傳遞信息與控制器

if(actionEvent.getSource().equals(ui.record)) { 
    if(recorderThread == null) { 
     recorder = new Recorder(); 
     recorderThread = new Thread(recorder); 
     recorderThread.start(); 
    } 
} 

在同一個事件監聽器,我也實現了一個mouseListener。

public void mouseReleased(MouseEvent mEvent) { 
    int x, y; 

    x = mEvent.getXOnScreen(); 
    y = mEvent.getYOnScreen(); 
} 

我想在點擊鼠標時將這些X和Y變量傳遞給記錄器線程中的記錄器對象。我想我可以用volatile變量來解決一個解決方案,但是我在某處讀到處理程序可以用來在兩個線程之間傳遞信息或調用方法,並且有興趣瞭解它。我發現this previous post面臨類似的問題,我的。

然而,解決方案的帖子,讓我很困惑。我認爲這個人將線程對象傳遞給處理程序,那麼任何線程都可以調用該處理程序中的所有對象?例如:

handler(someObj); 

然後在另一個線程

handler.getSomeObj().methodInObj(); 

但我不能完全肯定,如果這是處理程序是如何工作的。另外,他們似乎也在處理Swing的後臺線程,而不是用戶創建的單獨線程(如果這是相同的概念,請提前致歉)。

最後,該解決方案似乎已經調用了Java庫中內置的Handler類,而我想編寫自己的處理程序類,以便我可以更好地瞭解線程是如何通信的(因爲我是一位非常新手的youtube教程程序員) 。如果任何人都可以幫助我,它將不勝感激。提前致謝!

+0

究竟什麼是錄音機做背景的GUI運行時?它正在進行什麼活動? –

+0

而且,你永遠*線程之間發送*而是* *的對象,一個細微但非常重要的區別之間的信息。 –

+0

感謝您的澄清!記錄器只需創建一個名爲「Point」的對象列表,存儲鼠標點擊的X和Y位置,以供自動刷新器使用。 – Jeff

回答

2

另一方面,線程的概念與類的概念(包括與其成員的實例)之間的區別。

線程可以通過多種方式進行通信(意思是在其他線程可以寫入或讀取的地方讀取或寫入變量)在您的示例中,我將讓您的Recorder類公開方法addCoordinates()。一個私有列表成員,其中存儲了添加的座標,真正的問題是對列表的同步訪問:您必須確保沒有一個線程讀取列表,而另一個線程同時添加新記錄。是有一個同步的名單:

private List<Coordinates> myCoordinates = Collections.synchronizedList(new ArrayList<>()); 

public void addCoordinates(Coordinates coordinates) 
{ 
    // this runs in the context of your GUI thread 
    myCoordinates.add(coordinates); 
    synchronized(this) 
    { 
     this.notify(); // wakes up the recorder thread 
    } 

} 

public void run() 
{ 
    // this runs in the context of the Recorder thread 
    while (true) 
    { 
     synchronized(this) 
     { 
      this.wait(); // waits until the 'this' is notified 
     } 

     for(Coordinates c : myCoordinates) 
     { 
      // do something 
     } 
    } 
} 
2

刻錄機只需創建一個名爲「點」存儲對象的列表在鼠標點擊的X和Y位置,要通過autoclicker

然後記錄儀不應該在自己的線程中運行,因爲沒有必要做這個以後使用,而是你會簡單地直接寫入記錄來自EDT線程上的GUI 。否則,你會過度複雜的事情大大。例外情況是,如果記錄器實際上在做更多的事情,例如當前正在運行一個外部進程。

例如:

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class TestRecorder extends JPanel { 
    private static final int GAP = 3; 
    private MyRecorder myRecorder = new MyRecorder(); 
    private boolean recording = false; 

    public TestRecorder() { 
     JPanel btnPanel = new JPanel(new GridLayout(1, 0, GAP, 0)); 
     btnPanel.add(new JButton(new StartAction("Start"))); 
     btnPanel.add(new JButton(new StopAction("Stop"))); 
     btnPanel.add(new JButton(new ShowAction("Show"))); 

     addMouseListener(new MyMouse()); 
     setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 
     setPreferredSize(new Dimension(500, 400)); 
     setLayout(new BorderLayout()); 
     add(btnPanel, BorderLayout.PAGE_END); 
    } 

    private class MyMouse extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
      if (recording) { 
       myRecorder.addPoint(e.getPoint()); 
      } 
     } 
    } 

    private class StartAction extends AbstractAction { 
     public StartAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      recording = true; 
     } 
    } 

    private class StopAction extends AbstractAction { 
     public StopAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      recording = false; 
     } 
    } 

    private class ShowAction extends AbstractAction { 
     public ShowAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println("Points:"); 
      for (Point point : myRecorder.getPoints()) { 
       System.out.println(point); 
      } 
      System.out.println(); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 

    private static void createAndShowGui() { 
     TestRecorder mainPanel = new TestRecorder(); 
     JFrame frame = new JFrame("TestRecorder"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 
} 

public class MyRecorder { 
    private List<Point> points = new ArrayList<>(); 

    public List<Point> getPoints() { 
     return points; 
    } 

    public void addPoint(Point p) { 
     points.add(p); 
    } 
} 
+0

感謝您的迴應!是的,我有種認識到,後沒有被剝奪睡眠和憤怒在加劇試圖瞭解線程-.- 的事情是我也想同樣的過程複製到一個使用機器人類我autoclicker線程的,並且肯定會需要它自己的線程。我只是選擇使用錄音機作爲例子,因爲它更簡單,不會混淆問題。再次感謝您的幫助! – Jeff

+0

也許我應該把它和機器人對象合併起來?這樣,記錄器創建的任何列表都可以被機器人直接訪問,而無需其他複雜的列表和變量傳遞。 *旁註:注意到你是誰一直非常有幫助的,幾乎每一個問題我張貼的傢伙,所以只是想給一個特殊的SO,並感謝您(: – Jeff

+1

@Crumble:你犯了一個大錯新手,螺紋混淆對象你的autoclicker是一個對象,它可以在一個線程中運行,並且它可能在不同的線程上運行的方法。當你傳遞信息到autoclicker,你不能傳遞到一個線程,但到對象,通常如果是從GUI來了,它會進入Swing事件線程上autoclicker對象。 –

相關問題