我有一个JavaFX表,最终会在网络线程上收到数据。
使用Platform.runLater()更新视图模型很简单,但它不适合我们的架构。
当前的架构将应用程序分为" view"和"网络/通讯"部分。
所以我处于两难境地。
忠于架构和"关注点分离" - 网络阅读器类不应该调用Platform.runLater()
为了简单起见并让网络阅读器类调用Platform.runLater()
- 只是工作 - 没有其他代码。
我试图在代码
中说明这一点只需从网络阅读器
调用Platform.runLater()即可public class SimpleUpdate extends Application {
private int clock;
public class Item {
private IntegerProperty x = new SimpleIntegerProperty(0);
public final IntegerProperty xProperty() {
return this.x;
}
public final int getX() {
return this.xProperty().get();
}
public final void setX(final int x) {
this.xProperty().set(x);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Item> viewModel = FXCollections.observableArrayList();
TableView<Item> table = new TableView<Item>(viewModel);
TableColumn<Item, Integer> colX = new TableColumn<>();
colX.setCellValueFactory(new PropertyValueFactory<Item, Integer>("x"));
table.getColumns().add(colX);
primaryStage.setScene(new Scene(table));
primaryStage.show();
new Thread(() -> {
while (true) {
Platform.runLater(() -> { // update on JavaFX thread
if (clock % 2 == 0) {
viewModel.add(new Item());
viewModel.add(new Item());
} else {
viewModel.remove(1);
}
for (Item each : viewModel) {
each.setX(each.getX() + 1);
}
clock++;
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Network update").start();
}
public static void main(String[] args) {
launch(args);
}
}
代码
public class PureUpdate extends Application {
private int clock;
public class Item {
private IntegerProperty x = new SimpleIntegerProperty(0);
public final IntegerProperty xProperty() {
return this.x;
}
public final int getX() {
return this.xProperty().get();
}
public final void setX(final int x) {
this.xProperty().set(x);
}
}
public class ViewItem extends Item {
private Item original;
public ViewItem(Item original) {
super();
this.original = original;
sync();
}
public void sync() {
setX(original.getX());
}
public Item getOriginal() {
return original;
}
}
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<ViewItem> viewModel = FXCollections.observableArrayList();
TableView<ViewItem> table = new TableView<ViewItem>(viewModel);
TableColumn<ViewItem, Integer> colX = new TableColumn<>();
colX.setCellValueFactory(new PropertyValueFactory<ViewItem, Integer>("x"));
table.getColumns().add(colX);
primaryStage.setScene(new Scene(table));
primaryStage.show();
ObservableList<Item> networkModel = FXCollections
.synchronizedObservableList(FXCollections.observableArrayList());
networkModel.addListener((Observable obs) -> {
Platform.runLater(() -> {
List<Item> alreadyKnown = new ArrayList<>();
for (Iterator<ViewItem> it = viewModel.iterator(); it.hasNext();) {
ViewItem each = it.next();
alreadyKnown.add(each.getOriginal());
if (networkModel.contains(each.getOriginal())) {
each.sync();
} else {
it.remove();
}
}
for (Item each : networkModel.toArray(new Item[0])) {
if (!alreadyKnown.contains(each)) {
viewModel.add(new ViewItem(each));
}
}
});
});
new Thread(() -> {
while (true) {
if (clock % 2 == 0) {
networkModel.add(new Item());
networkModel.add(new Item());
} else {
networkModel.remove(1);
}
for (Item each : networkModel) {
each.setX(each.getX() + 1);
}
clock++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Network update").start();
}
public static void main(String[] args) {
launch(args);
}
}
问题。我可以在不编写额外代码的情况下实现纯粹的方法吗?
答案 0 :(得分:4)
让处理器向Runnable
发布通知。或Consumer<T>
,或定义自定义@FunctionalInterface
。
当您设计线程以及对JavaFX或任何其他需要在特定线程上进行同步的框架的依赖时,这将使测试更容易。
使用消费者的示例:
public class NetworkReader {
private final Consumer<? super Data> consumer;
public NetworkReader(Consumer<? super Data> consumer) {
this.consumer = Objects.requireNonNull(consumer);
}
public void readStuff() {
while (...) {
Data data = ...;
consumer.accept(data);
}
}
}
NetworkReader
将由例如new NetworkReader(d -> Platform.runLater(() -> updateModel(d)));
构建。 NetworkReader reader = new NetworkReader(d -> this.actuals = d);
reader.readStuff();
assertEquals(expecteds, actuals);
当您想要测试时,您可以按如下方式传递:
def compute_variance_grayscale(self, clusters, centroids, gImage, k):
# compute variance
variance = 0
for i in range(len(clusters)): #iterate over the available clusters
cluster = clusters[i]
sum = 0;
centroid = centroids[i]
for j in cluster: #for each data point in cluster j compute the sum
sum += (gImage.getImageValueAt(j[0], j[1]) - centroid) ** 2
variance += sum / (len(cluster) - k); #add the sum to the given variance
return variance
def compute_variance_rgb(self, clusters, centroids, cImage, k):
# compute variance
variance = 0
for i in range(len(clusters)):
cluster = clusters[i]
sum = 0;
centroid = centroids[i]
for j in cluster:
b,g,r = cImage.getImageValueAt(j[0], j[1])
b_e = (b - centroid[0]) ** 2
g_e = (g - centroid[1]) ** 2
r_e = (r - centroid[2]) ** 2
sum += (b_e + g_e + r_e)
variance += sum / (len(cluster) - k);
return variance
智能消费者可以在实际处理之前进行更新。