2009-09-07 16 views
13

मेरे पास एक ऐसा एप्लिकेशन है जो एक सेकंड को 5 से 50 गुना के बीच एक चर अद्यतन करता है और मैं वास्तविक समय में इस परिवर्तन की निरंतर XY साजिश को चित्रित करने का कोई तरीका ढूंढ रहा हूं।जावा में रीयल-टाइम ग्राफ़िंग

हालांकि इस तरह की उच्च अद्यतन दर के लिए JFreeChart की अनुशंसा नहीं की जाती है, फिर भी कई उपयोगकर्ता कहते हैं कि यह उनके लिए काम करता है। मैंने this डेमो का उपयोग करने का प्रयास किया है और इसे एक यादृच्छिक चर प्रदर्शित करने के लिए संशोधित किया है, लेकिन ऐसा लगता है कि यह हर समय 100% CPU उपयोग का उपयोग करता है। यहां तक ​​कि अगर मैं इसे अनदेखा करता हूं, तो भी मैं फॉर्म बनाने के लिए जेएफरी चार्ट की यूई कक्षा तक सीमित नहीं होना चाहता (हालांकि मुझे यकीन नहीं है कि इसकी क्षमताओं वास्तव में क्या हैं)। जावा के "फॉर्म" और ड्रॉप-डाउन मेनू के साथ इसे एकीकृत करना संभव होगा? (जैसा वीबी में उपलब्ध है) अन्यथा, क्या कोई विकल्प है जिसे मैं देख सकता हूं?

संपादित करें: मैं स्विंग करने के लिए नए हूँ, इसलिए मैं एक साथ एक कोड डाल दिया है बस (जबकि JFree की ApplicationFrame वर्ग का उपयोग न करें, क्योंकि मुझे यकीन है कि कैसे नहीं कर रहा हूँ इसके साथ JFreeChart की कार्यक्षमता का परीक्षण जो स्विंग के कॉम्बो बॉक्स और बटन के साथ काम करेगा)। अभी, ग्राफ तुरंत अद्यतन किया जा रहा है और सीपीयू उपयोग उच्च है। क्या नए मिलीसेकंड() के साथ मूल्य बफर करना संभव होगा और इसे दो बार दो बार अपडेट करना होगा? साथ ही, क्या मैं JFreeChart को बाधित किए बिना शेष जेएफआरएएम में अन्य घटक जोड़ सकता हूं? मुझे यह कैसे करना है? frame.getContentPane()। जोड़ें (नया बटन ("क्लिक करें")) ग्राफ को ओवरराइट करने लगता है।

package graphtest; 

import java.util.Random; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.ValueAxis; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.data.time.Millisecond; 
import org.jfree.data.time.TimeSeries; 
import org.jfree.data.time.TimeSeriesCollection; 

public class Main { 
    static TimeSeries ts = new TimeSeries("data", Millisecond.class); 

