How to embed processing into java.awt based gui
in
Integration and Hardware
•
2 years ago
Dear all,
I am using Processing as a standalone library inside a pure Java app. I have two classes - on is a Processing sketch responsible for drawing, other is an awt based GUI.
I would love to be able to call the processing sketch from within the gui upon a "Print" JButton click, but my current implementation causes null pointer exception. Here is my code for the Processing part so far:
Obviously the problem lies in communicating the filename string to setup method in Segments class (the part in bold that makes a call to RCallerReadNexus class). I have no other ideas as of how to proceed from here.
Sincerely, f
I am using Processing as a standalone library inside a pure Java app. I have two classes - on is a Processing sketch responsible for drawing, other is an awt based GUI.
I would love to be able to call the processing sketch from within the gui upon a "Print" JButton click, but my current implementation causes null pointer exception. Here is my code for the Processing part so far:
- // TODO
// add more grey space in the bottom
// allow for mirroring in y axis
package app;
import SimplePostscript.SimplePostscript;
import java.util.logging.Level;
import java.util.logging.Logger;
import processing.core.PApplet;
import processing.core.PFont;
public class Segments extends PApplet {
private static final long serialVersionUID = 1L;
RCallerReadNexus ReadNexus;
private SimplePostscript ps;
float[][] data;
float[][] labelPos;
String[] labels;
float dataMin, dataMax;
// For corners of the plot
float plotX1, plotY1;
float plotX2, plotY2;
// Parse from GUI
String RScriptpath = "/usr/local/bin/Rscript";
// White space
int HorMargin = 30; // <-->
int VertMargin = 40; // /\ \/
// Axis intervals (make it generic)
double IntervalMajor = 50; // 10
double IntervalMinor = 25; // 5
// Font size:
int fontSize = 11;
// Generate Eps output?
boolean getEps = true;
// Extra space for tree labels (make it generic)
int ShiftToRight = 150; // 57
public void ReadNexus(String filename) {
ReadNexus = new RCallerReadNexus(filename, RScriptpath);
}
public void setup() {
try {
size(900, 700); // width, height
hint(ENABLE_NATIVE_FONTS);
data = ReadNexus.getData();
labels = ReadNexus.getLabels();
labelPos = ReadNexus.getlabelsPos();
// Calculate the min and max
dataMin = ceil(RCallerReadNexus.getDataMin());
dataMax = ceil(RCallerReadNexus.getDataMax());
// wont generate png without:
noLoop();
// Corners of the plot
plotX1 = HorMargin + ShiftToRight; // <-->
plotX2 = width - plotX1 - ShiftToRight;
plotY1 = VertMargin; // /\ \/
plotY2 = height - plotY1;
// Post script
if (getEps) {
ps = new SimplePostscript(this);
ps.open("segments.eps", plotX1 - HorMargin,
plotY1 - VertMargin, plotX2 + HorMargin + ShiftToRight,
plotY2 + VertMargin);
}
PFont plotFont = createFont("Arial", 12);
doTextFont(plotFont);
} catch (Exception ex) {
Logger.getLogger(Segments.class.getName()).log(Level.SEVERE, null,
ex);
}
}
@Override
public void draw() {
try {
drawPlotArea();
drawHorGrid();
DrawVertGrid();
drawTree();
drawTreeLabels();
drawAxisLabels();
if (getEps) {
ps.close();
}
saveFrame("segments.png");
ReadNexus.saveData("Data.data");
ReadNexus.saveLabelsAndLabPos("LabelsAndLabPos.data");
} // END: try
catch (Exception ex) {
Logger.getLogger(Segments.class.getName()).log(Level.SEVERE, null,
ex);
}
}// END: draw
void drawHorGrid() {
boolean HorizPanelGridMajor = true;
boolean HorizPanelGridMinor = true;
for (float v = dataMin; v <= dataMax + ShiftToRight; v += IntervalMinor) {
if (v % IntervalMinor == 0) { // If Interval
float x = map(v, dataMin, dataMax, plotX1, plotX2);
if (v % IntervalMajor == 0) { // If Major Interval
if (HorizPanelGridMajor) {
// Draw major vertical grid
// Use same color as background
doStroke(255, 255, 255);
doStrokeWeight(2);
doLine(x, plotY1, x, plotY2);
}
} else if (HorizPanelGridMinor) {
// Draw minor vertical grid
// Use same color as background
doStroke(255, 255, 255);
doStrokeWeight(1);
doLine(x, plotY1, x, plotY2);
}
}
}
}// End: drawHorGrid
void DrawVertGrid() {
boolean VertPanelGridMajor = true;
boolean VertPanelGridMinor = true;
for (float v = dataMin; v <= dataMax; v += IntervalMinor) {
if (v % IntervalMinor == 0) { // if Interval
float y = map(v, dataMin, dataMax, plotY1, plotY2);
if (v % IntervalMajor == 0) { // If Major Interval
if (VertPanelGridMajor) {
// Draw the major horizontal grid
// Use same color as background
doStroke(255, 255, 255);
doStrokeWeight(2);
doLine(plotX1, y, plotX2 + ShiftToRight, y);
}
} else if (VertPanelGridMinor) {
doStroke(255, 255, 255);
doStrokeWeight(1);
doLine(plotX1, y, plotX2 + ShiftToRight, y);
}
}
}
}// End: drawVertGrid
void drawTree() {
doStrokeWeight(2);
doStroke(95, 95, 227); // blue
int rowCount = data.length;
for (int row = 0; row < rowCount; row++) {
float x0 = map(data[row][0], dataMin, dataMax, plotX1, plotX2);
float y0 = map(data[row][1], dataMin, dataMax, plotY1, plotY2);
float x1 = map(data[row][2], dataMin, dataMax, plotX1, plotX2);
float y1 = map(data[row][3], dataMin, dataMax, plotY1, plotY2);
doLine(x0, y0, x1, y1);
}
}
void drawTreeLabels() {
doFill(0, 0, 0); // black
smooth();
textSize(fontSize);
textAlign(CENTER, CENTER);
int rowCount = labels.length;
for (int row = 0; row < rowCount; row++) {
String label = labels[row];
float x0 = map(labelPos[row][0], dataMin, dataMax, plotX1, plotX2);
float y0 = map(labelPos[row][1], dataMin, dataMax, plotY1, plotY2);
// do the shift smarter
doText(label, x0, y0, 35, -1); // 35, -1 <-->, /\\/
}
}
// Shift the origin (0,0) to the lower-left corner (mirroring the y axis)
void ShiftOrigin() {
doTranslate(0, height);
doScale(1, -1); // 1, -1
}
void drawPlotArea() {
// White background
background(255, 255, 255);
// Show the plot area as a grey box
doFill(225, 225, 225);
rectMode(CORNERS);
noStroke();
doRect(plotX1, plotY1, plotX2 + ShiftToRight, plotY2);
}
// TODO
// In eps output labels are shifted to the right
void drawAxisLabels() {
doFill(0, 0, 0);
smooth();
textSize(fontSize);
textAlign(CENTER, CENTER);
// This is stupid
for (float v = dataMin; v <= dataMax + ShiftToRight / 6; v += IntervalMinor) {
// This wont draw the last label
// for (float v = dataMin; v <= dataMax; v += IntervalMinor) {
if (v % IntervalMajor == 0) { // If a major tick mark
float x = map(v, dataMin, dataMax, plotX1, plotX2);
doText(String.valueOf((int) v), x, plotY2, 0, 10); // 0, 10
// <-->,
// /\\/
}
}
}
void doFill(float r, float g, float b) {
fill(r, g, b);
if (getEps) {
ps.setrgb((int) r, (int) g, (int) b);
}
}
void doStroke(float r, float g, float b) {
stroke(r, g, b);
if (getEps) {
ps.setrgb((int) r, (int) g, (int) b);
}
}
void doStrokeWeight(float width) {
strokeWeight(width);
if (getEps) {
ps.setlinewidth(width);
ps.stroke();
}
}
void doLine(float x1, float y1, float x2, float y2) {
line(x1, y1, x2, y2);
if (getEps) {
ps.moveto(x1, y1);
ps.lineto(x2, y2);
ps.stroke();
}
}
void doRect(float x1, float y1, float x2, float y2) {
rect(x1, y1, x2, y2);
if (getEps) {
ps.rect(x1, y1, x2, y2);
ps.fill();
}
}
void doTranslate(float x, float y) {
translate(x, y);
if (getEps) {
ps.translate(x, y);
}
}
void doScale(float x, float y) {
scale(x, y);
if (getEps) {
ps.scale(x, y);
}
}
void doText(String label, float x0, float y0, int moveTextHor,
int moveTextVert) {
text(label, x0 + moveTextHor, y0 + moveTextVert);
if (getEps) {
ps.text(x0 + moveTextHor / 10, y0 + moveTextVert + 4, label);// /10,
// +4
}
}
void doTextFont(PFont plotFont) {
textFont(plotFont);
if (getEps) {
ps.setfont(String.valueOf(plotFont), fontSize);
}
}
}// END: Main
- package app;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JSeparator;
public class AppGui {
public String filename;
private Segments segments;
// Initialize all swing objects
// Frame
private JFrame Frame = new JFrame("Segments v4.0"); // create Frame
// Buttons with options
private JButton New = new JButton("New");
private JButton Open = new JButton("Open");
private JButton Close = new JButton("Close");
private JButton Print = new JButton("Print");
private JSeparator Separator = new JSeparator(JSeparator.VERTICAL);
private JButton Help = new JButton("Help");
private JButton Quit = new JButton("Quit");
// Menu
private JMenuBar mb = new JMenuBar(); // Menubar
/** Constructor for the GUI */
public AppGui() {
segments = new Segments();
// Set menubar
Frame.setJMenuBar(mb);
// Build Menus
mb.add(New); // Create Quit line
mb.add(Open);
mb.add(Close);
mb.add(Print);
mb.add(Separator);
mb.add(Help);
mb.add(Quit);
// Setup Main Frame
Frame.getContentPane().setLayout(new BorderLayout());
// Allows the Swing App to be closed
Frame.addWindowListener(new ListenCloseWdw());
// Add processing PApplet
segments.init();
Frame.add(segments);
// Add Menu listeners
Quit.addActionListener(new ListenMenuQuit());
Open.addActionListener(new ListenMenuOpen());
Print.addActionListener(new ListenMenuPrint());
}
public class ListenMenuQuit implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public class ListenMenuOpen implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(chooser);
File file = chooser.getSelectedFile();
filename = file.getAbsolutePath();
}
}
public class ListenMenuPrint implements ActionListener {
public void actionPerformed(ActionEvent e) {
segments.ReadNexus(filename);
}
}
public class ListenCloseWdw extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
public void launchFrame() {
// Display Frame
Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Frame.pack(); // Adjusts panel to components for display
Frame.setVisible(true);
}
public static void main(String args[]) {
AppGui gui = new AppGui();
gui.launchFrame();
}
}
Obviously the problem lies in communicating the filename string to setup method in Segments class (the part in bold that makes a call to RCallerReadNexus class). I have no other ideas as of how to proceed from here.
Sincerely, f
1