php小编草莓为您介绍本文中关于graphstream的view和jtextfield同步问题的java问答。在使用graphstream库时,有时会遇到view和jtextfield之间数据同步的挑战。通过本文,您将了解如何解决这个问题,让您的java程序更加顺畅和高效。
我已经在 https://github.com/graphstream/gs-ui-swing/issues/19#issue-2109865450 中发布了我的问题。但由于此存储库上的最后一个答案已于 2021 年 6 月 10 日发布,并且其他问题已发布,但没有任何回复,我不确定是否仍然有人在关注那里的问题。这就是为什么我在这里重新问我的问题。
我创建了一个由一个 view 和两个 jtextfield 组成的 jframe:
视图显示五个节点:四个只是地标,预计不会被用户移动(“fixed_*”),还有一个将被用户移动(“unfixed”)。两个 jtextfield 显示“未固定”节点的坐标。 view 和 jtextfield 都必须彼此同步。事实上,当用户移动视图中的“未固定”节点时,两个 jtextfield 必须相应更新:
相反,当用户修改 jtextfield 之一中的坐标时,视图也必须相应更新:
这里有四个测试用例:
测试用例 1、2 和 3 工作正常,但测试用例 4 不起作用。实际上,在测试用例 4 中,一旦用户移动了视图中的“未固定”节点,那么对其中一个 jtextfield 中的坐标的修改不会更新视图。
我试图分析测试用例 3 和 4 的执行之间的差异。为此,我在代码的不同位置打印了当前线程的名称。我看到通过 jtextfield 的修改是在线程“awt-eventqueue-0”(swing 的事件调度线程,不是吗?)上运行的,而通过 view 的修改是在线程“thread-0”上运行的。在我的实现中,“thread-0”是我运行 graphstream 的泵送循环的线程,等待 graphstream 的查看器线程中发生的事件并将它们复制回“thread-0”内。根据我对 graphstream 文档的理解:
我是否充分理解了文档?
在我的实现中,我选择从 swing 线程之外的另一个线程访问 graphstream 的 graph。因此,我从之前运行的测试用例 3 和 4 中推断出:
我的印象是我对所有这些线程都做了错误的事情。你能帮我一下吗?
我尝试制作一个最小工作示例(mwe)来重现我的问题。以下是 java 源文件 nodesynctest.java 的内容:
package mwe;
import java.awt.borderlayout;
import java.awt.component;
import java.awt.gridlayout;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.util.map;
import javax.swing.borderfactory;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jpanel;
import javax.swing.jtextfield;
import javax.swing.swingconstants;
import org.apache.commons.lang3.math.numberutils;
import org.graphstream.graph.graph;
import org.graphstream.graph.node;
import org.graphstream.graph.implementations.multigraph;
import org.graphstream.ui.graphicgraph.graphicgraph;
import org.graphstream.ui.graphicgraph.graphicnode;
import org.graphstream.ui.swing_viewer.swingviewer;
import org.graphstream.ui.view.view;
import org.graphstream.ui.view.viewer;
import org.graphstream.ui.view.viewerlistener;
import org.graphstream.ui.view.viewerpipe;
class nodesynctest {
public static void main(string[] args) {
system.out.println("nodesynctest.main : " + thread.currentthread().getname());
javax.swing.swingutilities.invokelater(new runnable() {
@override
public void run() {
system.out.println("swingutilities.invokelater.runnable.run : " + thread.currentthread().getname());
new nodesynctest();
}
});
}
nodesynctest() {
map<string, mynode> mynodes = map.of(
"fixed_top_left", new mynode(-2, 2),
"fixed_top_right", new mynode(2, 2),
"fixed_bottom_left", new mynode(-2, -2),
"fixed_bottom_right", new mynode(2, -2),
"unfixed", new mynode(0, 0)
);
graphstreamcontrol graphstreamcontrol = new graphstreamcontrol(mynodes);
jtextfieldscontrol jtextfieldscontrol = new jtextfieldscontrol(mynodes);
graphstreamcontrol.jtextfieldscontrol = jtextfieldscontrol;
jtextfieldscontrol.graphstreamcontrol = graphstreamcontrol;
graphstreamcontrol.fillgraphstreamgraph();
jframe maindialog = new jframe();
maindialog.setdefaultcloseoperation(jframe.exit_on_close);
maindialog.setsize(300, 300);
maindialog.getcontentpane().add((component) graphstreamcontrol.view, borderlayout.center);
maindialog.getcontentpane().add(jtextfieldscontrol.panel, borderlayout.south);
maindialog.setlocationrelativeto(null);
maindialog.setvisible(true);
graphstreamcontrol.startpumploop();
}
class graphstreamcontrol {
map<string, mynode> mynodes;
mynode myunfixednode;
graph graphstreamgraph;
viewer viewer;
view view;
viewerpipe viewerpipe;
jtextfieldscontrol jtextfieldscontrol;
graphstreamcontrol(map<string, mynode> mynodes) {
this.mynodes = mynodes;
myunfixednode = mynodes.get("unfixed");
system.setproperty("org.graphstream.ui", "swing");
graphstreamgraph = new multigraph("");
viewer = new swingviewer(graphstreamgraph, viewer.threadingmodel.graph_in_another_thread);
viewer.disableautolayout();
view = viewer.adddefaultview(false);
viewerpipe = viewer.newviewerpipe();
viewerpipe.addsink(graphstreamgraph);
viewerpipe.addviewerlistener(new viewerlistener() {
@override
public void viewclosed(string viewname) {}
@override
public void buttonpushed(string id) {}
@override
public void buttonreleased(string id) {
system.out.println("viewerlistener.buttonreleased : " + thread.currentthread().getname());
if ("unfixed".equals(id)) {
graphicgraph graphicgraph = viewer.getgraphicgraph();
graphicnode unfixedgraphstreamnode = (graphicnode) graphicgraph.getnode("unfixed");
myunfixednode.x = unfixedgraphstreamnode.getx();
myunfixednode.y = unfixedgraphstreamnode.gety();
jtextfieldscontrol.update();
}
}
@override
public void mouseover(string id) {}
@override
public void mouseleft(string id) {}
});
}
public void fillgraphstreamgraph() {
for (var entry : mynodes.entryset()) {
string nodeid = entry.getkey();
mynode mynode = entry.getvalue();
node graphstreamnode = graphstreamgraph.addnode(nodeid);
graphstreamnode.setattribute("xy", mynode.x, mynode.y);
graphstreamnode.setattribute("ui.label", nodeid);
graphstreamnode.setattribute("ui.style", "text-alignment: under;");
}
}
void startpumploop() {
new thread(() -> {
system.out.println("graphstreamcontrol.startpumploop : " + thread.currentthread().getname());
while (true) {
try {
viewerpipe.blockingpump();
} catch (interruptedexception e) {
e.printstacktrace();
}
}
}).start();
}
void update() {
graphicgraph graphicgraph = viewer.getgraphicgraph();
graphicnode unfixedgraphstreamnode = (graphicnode) graphicgraph.getnode("unfixed");
unfixedgraphstreamnode.setattribute("xy", myunfixednode.x, myunfixednode.y);
}
}
class jtextfieldscontrol {
map<string, mynode> mynodes;
mynode myunfixednode;
jpanel panel;
jtextfield xtextfield;
jtextfield ytextfield;
graphstreamcontrol graphstreamcontrol;
jtextfieldscontrol(map<string, mynode> mynodes) {
this.mynodes = mynodes;
myunfixednode = mynodes.get("unfixed");
panel = new jpanel(new gridlayout(1, 4));
jlabel xlabel = new jlabel("x:", swingconstants.right);
xlabel.setborder(borderfactory.createemptyborder(5, 5, 5, 5));
panel.add(xlabel);
xtextfield = new jtextfield(3);
xtextfield.sethorizontalalignment(swingconstants.right);
xtextfield.settext(double.tostring(myunfixednode.x));
xtextfield.getcaret().setdot(0);
xtextfield.addactionlistener(new actionlistener() {
public void actionperformed(actionevent event) {
system.out.println("jtextfieldscontrol - actionperformed on xtextfield : " + thread.currentthread().getname());
string xnodestring = xtextfield.gettext();
double xnodedouble = numberutils.todouble(xnodestring);
myunfixednode.x = xnodedouble;
graphstreamcontrol.update();
}
});
panel.add(xtextfield);
jlabel ylabel = new jlabel("y:", swingconstants.right);
ylabel.setborder(borderfactory.createemptyborder(5, 5, 5, 5));
panel.add(ylabel);
ytextfield = new jtextfield(3);
ytextfield.sethorizontalalignment(swingconstants.right);
ytextfield.settext(double.tostring(myunfixednode.y));
ytextfield.getcaret().setdot(0);
ytextfield.addactionlistener(new actionlistener() {
public void actionperformed(actionevent event) {
system.out.println("jtextfieldscontrol - actionperformed on ytextfield : " + thread.currentthread().getname());
string ynodestring = ytextfield.gettext();
double ynodedouble = numberutils.todouble(ynodestring);
myunfixednode.y = ynodedouble;
graphstreamcontrol.update();
}
});
panel.add(ytextfield);
}
void update() {
string xnodestring = double.tostring(myunfixednode.x);
xtextfield.settext(xnodestring);
xtextfield.getcaret().setdot(0);
string ynodestring = double.tostring(myunfixednode.y);
ytextfield.settext(ynodestring);
ytextfield.getcaret().setdot(0);
}
}
class mynode {
double x;
double y;
mynode(double x, double y) {
this.x = x;
this.y = y;
}
}
}这是 maven pom 文件 pom.xml,用于构建包含所有依赖项的可执行 jar:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mwe</groupId>
<artifactId>mwe</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MWE</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-ui-swing</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- here we specify that we want to use the main
method within the App class -->
<mainClass>mwe.NodeSyncTest</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>mwe.NodeSyncTest</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>要使用这两个文件,只需创建一个文件夹 mwe/,将 nodesynctest.java 放入 mwe/src/main/java/mwe/ 并将 pom.xml 放入 mwe/,然后在 mwe/ 中运行
mvn 编译程序集:single
和
java -jar 目标/mwe-0.0.1-snapshot-jar-with-dependency.jar
这是完整的项目文件夹:mwe.zip
经过一番调试,终于找到了问题出在哪里。我只需要更换线路:
unfixedgraphstreamnode.setattribute("xy", myunfixednode.x, myunfixednode.y);通过两行:
unfixedgraphstreamnode.setattribute("x", myunfixednode.x);
unfixedgraphstreamnode.setattribute("y", myunfixednode.y);让一切正常工作。
为什么
unfixedgraphstreamnode.setattribute("xy", myunfixednode.x, myunfixednode.y);不起作用对我来说仍然是个谜。事实上,https://www.php.cn/link/c305a250710e95cf6bad18c18a1c02f4 和 https://www.php.cn/link/7c097a5ed40a8d91afd49026dd3b1062 的文档说我们可以使用 xy 属性来设置节点的坐标。但也鼓励使用属性 xyz。因此,我尝试将代码更改为:
unfixedGraphStreamNode.setAttribute("xyz", myUnfixedNode.x, myUnfixedNode.y, 0.0);并且它有效!我将在项目的 github 存储库上发布问题。
以上就是GraphStream 的 View 和 JTextField 之间的同步问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号