    public static void main(String[] args) throws InterruptedException { 
     gen myGen = new gen(); 
     new Thread(myGen).start(); 

     TimeSeriesCollection dataset = new TimeSeriesCollection(ts); 
     JFreeChart chart = ChartFactory.createTimeSeriesChart(
      "GraphTest", 
      "Time", 
      "Value", 
      dataset, 
      true, 
      true, 
      false 
     ); 
     final XYPlot plot = chart.getXYPlot(); 
     ValueAxis axis = plot.getDomainAxis(); 
     axis.setAutoRange(true); 
     axis.setFixedAutoRange(60000.0); 

     JFrame frame = new JFrame("GraphTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     ChartPanel label = new ChartPanel(chart); 
     frame.getContentPane().add(label); 
     //Suppose I add combo boxes and buttons here later 

     frame.pack(); 
     frame.setVisible(true); 
    } 

    static class gen implements Runnable { 
     private Random randGen = new Random(); 

     public void run() { 
      while(true) { 
       int num = randGen.nextInt(1000); 
       System.out.println(num); 
       ts.addOrUpdate(new Millisecond(), num); 
       try { 
        Thread.sleep(20); 
       } catch (InterruptedException ex) { 
        System.out.println(ex); 
       } 
      } 
     } 
    } 

} 

उत्तर

7

यदि आपका चर तेज़ अद्यतन कर रहा है, तो प्रत्येक बार चार्ट अपडेट करने में कोई बात नहीं है।

क्या आपने वैरिएबल परिवर्तनों को बफर करने और चार्ट को रीफ्रेश करने के बारे में सोचा है, प्रत्येक 5 एस कहें? आपको यह पता होना चाहिए कि JFreeChart इस तरह की अद्यतन दरों को अच्छी तरह से संभाल सकता है।

चूंकि JFreeChart एक सामान्य डेस्कटॉप लाइब्रेरी है, इसलिए आप इसे मानक स्विंग एप्लिकेशन के साथ आसानी से एकीकृत कर सकते हैं। या, आप इसे वेब एप्लिकेशन के माध्यम से चार्ट करने के लिए उपयोग कर सकते हैं (जेपीईजी/पीएनजी इत्यादि को प्रतिपादित करके। जेएफरी चार्ट स्वचालित रूप से छवि मानचित्र भी उत्पन्न कर सकता है, ताकि आप माउसओवर इत्यादि का उपयोग कर सकें)

+0

यह एक अच्छा विचार की तरह लगता है, हालांकि मैं भी टाइमस्टैम्प किसी तरह का बफ़र होना होगा। हालांकि, जेएफरी चार्ट 100% सीपीयू उपयोग लेता है चाहे मेरे पास हर सेकेंड में 2 या 50 अपडेट हों। – thodinc

+2

ठीक है, यह काफी कुछ कर रहा है - ग्राफ को हर बार स्क्रैच से पुन: उत्पन्न करना। इसलिए मैं थोड़ी कम बार-बार अद्यतन करने की सिफारिश करता हूं (बेशक यह आपकी मशीन और आपके अतिरिक्त भार पर निर्भर करता है ...) –

0

here से पहले उत्तर दिया गया। आपका चर प्रति सेकंड 50 गुना तक बदलता है, लेकिन ज्यादातर मामलों में आपको हर बार परिवर्तन करने की आवश्यकता नहीं होगी। इसके बजाय आप नियमित अंतराल पर ग्राफ को अपडेट कर सकते हैं (उदाहरण के लिए प्रत्येक 100ms)।

+0

मैंने पहले से ही उस थ्रेड में उल्लिखित कुछ अन्य पुस्तकालयों को देखा है, लेकिन बहुत सारे नहीं हैं कि मैं जावा के ड्रॉप-डाउन बॉक्स और अन्य ऑब्जेक्ट्स के साथ एकीकृत कर सकता हूं। वे सभी अलग-अलग अनुप्रयोगों के रूप में लॉन्च होने लगते हैं। मैं वर्तमान में जेरोबिन देख रहा हूं जो काम कर सकता है, लेकिन उपयोग करने के लिए थोड़ा और जटिल है। – thodinc

1

यदि डेटा चार्ट उत्पन्न करने से अधिक बार अपडेट हो रहा है, तो आपके पास एक अलग थ्रेड में कार्य होना चाहिए जो चार्ट को पुन: उत्पन्न करता है, और जब यह हो जाता है तो एक और पुनर्जन्म शुरू होता है। इसके अलावा अक्सर अयस्क चलाने में थोड़ा सा बिंदु होता है, लेकिन यदि यह एक सीपीयू लोड का बहुत अधिक हो जाता है, तो आप आवृत्ति को वापस थका सकते हैं जिसके साथ यह पुनरारंभ होता है। यदि अपडेट नहीं आते हैं, तो आप पुन: उत्पन्न नहीं करते हैं। मैंने हाल ही में अपने Zocalo project में ऐसा कुछ किया। यह सब कुछ करता है लेकिन थ्रॉटलिंग वापस।

package net.commerce.zocalo.freechart; 

// Copyright 2009 Chris Hibbert. All rights reserved. 

// This software is published under the terms of the MIT license, a copy 
// of which has been included with this distribution in the LICENSE file. 

import java.util.concurrent.atomic.AtomicBoolean; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Callable; 
import java.util.concurrent.Future; 
import java.util.Map; 
import java.util.HashMap; 

/** Schedule a task like generating a price history graph. Multiple requests may come 
in sporadically. We want to ensure that only one is being processed at a time. If we're 
busy processing when a request comes in, we'll remember to start another when this one is 
done. Multiple requests that come in while processing will spur a single restart. */ 
public class ChartScheduler { 
    static private Logger log = Logger.getLogger(ChartScheduler.class); 
    static private Map<String, ChartScheduler> schedulers = new HashMap<String, ChartScheduler>(); 
    private AtomicBoolean generating = new AtomicBoolean(false); 
    private AtomicBoolean requested = new AtomicBoolean(false); 
    private ExecutorService threads = Executors.newCachedThreadPool(); 
    private Callable<Boolean> callable; 
    private int runs = 0; 
    private String name; 


