gpt4 book ai didi

Javafx双向绑定(bind)SimpleDoubleProperty SimpleStringProperty数组越界

转载 作者:行者123 更新时间:2023-12-01 22:15:59 25 4
gpt4 key购买 nike

当我运行以下代码时,出现数组索引越界异常。我的目标是绑定(bind) Text 对象和 ProgressBar 对象,以便它们同时更新。我尝试使用双向绑定(bind)。我一定是踩到什么地方了。我已经运行了它很多次,并且已经看到它成功运行了一两次。通常,在观察进度条一段时间后,就会发生异常。有时我看到一个或两个文本对象在各自的进度条上停止更新,但进度条继续前进,直到出现异常。 JavaFX 绑定(bind)专家请帮忙。

Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.get(ArrayList.java:431)
at javafx.scene.Parent.updateCachedBounds(Parent.java:1580)
at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1377)
at javafx.scene.Node.updateGeomBounds(Node.java:3556)
at javafx.scene.Node.getGeomBounds(Node.java:3509)
at javafx.scene.Node.getLocalBounds(Node.java:3457)
at javafx.scene.Node.updateTxBounds(Node.java:3620)
at javafx.scene.Node.getTransformedBounds(Node.java:3403)
at javafx.scene.Node.updateBounds(Node.java:538)
at javafx.scene.Parent.updateBounds(Parent.java:1708)
at javafx.scene.Parent.updateBounds(Parent.java:1706)
at javafx.scene.Parent.updateBounds(Parent.java:1706)
at javafx.scene.Parent.updateBounds(Parent.java:1706)
at javafx.scene.Parent.updateBounds(Parent.java:1706)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2404)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:314)
at com.sun.javafx.tk.Toolkit$$Lambda$163/2039336538.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:313)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:340)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:525)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:505)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$400(QuantumToolkit.java:334)
at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$40/1271950976.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/1963387170.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)

这是完整的源代码。

    package javafxapplication2;

import java.io.BufferedReader;
import java.net.URL;
import java.security.Provider.Service;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextBoundsType;
import javafx.util.StringConverter;
import javafx.util.converter.DoubleStringConverter;
import javafx.util.converter.NumberStringConverter;
import org.controlsfx.control.HyperlinkLabel;


