Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将多个实时图形从XChart添加到JPanel_Java_Swing_User Interface_Graph_Jtabbedpane - Fatal编程技术网

Java 将多个实时图形从XChart添加到JPanel

Java 将多个实时图形从XChart添加到JPanel,java,swing,user-interface,graph,jtabbedpane,Java,Swing,User Interface,Graph,Jtabbedpane,我负责用Java创建一个GUI来监控多个地区多人的心率(出于保密原因进行了修改) 总共有8个地区,每个地区有8个人。这些由JTabbedPane表示,每个区域有一个选项卡。我正在尝试使用XChart库绘制和创建8个实时图形。数据将从文本文件中读取,并作为两个双数组传递。其中一个数组是以毫秒为单位的时间(x轴),第二个数组是一个人的心率数据(y轴)。每个人在其相应的区域选项卡中都有自己的图表 这类似于观看几张图表来监测医院的生命体征,以了解该应用程序应该模拟什么 我目前正在使用模型-视图-控制器体

我负责用Java创建一个GUI来监控多个地区多人的心率(出于保密原因进行了修改)

总共有8个地区,每个地区有8个人。这些由JTabbedPane表示,每个区域有一个选项卡。我正在尝试使用XChart库绘制和创建8个实时图形。数据将从文本文件中读取,并作为两个双数组传递。其中一个数组是以毫秒为单位的时间(x轴),第二个数组是一个人的心率数据(y轴)。每个人在其相应的区域选项卡中都有自己的图表

这类似于观看几张图表来监测医院的生命体征,以了解该应用程序应该模拟什么

我目前正在使用模型-视图-控制器体系结构

TLDR要分解它,我只尝试在JTabbedPane内的JPanel内的选项卡中添加多个实时XYChart。但就目前而言,只需添加一张实时图表就好了

View.java