    private ChartScheduler(String name, final Runnable worker) { 
     this.name = name; 
     callable = new Callable<Boolean>() { 
      public Boolean call() throws Exception { 
       worker.run(); 
       runs++; 
       restartIfNeeded(); 
       return true; 
      } 
     }; 
    } 

    public static ChartScheduler create(String name, Runnable worker) { 
     ChartScheduler sched = find(name); 
     if (sched == null) { 
      sched = new ChartScheduler(name, worker); 
      schedulers.put(name, sched); 
     } 
     return sched; 
    } 

    public static ChartScheduler find(String name) { 
     return schedulers.get(name); 
    } 

    public boolean generateNewChart() { 
     requested.set(true); 
     if (generating.compareAndSet(false, true)) { 
      startNewThread(); 
      return true; 
     } else { 
      return false; 
     } 
    } 

    private Future<Boolean> startNewThread() { 
     generating.set(true); 
     requested.set(false); 

     return threads.submit(callable); 
    } 

    private boolean restartIfNeeded() { 
     generating.set(false); 
     if (requested.get()) { 
      return generateNewChart(); 

     } else { 
      return false; 
     } 
    } 

    public boolean isBusy() { 
     return generating.get(); 
    } 

    public int runs() { 
     return runs; 
    } 
} 
0

शायद आप दो धागे का उपयोग कर सकते हैं। आपकी परिवर्तनीय चुड़ैल प्राथमिकता को अद्यतन करने के लिए एक 10 के बराबर है। और दूसरा धागा जो सकारात्मक चुड़ैल प्राथमिकता के रूप में इतनी तेजी से चित्रित करता है।

मुझे एक ऐसे गेम में ऐसा करना था जिसे मैं लिख रहा हूं।

यह संभव है कि मैं आपके प्रश्न को समझ नहीं पाया।

0

ठीक है, मैं उच्च अपडेट के लिए जेएफरीचार्ट का भी उपयोग कर रहा हूं। JFreeChart 10 से 15 फ्रेम/सेकेंड तक अपडेट करता है लेकिन 100% CPU उपयोग का उपयोग करता है। लेकिन अगर मैं इसे बहुत अधिक आवृत्ति पर अपडेट करना चाहता हूं तो इसे अपडेट नहीं किया जाएगा।यदि आपको कोई भी लाइब्रेरी मिलती है जिसे अब 20 एफपीएस पर अपडेट किया जा सकता है और जावा में एप्लिकेशन विकसित करने के लिए इसका इस्तेमाल किया जा सकता है तो कृपया मुझे भी सुझाव दें। मैंने कई लाइब्रेरी JFreeChart FAQ देखी हैं लेकिन मुझे यकीन नहीं है कि अगर किसी के पास लगभग 20 एफपीएस पर अपडेट के लिए उपयोग किया जा सकता है।

1

इस ब्लॉग पोस्ट के अनुसार:

http://jonathanwatmough.com/2008/02/prototyping-code-in-clojure/

इसके लागू करने के लिए के.जे. डीएसपी लाइब्रेरी का उपयोग कर ऑडियो स्पेक्ट्रम की 'असली-इश समय' प्रदर्शन संभव:

http://sirk.sytes.net/software/libs/kjdss/index.htm

इसलिए यदि

आप काफी सरल चार्ट के साथ प्राप्त कर सकते हैं यह JFreeChart का विकल्प हो सकता है।

0

अपने सीपीयू को 100% से कम करने के लिए और अपने जीयूआई को उत्तरदायी रहने की अनुमति देने के लिए, आपको अपने चार्ट अपडेटिंग दर को वापस थ्रॉटल करना होगा। प्रति सेकंड लगभग 24 फ्रेम की अधिकतम अद्यतन दर वास्तविक समय चार्ट के लिए समझ में आता है; किसी भी तेजी से वैसे भी कम या ज्यादा अलग है। यदि आपका डेटा उस दर से तेज़ी से आ रहा है, तो आपको बस पृष्ठभूमि में इसे बफर करना होगा और अपनी चार्ट को अपनी वांछित अद्यतन दर पर अग्रभूमि में अपडेट करना होगा। निम्नलिखित उदाहरण में, मैं XChart का उपयोग SwingWorker पृष्ठभूमि थ्रेड के साथ करता हूं। डेटा कैप्चर प्रत्येक 5 एमएस प्रति एक की दर से निर्धारित किया जाता है और यह चार्ट प्रति सेकंड 24 फ्रेम पर अपडेट किया जाता है। इस अवधारणा को JFreeCharts या किसी अन्य चार्टिंग लाइब्रेरी के साथ-साथ मामूली संशोधन के साथ काम करना चाहिए। अस्वीकरण: मैं एक्सचर्ट का मुख्य डेवलपर हूं।

import java.util.LinkedList; 
import java.util.List; 

import javax.swing.SwingWorker; 

import org.knowm.xchart.QuickChart; 
import org.knowm.xchart.SwingWrapper; 
import org.knowm.xchart.XYChart; 

/** 
* Creates a real-time chart using SwingWorker 
*/ 
public class SwingWorkerRealTime { 