public class FXMLDocumentController implements Initializable {

@FXML
private TreeView treeView;


List<JobProgress> jobProgressInfos = Arrays.<JobProgress>asList(
new JobProgress("JJ&P_POP_DAT", "Running Jobs"),
new JobProgress("Des_master_33334", "Running Jobs"),
new JobProgress("FS_BUSS", "Running Jobs"),
new JobProgress("CONER_DWN_MIX", "Running Jobs"),
new JobProgress("newjb", "Running Jobs"),
new JobProgress("jb name", "Running Jobs"),
new JobProgress("tst jb", "Pending Jobs"),
new JobProgress("ult--ob", "Pending Jobs"),
new JobProgress("inl jb", "Pending Jobs"),
new JobProgress("fst jb", "Completed Jobs"),
new JobProgress("VoCt_Nme_Jb", "Completed Jobs"));
TreeItem<String> rootNode = new TreeItem<>("Job Details");



@Override
public void initialize(URL url, ResourceBundle rb) {
}

void setup()
{
rootNode.setExpanded(true);
for (JobProgress jobProgressInfo : jobProgressInfos)
{
Text text = new Text();

text.setBoundsType(TextBoundsType.VISUAL);
text.setFill(Color.BLACK);
ProgressBar bar = new ProgressBar(0.0);

//Bind bar and text:
bar.progressProperty().bind(jobProgressInfo.getJobPercentDouble());
text.textProperty().bind(jobProgressInfo.getJobPercentString());

StackPane stack = new StackPane();
stack.getChildren().addAll(bar,text);
Node icon = stack;

text.textProperty().addListener(new ChangeListener<String>()
{
public void changed(ObservableValue ov, String t, String t1) {
System.out.println(ov);
System.out.println(t);
System.out.println(t1);
System.out.println("");
}
});
TreeItem<String> empLeaf = new TreeItem<>(jobProgressInfo.getJobName(),icon);

boolean found = false;
for (TreeItem<String> depNode : rootNode.getChildren())
{
if (depNode.getValue().contentEquals(jobProgressInfo.getJobStatus()))
{
depNode.getChildren().add(empLeaf);
found = true;
break;
}
}
if (!found) {
TreeItem<String> depNode = new TreeItem<>(
jobProgressInfo.getJobStatus()
);
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}

}

treeView.setRoot(rootNode);

treeView.addEventHandler(MouseEvent.MOUSE_CLICKED,new EventHandler<MouseEvent>()
{
@Override public void handle(MouseEvent mouseEvent)
{
if ( mouseEvent.getButton().equals(MouseButton.PRIMARY))
{
if (treeView.getSelectionModel().getSelectedItem() instanceof TreeItem)
{
TreeItem item = (TreeItem)treeView.getSelectionModel().getSelectedItem();
if (item.getParent() != null && item.getParent().getParent() != null)
{
System.out.println("You primary clicked a job!");
}
}
}
else if ( mouseEvent.getButton().equals(MouseButton.SECONDARY))
{
if (treeView.getSelectionModel().getSelectedItem() instanceof TreeItem)
{
TreeItem item = (TreeItem)treeView.getSelectionModel().getSelectedItem();
if (item.getParent() != null && item.getParent().getParent() != null)
{
System.out.println("You scondary clicked a job!");
}
}
}
}
});

Service svc = new Service();
svc.createTask().run();
}

public class Service extends javafx.concurrent.Service<Void>
{

@Override
protected Task<Void> createTask()
{
return new TestTask();
}

private class TestTask extends Task<Void>
{

public TestTask()
{

}

@Override
protected Void call() throws Exception
{
for (JobProgress jp : jobProgressInfos)
{
new Thread(){
@Override
public void run(){
try {

for(double i=0; i<=1; i+=0.01)
{
DecimalFormat df = new DecimalFormat("#.####");
jp.setJobPercentDouble(Double.parseDouble( df.format(i)));
Thread.sleep(500);
}

} catch (InterruptedException ex) {
System.err.println("Error on Thread Sleep");
}
}

}.start();
}
return null;
}

@Override
protected void succeeded()
{
}



@Override
protected void cancelled()
{
}
}
}


public static class JobProgress
{
private final SimpleDoubleProperty jobPercentDouble;
private final SimpleStringProperty jobPercentString;
private final SimpleStringProperty jobName;
private final SimpleStringProperty jobStatus;
private final HyperlinkLabel hyperLink;

private JobProgress(String aJobName, String aJobStatus) {
this.jobName = new SimpleStringProperty(aJobName);
this.jobStatus = new SimpleStringProperty(aJobStatus);
this.hyperLink = new HyperlinkLabel("test");
this.jobPercentDouble = new SimpleDoubleProperty();
this.jobPercentString = new SimpleStringProperty();


Bindings.bindBidirectional(jobPercentString,jobPercentDouble, new NumberStringConverter());
// StringConverter<? extends Number> converter = new NumberStringConverter();

// Bindings.bindBidirectional(stringProp, doubleProp, new Format()
// {
//
// @Override
// public StringBuffer format(Object obj, StringBuffer toAppendTo,FieldPosition pos)
// {
// System.out.println(obj.toString());
// return toAppendTo.append(obj.toString());
// }
//
// @Override
// public Object parseObject(String source, ParsePosition pos)
// {
// System.out.println("parseObj " + source);
// return Integer.parseInt(source);
// }
//
// });
}

public String getJobName() {
return jobName.get();
}

public void setJobName(String value) {
jobName.set(value);
}

public String getJobStatus() {
return jobStatus.get();
}

public void setJobStatus(String value) {
jobStatus.set(value);
}

public SimpleStringProperty getJobPercentString() {
return jobPercentString;
}

public void setJobPercentString(String value) {
jobPercentString.set(value);
}

public SimpleDoubleProperty getJobPercentDouble() {
return jobPercentDouble;
}

public void setJobPercentDouble(double value) {
jobPercentDouble.set(value);
}
}

}

这是 FXML

    <?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="509.0" prefWidth="222.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="javafxapplication2.FXMLDocumentController">
<children>
<TreeView fx:id="treeView" layoutX="11.0" layoutY="5.0" prefHeight="496.0" prefWidth="200.0" AnchorPane.bottomAnchor="8.0" AnchorPane.leftAnchor="11.0" AnchorPane.rightAnchor="11.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>

最后但并非最不重要的一点是:

package javafxapplication2;

import java.net.URL;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class JavaFXApplication2 extends Application {

@Override
public void start(Stage stage) throws Exception
{
URL resource = getClass().getResource("FXMLDocument.fxml");

FXMLLoader loader = new FXMLLoader(resource);
Parent root = (Parent) loader.load();
FXMLDocumentController controller = loader.getController();
controller.setup();

Scene scene = new Scene(root);

stage.setScene(scene);
stage.show();
}

/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}

}

最佳答案

您将如此多的部分混合在一起,例如服务、任务、线程。而且您的命名约定与 JavaFX 的命名约定不同,就像您的属性一样。