private void initComponents() {
    jTabbedPane1 = new javax.swing.JTabbedPane();
    tabRegion1 = new javax.swing.JPanel();
    jTabbedPane1.setTabPlacement(javax.swing.JTabbedPane.BOTTOM);
    tabRegion1.setLayout(new java.awt.GridLayout(4, 2));

    // Populate the JPanel with empty static graphs
    for(int i = 0; i < Global.MAX_GRAPHS; i++)
        tabRegion1.add(Graph.getRandomStaticGraph());

    jTabbedPane1.addTab("Region 1", tabRegion1);
}
private void initComponents(){
jTabbedPane1=newjavax.swing.JTabbedPane();
tabRegion1=newjavax.swing.JPanel();
setTabPlacement(javax.swing.jTabbedPane1.BOTTOM);
tabRegion1.setLayout(新java.awt.GridLayout(4,2));
//用空静态图填充JPanel
对于(int i=0;i
Graph.java(模型)

//测试目的
公共静态JPanel getRandomStaticGraph(){
XYChart chart=getEmptyXYChart();
XYSeries=chart.addSeries(“心率”,null,getRandomWalk(200));
系列。设置标记(系列标记。无);
返回新面板(图表);
}
//测试目的
公共静态JPanel getRandomRealTimeGraph()抛出InterruptedException{
XYChart chart=getEmptyXYChart();
//表现出来
最终摇摆振打器sw=新摇摆振打器(图表);
sw.displayChart();
双相=0;
double[]initdata=getSineData(阶段);
XYSeries=chart.addSeries(“心率”,null,getRandomWalk(200));
while(true){
相位+=2*Math.PI*2/20.0;
睡眠(100);
最终双[][]数据=getSineData(阶段);
图表.UpdateXeseries(“正弦”,数据[0],数据[1],空);
sw.repaitchart();
}
}
//用于生成随机静态图(测试目的)
私有静态双[]getRandomWalk(int numPoints){
double[]y=新的双精度[numPoints];
y[0]=0;
对于(int i=1;i
资源和我查看过的地方
:此网站帮助我创建了一个实时图形基类,但无法帮助将其集成到JPanel中,也无法帮助我通过repaint()或update()使其成为“实时”图形。并不是说必须使用repaint()或update()。我愿意接受几乎所有的建议

当前环境
-NetBeans IDE 8.2(用于GUI生成器)
-Java 1.8.0_111
-XChart JAR()

附加注释
我无法调用getRandomRealTimeGraph()来返回JPanel甚至XChartPanel,因此我可以将其添加到JTabbedPane。我会喜欢任何有帮助的建议

如果这有帮助的话,数据已经存在并且正在被解析为两个双精度数组。但就目前而言,我并不真正关心x数据和y数据。只要我以后能把它换掉,我对任何事情都满意


非常感谢你

好吧,你需要后退一大步,想想你想要实现什么,然后你需要弄清楚如何让它适用于一张图表,如果你能让它适用于一张图表,你应该能够调整它

从一个简单的模型概念开始。模型应该将数据抽象出来,这样不管数据来自文件、web服务、数据库、串行端口还是其他方式,解决方案的其他部分不应该关心,它们应该只关心以常见方式呈现的数据

类似于

public interface HeartMonitorModel {
    public List<Double>[] getSineData();
    public List<Double> getWalkData();
}
最后,我们需要把它全部展示出来

public class SeriesChartPane extends JPanel implements ChartMonitor {

    private HeartMonitorModel model;
    private XYChart chart;

    public SeriesChartPane(HeartMonitorModel model) {
        this.model = model;
        chart = new XYChartBuilder().width(400).height(200).title("Are you dead yet?").build();

        List<Double> walkData = model.getWalkData();
        chart.addSeries("Heart Rate", null, walkData);

        List<Double>[] sineData = model.getSineData();
        chart.addSeries("sine", sineData[0], sineData[1]);
        setLayout(new BorderLayout());

        XChartPanel<XYChart> chartPane = new XChartPanel<>(chart);
        add(chartPane);

        UpdateWorker worker = new UpdateWorker(this);
        worker.execute();
    }

    @Override
    public HeartMonitorModel getModel() {
        return model;
    }

    @Override
    public void updateData(List<Double>[] data) {
        chart.updateXYSeries("sine", data[0], data[1], null);
        repaint();
    }

}
查看和了解有关Swing和线程工作原理的更多详细信息


当true
循环有阻塞事件调度线程的危险时,您可能还需要对范式进行刷新,以防止UI更新。你可能想用一个SwingWorker或者一个Swing
定时器来执行更新-而且,你对MVC的想法有点离谱,没有更多的上下文,很难知道在哪里提供帮助,我的直觉是你的
Graph
类是错误的,除了做很多工作之外,它只处理一个图形。您要做的是将数据的管理与演示分离。当模型发生更新时,您希望触发对UI的请求以更新新数据。这可能需要您有多个模型,例如,您可能有“原始”模型,然后将其输入/更新图表模型,然后触发对UIHi的某种更新!非常感谢程序员提供的难以置信的详细帮助,以及对一切的解释和建议
public class DefaultHeartMonitorModel implements HeartMonitorModel {

    private double phase = 0;
    private int numPoints = 200;

    @Override
    public List[] getSineData() {
        phase += 2 * Math.PI * 2 / 20.0;
        List<Double> xData = new ArrayList<>(100);
        List<Double> yData = new ArrayList<>(100);
        for (int i = 0; i < 100; i++) {
            double radians = phase + (2 * Math.PI / 100 * i);
            xData.add(radians);
            yData.add(Math.sin(radians));
        }
        return new List[]{xData, yData};
    }

    @Override
    public List getWalkData() {
        List<Double> data = new ArrayList<>(numPoints);
        data.add(0.0);
        for (int i = 1; i < numPoints; i++) {
            double last = data.get(i - 1);
            data.add(last + + Math.random() - .5);
        }
        return data;
    }

}
public interface ChartMonitor {
    public HeartMonitorModel getModel();
    public void updateData(List<Double>[] data);
}
public class UpdateWorker extends SwingWorker<Void, List<Double>[]> {

    private ChartMonitor monitor;
    private XYChart chart;

    public UpdateWorker(ChartMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    protected Void doInBackground() throws Exception {
        while (true) {
            Thread.sleep(100);
            publish(monitor.getModel().getSineData());
        }
    }

    @Override
    protected void process(List<List<Double>[]> chunks) {
        for (List<Double>[] data : chunks) {
            monitor.updateData(data);
        }
    }

}
public class SeriesChartPane extends JPanel implements ChartMonitor {

    private HeartMonitorModel model;
    private XYChart chart;

    public SeriesChartPane(HeartMonitorModel model) {
        this.model = model;
        chart = new XYChartBuilder().width(400).height(200).title("Are you dead yet?").build();

        List<Double> walkData = model.getWalkData();
        chart.addSeries("Heart Rate", null, walkData);

        List<Double>[] sineData = model.getSineData();
        chart.addSeries("sine", sineData[0], sineData[1]);
        setLayout(new BorderLayout());

        XChartPanel<XYChart> chartPane = new XChartPanel<>(chart);
        add(chartPane);

        UpdateWorker worker = new UpdateWorker(this);
        worker.execute();
    }

    @Override
    public HeartMonitorModel getModel() {
        return model;
    }

    @Override
    public void updateData(List<Double>[] data) {
        chart.updateXYSeries("sine", data[0], data[1], null);
        repaint();
    }

}
public class HeartMonitor {

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

    public HeartMonitor() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                HeartMonitorModel model = new DefaultHeartMonitorModel();

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new SeriesChartPane(model));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}