Надо мне было вывести график по данным из БД (mysql), просто что бы периодически заглядывать. БД на домашнем компе. Решил воспользвоаться для рисования графиков javafx, воткнув ее в Swing Frame. Дело не хитрое, поколупался и вывел. Но был сильно удивлен тем, что javafx на раз роняет X server в ubuntu! Вот весь код примера.
package sleep;
import java.awt.EventQueue;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.effect.Shadow;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.web.HTMLEditor;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.BoxLayout;
import java.awt.Component;
import javax.swing.SwingConstants;
public class Graph {
private JFrame frame;
private static String uri;
private final static double AVG_INDEX = 60;
private String startTime, endTime;
private JFXPanel jfxp;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
uri = "jdbc:mysql://localhost:3306/motion";
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(1);
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Graph window = new Graph();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Graph() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
// frame.setSize(466, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JFXPanel jfx = new JFXPanel();
jfx.setSize(560, 300);
jfx.setLocation(10, 40);
// defining the axes
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Число минут с начала замера");
final AreaChart<String, Number> lineChart = new AreaChart<>(xAxis,
yAxis);
Series<String, Number> data = graph();
Series<String, Number> derives = derives(data);
lineChart.getData().add(data);
lineChart.getData().add(derives);
lineChart.setTitle("Начало замера: " + Graph.this.startTime
+ " Завершение замера: " + endTime);
Platform.runLater(new Runnable() {
@Override
public void run() {
// creating the chart
Scene scene = new Scene(lineChart, 400, 300);
jfx.setScene(scene);
}
});
JButton btnUpdate = new JButton("Update");
btnUpdate.setHorizontalAlignment(SwingConstants.LEADING);
btnUpdate.setAlignmentX(Component.CENTER_ALIGNMENT);
btnUpdate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
@Override
public void run() {
lineChart.getData().clear();
lineChart.getData().add(graph());
}
});
}
});
panel.add(btnUpdate);
JButton btnNewButton = new JButton("Truncate");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try (Connection con = DriverManager.getConnection(uri, "root",
"111"); Statement st = con.createStatement()) {
st.execute("TRUNCATE TABLE motions");
} catch (SQLException t) {
// TODO Auto-generated catch block
t.printStackTrace();
System.exit(1);
}
}
});
btnNewButton.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(btnNewButton);
frame.getContentPane().add(jfx, BorderLayout.CENTER);
}
private Series<String, Number> graph() {
// EXAMPLE CODE START
Series<String, Number> fluent = new XYChart.Series<>();
fluent.setName("Движения");
try (Connection con = DriverManager.getConnection(uri, "root",
"111");
Statement st = con.createStatement();
ResultSet rs = st
.executeQuery("SELECT time,UNIX_TIMESTAMP(time) as t,SECOND(time) as s,MINUTE(time) as m,pixels FROM motions ORDER BY time")) {
int init = 0;
int pixels = 0;
double avg = 0;
int lastSecond = 0;
int second = 0;
int lastMinute = 0;
int minute = 0;
while (rs.next()) {
if (init == 0) {
init = rs.getInt("t");
startTime = rs.getString("time");
}
second = rs.getInt("s");
pixels = rs.getInt("pixels");
avg = Math.max(avg, pixels);
if (lastSecond != second) {
minute = rs.getInt("m");
if (lastMinute != minute) {
double elapsedTime = rs.getInt("t") - init;
elapsedTime /= AVG_INDEX;
XYChart.Data<String, Number> data = new XYChart.Data<String, Number>(
Integer.toString((int) Math.floor(elapsedTime)),
avg);
Rectangle r = new Rectangle();
r.setWidth(5);
r.setHeight(5);
r.setArcWidth(2);
r.setArcHeight(2);
r.setFill(Color.BLUE);
data.setNode(r);
fluent.getData().add(data);
avg = 0;
lastMinute = minute;
endTime = rs.getString("time");
}
lastSecond = second;
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(1);
}
return fluent;
}
private Series<String, Number> derives(Series<String, Number> series) {
Series<String, Number> derive = new XYChart.Series<>();
derive.setName("Производные");
int last = 0;
for (XYChart.Data element : series.getData()) {
XYChart.Data<String, Number> data = new XYChart.Data<String, Number>(
String.valueOf((int) element.getXValue()),
(int) element.getYValue());
derive.getData().add(data);
}
return derive;
}
}
Причем происходит это в самые разные моменты. Например было, что в свинговой кнопке, код слушателя обращался к БД выполняя запрос и иксы падали! И еще множество вариантов. Пробовал ставить дрова от нвидии 325 и 304, в обоих случаях результат один, сегфолты типа:
202.491] (EE)
[ 202.491] (EE) Backtrace:
[ 202.491] (EE) 0: /usr/bin/X (xorg_backtrace+0x36) [0x7f4a84853516]
[ 202.491] (EE) 1: /usr/bin/X (0x7f4a846a3000+0x1b4359) [0x7f4a84857359]
[ 202.491] (EE) 2: /lib/x86_64-linux-gnu/libpthread.so.0 (0x7f4a837a6000+0xfbd0) [0x7f4a837b5bd0]
[ 202.491] (EE) 3: /usr/lib/x86_64-linux-gnu/libpixman-1.so.0 (pixman_region_intersect+0x24) [0x7f4a83358034]
[ 202.491] (EE) 4: /usr/lib/xorg/modules/drivers/intel_drv.so (0x7f4a80f37000+0x5667f) [0x7f4a80f8d67f]
[ 202.491] (EE) 5: /usr/bin/X (0x7f4a846a3000+0x132d35) [0x7f4a847d5d35]
[ 202.491] (EE) 6: /usr/bin/X (0x7f4a846a3000+0x58af1) [0x7f4a846fbaf1]
[ 202.491] (EE) 7: /usr/bin/X (0x7f4a846a3000+0x475aa) [0x7f4a846ea5aa]
[ 202.491] (EE) 8: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xf5) [0x7f4a823f2ea5]
[ 202.491] (EE) 9: /usr/bin/X (0x7f4a846a3000+0x478f1) [0x7f4a846ea8f1]
[ 202.491] (EE)
[ 202.491] (EE) Segmentation fault at address 0x29
[ 202.491]
Fatal server error:
[ 202.491] Caught signal 11 (Segmentation fault). Server aborting
[ 202.491]
[ 202.491] (EE)
Please consult the The X.Org Foundation support
at http://wiki.x.org
for help.
Ядро 3.11 и 3.10 оба на х64 ОС ubuntu 13.04 Ява из репов. Код примера не дописан, но этот код при запуске стабильно роняет иксы у меня. Были и другие варианты падений.
Вот такие пироги.