Rumah  >  Artikel  >  Isu penyegerakan antara GraphStream's View dan JTextField

Isu penyegerakan antara GraphStream's View dan JTextField

WBOY
WBOYke hadapan
2024-02-22 12:30:171020semak imbas

Editor PHP Strawberry memperkenalkan kepada anda Soal Jawab Java tentang isu penyegerakan antara GraphStream's View dan JTextField dalam artikel ini. Apabila menggunakan pustaka GraphStream, anda kadangkala menghadapi cabaran dengan penyegerakan data antara View dan JTextField. Melalui artikel ini, anda akan belajar bagaimana untuk menyelesaikan masalah ini dan menjadikan program Java anda lebih lancar dan lebih cekap.

Isu kandungan

Saya telah menyiarkan isu saya di https://github.com/graphstream/gs-ui-swing/issues/19#issue-2109865450. Tetapi memandangkan jawapan terakhir pada repositori ini telah disiarkan pada 10 Jun 2021, dan soalan lain telah disiarkan tanpa sebarang balasan, saya tidak pasti sama ada sesiapa masih memberi perhatian kepada soalan di sana. Itulah sebabnya saya bertanya semula soalan saya di sini.

Saya mencipta jframe yang terdiri daripada paparan dan dua medan jtext:

Paparan menunjukkan lima nod: empat hanyalah tanda tempat dan tidak dijangka dialihkan oleh pengguna ("fixed_*"), dan satu akan dialihkan oleh pengguna ("unfixed"). Dua jtextfields memaparkan koordinat nod "tidak disematkan". Kedua-dua paparan dan jtextfield mesti selari antara satu sama lain. Malah, apabila pengguna mengalihkan nod "tidak disematkan" dalam paparan, kedua-dua medan jtext mesti dikemas kini dengan sewajarnya:

Sebaliknya, apabila pengguna mengubah suai koordinat dalam salah satu medan jtext, paparan juga mesti dikemas kini dengan sewajarnya:

Berikut adalah empat kes ujian:

  • Kes Ujian 1: Pengguna menjalankan apl dan menggerakkan nod "tidak disematkan" dalam paparan.
  • Kes Ujian 2: Pengguna menjalankan aplikasi dan mengubah suai koordinat dalam salah satu medan jtext.
  • Kes Ujian 3: Pengguna menjalankan aplikasi, mengubah suai koordinat dalam salah satu medan jtext, dan kemudian menggerakkan nod "tidak disematkan" dalam paparan.
  • Kes Ujian 4: Pengguna menjalankan aplikasi, menggerakkan nod "tidak disematkan" dalam paparan, dan kemudian mengubah suai koordinat dalam salah satu medan jtext.

Kes ujian 1, 2 dan 3 berfungsi dengan baik tetapi kes ujian 4 tidak berfungsi. Malah, dalam kes ujian 4, sebaik sahaja pengguna mengalihkan nod "tidak disematkan" dalam paparan, pengubahsuaian pada koordinat dalam salah satu medan jtext tidak mengemas kini paparan.

Saya cuba menganalisis perbezaan antara pelaksanaan kes ujian 3 dan 4. Untuk melakukan ini, saya mencetak nama benang semasa di pelbagai tempat dalam kod. Saya melihat bahawa pengubahsuaian melalui jtextfield dijalankan pada utas "awt-eventqueue-0" (benang penghantar acara swing, bukan?), manakala pengubahsuaian melalui paparan dijalankan pada utas "thread-0". Dalam pelaksanaan saya, "benang-0" ialah utas yang saya jalankan gelung pam graphstream, menunggu peristiwa yang berlaku dalam utas pemapar graphstream dan menyalinnya kembali dalam "benang-0". Daripada pemahaman saya tentang dokumentasi aliran graf:

  • penonton graphstream sentiasa berjalan dalam urutan penghantaran acara swing (edt),
  • Graf aliran graf yang dikaitkan dengan pemapar aliran graf boleh diakses daripada edt atau urutan lain, bergantung pada model benang graf yang digunakan,
  • Mengakses graf daripada urutan lain adalah lebih berkuasa daripada edt kerana ia membenarkan menjalankan algoritma pada graf selari dengan pemapar aliran graf.

Adakah saya memahami sepenuhnya dokumentasi?

Dalam pelaksanaan saya, saya memilih untuk mengakses graf aliran graf daripada utas lain di luar utas ayunan. Jadi, saya simpulkan daripada kes ujian 3 dan 4 yang dijalankan sebelum ini:

  • Mengemas kini pandangan aliran graf daripada edt tidak menghalang kemas kini masa hadapan pandangan aliran graf daripada "benang-0" (kes ujian 3),
  • Tetapi kemas kini pada paparan graf strim dalam "thread-0" menghalang sebarang kemas kini masa hadapan pada paparan graphstream dalam edt (Kes Ujian 4).

Saya mendapat tanggapan bahawa saya melakukan perkara yang salah dengan semua rangkaian ini. Boleh kamu bantu saya?

Saya cuba membuat contoh kerja minimum (mwe) untuk menghasilkan semula masalah saya. Berikut ialah kandungan fail sumber 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;
        }
    }
    
}

Ini ialah fail pom maven pom.xml yang digunakan untuk membina balang boleh laku dengan semua kebergantungan:

<?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>

Untuk menggunakan kedua-dua fail ini, cuma buat folder mwe/, masukkan nodesynctest.java ke dalam mwe/src/main/java/mwe/ dan pom.xml ke dalam mwe/, kemudian jalankan dalam mwe/

mvn 编译程序集:single

dan

java -jar 目标/mwe-0.0.1-snapshot-jar-with-dependency.jar

Ini ialah folder projek lengkap: mwe.zip

Penyelesaian

Selepas beberapa nyahpepijat, akhirnya saya menemui masalahnya. Saya cuma perlu tukar talian :

unfixedgraphstreamnode.setattribute("xy", myunfixednode.x, myunfixednode.y);

Dengan dua baris:

unfixedgraphstreamnode.setattribute("x", myunfixednode.x);
unfixedgraphstreamnode.setattribute("y", myunfixednode.y);

Semuanya berfungsi dengan baik.

Kenapa

unfixedgraphstreamnode.setattribute("xy", myunfixednode.x, myunfixednode.y);

Tidak bekerja masih menjadi misteri bagi saya. Malah, dokumentasi untuk https://www.php.cn/link/c305a250710e95cf6bad18c18a1c02f4 dan https://www.php.cn/link/7c097a5ed40a8d91afd49026 boleh digunakan. Jadi saya cuba menukar kod kepada: xy 属性来设置节点的坐标。但也鼓励使用属性 xyz

unfixedGraphStreamNode.setAttribute("xyz", myUnfixedNode.x, myUnfixedNode.y, 0.0);

并且它有效!我将在项目的 github 存储库上发布问题。

Atas ialah kandungan terperinci Isu penyegerakan antara GraphStream's View dan JTextField. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam