2017-06-01 59 views
0

我爲我遇到的問題做了一個小型工作示例程序。請記住袒露我的真正的程序較爲複雜,需要所有這些類,即使這個小樣本中TableView不會更新線程中的新信息

主要類看起來超尺寸:

public class PingTest extends Application { 

private static final ArrayList<PingThread> THREADS = new ArrayList(); 

@Override 
public void start(Stage primaryStage) { 

    AnchorPane root = new AnchorPane(); 
    TableView<Map.Entry<String, Ping>> tblPing = new TableView(); 
    TableColumn<Map.Entry<String, Ping>, String> colName = new TableColumn("Name"); 
    TableColumn<Map.Entry<String, Ping>, String> colTime = new TableColumn("Time"); 
    TableColumn<Map.Entry<String, Ping>, String> colDifference = new TableColumn("Difference"); 

    colName.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(p.getValue().getKey())); 
    colTime.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(Integer.toString(p.getValue().getValue().getTime()))); 
    colDifference.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(Integer.toString(p.getValue().getValue().getDifference()))); 

    ObservableList<Map.Entry<String, Ping>> items = FXCollections.observableArrayList(Pings.getPings().entrySet()); 
    tblPing.setItems(items); 

    Scene scene = new Scene(root, 300, 750); 

    // Align to pane 
    AnchorPane.setTopAnchor(tblPing, 0.0); 
    AnchorPane.setLeftAnchor(tblPing, 0.0); 
    AnchorPane.setRightAnchor(tblPing, 0.0); 
    AnchorPane.setBottomAnchor(tblPing, 0.0); 

    tblPing.getColumns().addAll(colName, colTime, colDifference); 
    root.getChildren().add(tblPing); 

    // Setting primary Stage 
    primaryStage.setOnCloseRequest(e -> { 
     THREADS.forEach(t -> t.interrupt()); 
    }); 
    primaryStage.setTitle("Ping List"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

} 

public static void main(String[] args) { 
    // Some examples 
    String[] servers = {"www.google.com", "www.bing.com", "www.yahoo.com", "www.stackoverflow.com"}; 

    // Start Threads 
    for (String server : servers) { 
     PingThread pingThread = new PingThread(server); 
     pingThread.start(); 
     THREADS.add(pingThread); 
    } 
    launch(args); 
} 

}

助手類

public class Ping { 

private int difference; 
private int time; 
private final String url; 

public Ping(String url,int time) { 
    this.url = url; 
    this.time = time; 
    difference = 0; 
} 

public int getDifference() { 
    return difference; 
} 

public int getTime() { 
    return time; 
} 

public void setTime(int time) { 
    difference = time - this.time; 
    this.time = time; 
} 

public String getUrl() { 
    return url; 
} 

} 

線程

public class PingThread extends Thread { 

private final String SERVER; 
private int ping = 0; 

public PingThread(String server) { 
    SERVER = server; 
} 

@Override 
public void run() { 
    try { 
     while (true) { 
      // Ping, update then sleep 
      ping(); 
      Pings.update(SERVER, ping); 
      Thread.sleep(1000); 
     } 
    } catch (InterruptedException ex) { 
     // Used to end thread 
    } 
} 

public void ping() { 
    try { 
     // Sendinging request 
     InetAddress host = InetAddress.getByName(SERVER); 
     long tm = System.nanoTime(); 
     Socket so = new Socket(host, 80); 
     so.close(); 
     ping =(int)((System.nanoTime() - tm)/1000000L); 
    } catch (IOException ex) { 
    } 

} 

}

數據容器

public class Pings { 

private static final ConcurrentHashMap<String,Ping> PINGS= new ConcurrentHashMap(); 

public static synchronized void update(String server, int time) { 
    if (PINGS.containsKey(server)) { 
     PINGS.get(server).setTime(time); 
    } else { 
     PINGS.put(server, new Ping(server,time)); 
    } 
} 
public static synchronized ConcurrentHashMap<String,Ping> getPings(){ 
    return PINGS; 
} 
} 