在我稍微清理了代码并制作了自己的 JobProgress 类文件之后,您现在应该准备好获取它了。

您错过了在 JobProgress 对象上设置初始进度。那么如果不存在数字,双向绑定(bind)应该如何将数字转换为字符串?!

此外,我还删除了一些监听器和操作处理程序。您应该能够简单地再次添加它们。

FXMLDocumentController.java

import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextBoundsType;

public class FXMLDocumentController implements Initializable {

@FXML
private TreeView treeView;

private final List<JobProgress> jobList = Arrays.<JobProgress>asList(
new JobProgress("JJ&P_POP_DAT", "Running Jobs"),
new JobProgress("Des_master_33334", "Running Jobs"),
new JobProgress("FS_BUSS", "Running Jobs"),
new JobProgress("CONER_DWN_MIX", "Running Jobs"),
new JobProgress("newjb", "Running Jobs"),
new JobProgress("jb name", "Running Jobs"),
new JobProgress("tst jb", "Pending Jobs"),
new JobProgress("ult--ob", "Pending Jobs"),
new JobProgress("inl jb", "Pending Jobs"),
new JobProgress("fst jb", "Completed Jobs"),
new JobProgress("VoCt_Nme_Jb", "Completed Jobs"));

@Override
public void initialize(URL url, ResourceBundle rb) {
TreeItem<String> rootNode = new TreeItem<>("Job Details");

rootNode.setExpanded(true);

for (JobProgress jb : jobList) {
Text text = new Text();
ProgressBar bar = new ProgressBar(0.0);
bar.progressProperty().bind(jb.jobProgressProperty());

text.setBoundsType(TextBoundsType.VISUAL);
text.setFill(Color.BLACK);
text.textProperty().bind(jb.jobProgressStringProperty());

StackPane stack = new StackPane();
stack.getChildren().addAll(bar, text);
Node icon = stack;

TreeItem<String> empLeaf = new TreeItem<>(jb.getJobName(), icon);
boolean found = false;
for (TreeItem<String> depNode : rootNode.getChildren()) {
if (depNode.getValue().contentEquals(jb.getJobStatus())) {
depNode.getChildren().add(empLeaf);
found = true;
break;
}
}
if (!found) {
TreeItem<String> depNode = new TreeItem<>(jb.getJobStatus());
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}
}
treeView.setRoot(rootNode);
new Thread(simulateProgress()).start();

}

private Task<Void> simulateProgress() {
Task<Void> task = new Task<Void>() {

@Override
protected Void call() throws Exception {
for (double i = 0.0; i <= 1.0; i += 0.1) {
for (JobProgress job : jobList) {
job.setJobProgress(i);
}
Thread.sleep(1000);
}
return null;
}
};
return task;
}
}

JavaFXApplication2.java

import java.net.URL;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class JavaFXApplication2 extends Application {

@Override
public void start(Stage stage) throws Exception {
URL resource = getClass().getResource("FXMLDocument.fxml");
FXMLLoader loader = new FXMLLoader(resource);
Parent root = (Parent) loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}

public static void main(String[] args) {
launch(args);
}
}

JobProgress.java

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.util.converter.NumberStringConverter;

public class JobProgress {

private final SimpleDoubleProperty jobProgress;

public double getJobProgress() {
return jobProgress.get();
}

public void setJobProgress(double value) {
jobProgress.set(value);
}

public SimpleDoubleProperty jobProgressProperty() {
return jobProgress;
}

private final SimpleStringProperty jobProgressString;

public void setJobProgressString(String value) {
jobProgressString.set(value);
}

public String getJobProgressString() {
return jobProgressString.get();
}

public SimpleStringProperty jobProgressStringProperty() {
return jobProgressString;
}

private final SimpleStringProperty jobName;

public String getJobStatus() {
return jobStatus.get();
}

public void setJobStatus(String value) {
jobStatus.set(value);
}

private final SimpleStringProperty jobStatus;

public String getJobName() {
return jobName.get();
}

public void setJobName(String value) {
jobName.set(value);
}

public JobProgress(String jobName, String jobStatus) {
this.jobName = new SimpleStringProperty(jobName);
this.jobStatus = new SimpleStringProperty(jobStatus);
this.jobProgress = new SimpleDoubleProperty(0.0);
this.jobProgressString = new SimpleStringProperty();
Bindings.bindBidirectional(jobProgressString, jobProgress, new NumberStringConverter());
}
}

解决方案如下所示:

enter image description here

关于Javafx双向绑定(bind)SimpleDoubleProperty SimpleStringProperty数组越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31035081/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com