    MySwingWorker mySwingWorker; 
    SwingWrapper<XYChart> sw; 
    XYChart chart; 

    public static void main(String[] args) throws Exception { 

    SwingWorkerRealTime swingWorkerRealTime = new SwingWorkerRealTime(); 
    swingWorkerRealTime.go(); 
    } 

    private void go() { 

    // Create Chart 
    chart = QuickChart.getChart("SwingWorker XChart Real-time Demo", "Time", "Value", "randomWalk", new double[] { 0 }, new double[] { 0 }); 
    chart.getStyler().setLegendVisible(false); 
    chart.getStyler().setXAxisTicksVisible(false); 

    // Show it 
    sw = new SwingWrapper<XYChart>(chart); 
    sw.displayChart(); 

    mySwingWorker = new MySwingWorker(); 
    mySwingWorker.execute(); 
    } 

    private class MySwingWorker extends SwingWorker<Boolean, double[]> { 

    LinkedList<Double> fifo = new LinkedList<Double>(); 

    public MySwingWorker() { 

     fifo.add(0.0); 
    } 

    @Override 
    protected Boolean doInBackground() throws Exception { 

     while (!isCancelled()) { 

     fifo.add(fifo.get(fifo.size() - 1) + Math.random() - .5); 
     if (fifo.size() > 500) { 
      fifo.removeFirst(); 
     } 

     double[] array = new double[fifo.size()]; 
     for (int i = 0; i < fifo.size(); i++) { 
      array[i] = fifo.get(i); 
     } 
     publish(array); 

     try { 
      Thread.sleep(5); 
     } catch (InterruptedException e) { 
      // eat it. caught when interrupt is called 
      System.out.println("MySwingWorker shut down."); 
     } 

     } 

     return true; 
    } 

    @Override 
    protected void process(List<double[]> chunks) { 

     System.out.println("number of chunks: " + chunks.size()); 

     double[] mostRecentDataSet = chunks.get(chunks.size() - 1); 

     chart.updateXYSeries("randomWalk", null, mostRecentDataSet, null); 
     sw.repaintChart(); 

     long start = System.currentTimeMillis(); 
     long duration = System.currentTimeMillis() - start; 
     try { 
     Thread.sleep(40 - duration); // 40 ms ==> 25fps 
     // Thread.sleep(400 - duration); // 40 ms ==> 2.5fps 
     } catch (InterruptedException e) { 
     } 

    } 
    } 
} 

XChart SwingWorker Realtime Java Chart

संबंधित मुद्दे