GUI目錄沒有更新到新的價值觀,在我更大的執行情況在這個小例子。我在將值綁定到TableView時做了什麼錯誤?

回答

0

這段代碼有許多問題。

最直接的就是調用

FXCollections.observableArrayList(Pings.getPings().entrySet()); 

創建一個新的觀察的名單和Pings.getPings().entrySet()給它增加了一切。但隨後修改用於構建它的集合將不會修改可觀察列表,因此表格不會更改。您需要將可觀察列表存儲在模型中(Pings)並直接進行更新。

您還需要對FX應用程序線程進行更新,您需要在Ping類中使用JavaFX屬性,以便表可以觀察對這些值的更改。

所以:

public class Ping { 

    private final ReadOnlyIntegerWrapper difference = new ReadOnlyIntegerWrapper(); 
    private final ReadOnlyIntegerWrapper time = new ReadOnlyIntegerWrapper(); 
    private final String url; 

    public Ping(String url,int time) { 
     this.url = url; 
     setTime(time); 
     difference.set(0); 
    } 

    public ReadOnlyIntegerProperty differenceProperty() { 
     return difference.getReadOnlyProperty() ; 
    } 

    public final int getDifference() { 
     return differenceProperty().get(); 
    } 

    public ReadOnlyIntegerProperty timeProperty() { 
     return time ; 
    } 

    public final int getTime() { 
     return timeProperty().get(); 
    } 

    public void setTime(int time) { 
     difference.set(time - getTime()); 
     this.time.set(time); 
    } 

    public String getUrl() { 
     return url; 
    } 

} 

數據必須在FX應用程序線程被改變,所以你的數據容器也可以被單線程:

public class Pings { 

    private static final Map<String,Ping> PINGS= new HashMap<>(); 
    private static final ObservableList<Ping> pingList = FXCollections.observableArrayList(); 

    public static void update(String server, int time) { 
     if (PINGS.containsKey(server)) { 
      PINGS.get(server).setTime(time); 
     } else { 
      Ping ping = new Ping(server, time); 
      pingList.add(ping); 
      PINGS.put(server, ping); 
     } 
    } 
    public static ObservableList<Ping> getPings(){ 
     return pingList; 
    } 

} 

現在線程做:

public class PingThread extends Thread { 

    private final String SERVER; 

    public PingThread(String server) { 
     SERVER = server; 
    } 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       // Ping, update then sleep 
       final int ping = ping(); 
       // again, not exactly sure how you want to handle exceptions... 
       if (ping >= 0) { 
        Platform.runLater(() -> Pings.update(SERVER, ping)); 
       } 
       Thread.sleep(1000); 
      } 
     } catch (InterruptedException ex) { 
      // Used to end thread 
     } 
    } 

    public int ping() { 
     try { 
      // Sendinging request 
      InetAddress host = InetAddress.getByName(SERVER); 
      long tm = System.nanoTime(); 
      Socket so = new Socket(host, 80); 
      so.close(); 
      return (int)((System.nanoTime() - tm)/1000000L); 
     } catch (IOException ex) { 
      return -1 ; // or handle exception? 
     } 

    } 

} 

最後將表格設置爲:

TableView<Ping> tblPing = new TableView<>(); 
TableColumn<Ping, String> colName = new TableColumn<>("Name"); 
TableColumn<Ping, Number> colTime = new TableColumn<>("Time"); 
TableColumn<Ping, Number> colDifference = new TableColumn<>("Difference"); 

colName.setCellValueFactory(p -> new SimpleStringProperty(p.getValue())); 
colTime.setCellValueFactory(p -> p.getValue().timeProperty()); 
colDifference.setCellValueFactory(p -> p.getValue().differenceProperty()); 

tblPing.getColumns().addAll(colName, colTime, colDifference); 

tblPing.setItems(Pings.getPings()); 
+0

非常感謝yourt的全面解釋 – chenino