java fx节点 位置更新_javafx-2 – JavaFX一次更新大量按钮的最佳方法是什么?

JavaFX一次更新大量按钮/节点的最佳方法是什么?

我提前道歉这是我的第一个StackOverflow问题……

所以我为我们创建的特定内部设备创建了一个模拟器.该设备上有一个按钮,闪烁的LED速率为100毫秒.

所以我基本上创建了一个看起来像内部设备的视图.我在我的视图上设置了一个按钮,通过btn.setStyle闪烁(“ – fx-background-color:#”rgb“;”);

这很好用,但是当我在屏幕上添加100个这样的“设备”时,CPU使用天空火箭并且应用程序变得无法使用.

希望这里有一些相关的代码:

如果当前可见的话,这段代码会调用设备上的Update方法:

final Duration oneFrameAmt = Duration.millis(10);

final KeyFrame oneFrame = new KeyFrame(oneFrameAmt, new EventHandler() {

@Override

public void handle(ActionEvent arg0) {

updateDrawnEntities();

}

}); // oneFrame

// sets the game world's game loop (Timeline)

loop = TimelineBuilder.create().cycleCount(Animation.INDEFINITE).keyFrames(oneFrame).build();

}

protected void updateDrawnEntities() {

for (ADeviceView> view : DeviceLayoutManager.getDeviceViews()) {

Pane content = view.getMainContentPanel();

if (content.isVisible()) {

view.update();

}

}

}

Update方法本身看起来如此(注意m_TaskLED具有通过jfx ChangeListeners设置的值,但它仅在调用run函数时更新.):

@Override

public void update() {

m_TaskLED.run();

}

runnable方法看起来像这样:

@Override

public void run() {

if (m_Color == null) return;

if (m_LEDState == null) return;

if (!m_IsChanged) return;

if (m_LEDState != ELEDState.Off && m_Color != EColor.Off) {

ColorRegistry.applyColor(m_Control, m_Color);

}

else {

ColorRegistry.applyColor(m_Control, null);

}

// Clear the change flag so we can maybe shortcut future executions

m_IsChanged = false;

}

最后但并非最不重要的是applyColor方法看起来像这样:

public static void applyColor(Node p_Node, EColor p_Color) {

if (p_Color != null) {

if (p_Node instanceof Shape) {

((Shape) p_Node).setFill(Paint.valueOf(getRGB(p_Color)));

}

else {

p_Node.setStyle(FX_BACKGROUND_COLOR + getRGB(p_Color) + ";");

}

}

else {

if (p_Node instanceof Shape) {

String style = ((Shape) p_Node).getStyle().toLowerCase();

String rgb = style.substring(style.indexOf(FX_BACKGROUND_COLOR) + FX_BACKGROUND_COLOR.length());

((Shape) p_Node).setFill(Paint.valueOf(rgb));

}

p_Node.setStyle("");

}

}

作为旁注,我尝试了JavaFX 2和JavaFX 8,没有区别.实际上我又回到了JavaFX 2,因为JavaFX 8的性能更差,但我不认为它直接与JavaFX 8有关.事实上,我认为这是JDK8中的性能问题,因为我没有显示/更新任何GUI组件,但我的CPU使用率为20%.

这是我的模拟器的示例图片:

这是我试图模拟的物理设备的示例图片:

这是一些分析:

最佳答案 你能使用

looked-up colors(向下滚动预定义颜色列表的链接)吗?这会每100毫秒快速更改300个按钮,并且它在我的系统上运行良好(需要一段时间才能启动,并且在JIT似乎开始之前有几秒钟,但是它很好).显然,这里的所有按钮都有相同颜色的图形,但你可以根据这一点找出一些逻辑来做更复杂的事情.

您可能还想查看JavaFX 8 PseudoClasses.

import javafx.animation.Animation;

import javafx.animation.KeyFrame;

import javafx.animation.Timeline;

import javafx.application.Application;

import javafx.beans.property.BooleanProperty;

import javafx.beans.property.SimpleBooleanProperty;

import javafx.scene.Scene;

import javafx.scene.control.Button;

import javafx.scene.layout.FlowPane;

import javafx.scene.shape.Circle;

import javafx.stage.Stage;

import javafx.util.Duration;

public class LotsOfFlashingButtons extends Application {

@Override

public void start(Stage primaryStage) {

final FlowPane root = new FlowPane();

root.setStyle("led-color: red;");

final int NUM_BUTTONS = 300 ;

for (int i=0; i

final Button button = new Button(Integer.toString(i+1));

button.setOnAction(event -> System.out.println("Button "+button.getText() + " pressed"));

final Circle circle = new Circle(5);

circle.setStyle("-fx-fill: led-color");

button.setGraphic(circle);

root.getChildren().add(button);

}

final BooleanProperty red = new SimpleBooleanProperty(true);

final Timeline flash = new Timeline(new KeyFrame(Duration.millis(100),

event -> {

red.set( ! red.get());

if (red.get()) {

root.setStyle("led-color: red;");

} else {

root.setStyle("led-color: green;");

}

}

));

flash.setCycleCount(Animation.INDEFINITE);

flash.play();

Scene scene = new Scene(root, 800, 600);

primaryStage.setScene(scene);

primaryStage.show();

}

public static void main(String[] args) {

launch(args);

}

}

顺便说一句,它从您的代码中看起来好像您正在更改用户线程中的样式(即不在JavaFX应用程序线程中).这是你不应该做的事情.

更新:使用setFill(…)肯定更快.这个版本的运行速度比使用css的同等版本快得多.

final Circle[] graphics = new Circle[NUM_BUTTONS];

for (int i=0; i

final Button button = new Button(Integer.toString(i+1));

button.setOnAction(event -> System.out.println("Button "+button.getText() + " pressed"));

final Circle circle = new Circle(5);

graphics[i] = circle ;

button.setGraphic(circle);

root.getChildren().add(button);

}

final Random rng = new Random();

final Timeline flash = new Timeline(new KeyFrame(Duration.millis(100),

event -> {

for (Circle circle : graphics) {

circle.setFill(Color.rgb(rng.nextInt(256), rng.nextInt(256), rng.nextInt(256)));

}

}

));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值