yes perfectly got it ,thank you
i have tried to draw graph , somehow i got success
import processing.serial.*;
Serial port;
ArrayList<PVector> dataPoints;
float graphX; // X-coordinate of the graph
float graphY; // Y-coordinate of the graph
float graphWidth; // Width of the graph
float graphHeight;
// x axis label range
int xMin = 0;
int xMax = 100;
int xStep = 10;
// y axis label range
int yMin = 0;
int yMax = 5;
int yStep = 1;
void setup() {
size(750, 500); // Set the size of the window
graphX = width * 0.2; // Set the initial X-coordinate of the graph
graphY = height * 0.8; // Set the initial Y-coordinate of the graph
graphWidth = width * 0.6; // Width of the graph
graphHeight = height * 0.6; // Height of the graph
printArray(Serial.list()); // Print available serial ports in the console
port = new Serial(this, "COM3", 9600); // Replace "COM3" with the appropriate port name
port.bufferUntil('\n'); // Set the character to buffer until newline
// Initialize data points list
dataPoints = new ArrayList<PVector>();
}
void draw() {
background(255); // Set the background color to white
// Set the stroke color and weight for axes and origin
stroke(0); // Set the stroke color to black
strokeWeight(1); // Set the stroke weight to 1
// Update the position of the graph based on mouse movement
if (mousePressed) {
graphX += mouseX - pmouseX; // Update the X-coordinate of the graph based on mouse movement on the X-axis
graphY += mouseY - pmouseY; // Update the Y-coordinate of the graph based on mouse movement on the Y-axis
}
// Draw the x-axis
line(graphX, graphY, graphX + graphWidth, graphY);
// Draw the arrowhead at the end of the x-axis
float arrowSize = 8; // Size of the arrowhead
triangle(graphX + graphWidth - arrowSize, graphY - arrowSize/2,
graphX + graphWidth - arrowSize, graphY + arrowSize/2,
graphX + graphWidth, graphY);
// Draw the x-axis label
textAlign(RIGHT);
fill(0);
text("Angle(θ)", graphX + graphWidth/2 + 24, graphY + 42);
// Draw the y-axis
line(graphX, graphY, graphX, graphY - graphHeight);
// Draw the arrowhead at the end of the y-axis
triangle(graphX - arrowSize/2, graphY - graphHeight + arrowSize,
graphX + arrowSize/2, graphY - graphHeight + arrowSize,
graphX, graphY - graphHeight);
// Draw the "h_dot" label on the y-axis
textAlign(RIGHT);
fill(0);
text("Velocity of Mechanism (m/s)", graphX - 25, graphY - graphHeight +152);
// Draw the origin O(0,0)
fill(255, 0, 0);
noStroke();
float originSize = 10;
ellipse(graphX, graphY, originSize, originSize);
// Write x-axis values
textAlign(CENTER);
fill(0);
stroke(0);
for (int i = xMin; i <= xMax; i += xStep) {
float xPos = map(i, xMin, xMax, graphX, graphX + graphWidth );
line(xPos, graphY, xPos, graphY + 8);
text(i, xPos, graphY + 25);
int numSubDivisions = 10; // Number of smaller divisions within each major division
float majorDivisionWidth = graphWidth / (float)(xMax - xMin) * xStep;
float subDivisionWidth = majorDivisionWidth / numSubDivisions;
for (int j = 0; j < numSubDivisions; j++) {
float subXPos = xPos + (j * subDivisionWidth);
if (subXPos < graphX + graphWidth ) {
line(subXPos, graphY, subXPos, graphY + 4);
}
}
}
// Write y-axis values
textAlign(RIGHT, CENTER);
fill(0);
stroke(0);
for (int i = yMin; i <= yMax; i += yStep) {
float yPos = map(i, yMin, yMax, graphY, graphY - graphHeight);
line(graphX - 8, yPos, graphX, yPos);
text(i, graphX - 12, yPos);
int numSubDivisions = 10; // Number of smaller divisions within each major division
float majorDivisionWidth = graphHeight / (float)(yMax - yMin) * yStep;
float subDivisionWidth = majorDivisionWidth / numSubDivisions;
for (int k = 0; k < numSubDivisions; k++) {
float subYPos = yPos + (k * subDivisionWidth);
if (graphY > subYPos) {
line(graphX - 4, subYPos, graphX, subYPos );
}
}
}
// Draw data points
noFill();
stroke(0, 0, 255);
for (int i = 1; i < dataPoints.size(); i++) {
PVector prevPoint = dataPoints.get(i - 1);
PVector point = dataPoints.get(i);
float prevX = map(prevPoint.x, xMin, xMax, graphX, graphX + graphWidth);
float prevY = map(prevPoint.y, yMin, yMax, graphY, graphY - graphHeight);
float x = map(point.x, xMin, xMax, graphX, graphX + graphWidth);
float y = map(point.y, yMin, yMax, graphY, graphY - graphHeight);
line(prevX, prevY, x, y);
}
// Draw latest point
if (dataPoints.size() > 0) {
PVector latestPoint = dataPoints.get(dataPoints.size() - 1);
float x = map(latestPoint.x, xMin, xMax, graphX, graphX + graphWidth);
float y = map(latestPoint.y, yMin, yMax, graphY, graphY - graphHeight);
fill(255, 0, 0);
ellipse(x, y, 8, 8);
}
}
void serialEvent(Serial port) {
String data = port.readStringUntil('\n'); // Read the received data until newline character
if (data != null) {
data = data.trim();
println("Data received: " + data);
// Parse the data string
int commaIndex = data.indexOf(',');
if (commaIndex != -1) {
String angleStr = data.substring(0, commaIndex);
String hDotStr = data.substring(commaIndex + 1);
// Convert the parsed values to floats
float angle = float(angleStr);
float h_dot = float(hDotStr);
// Create a PVector with angle and h_dot values
PVector point = new PVector(angle, h_dot);
// Add the point to the data points list
dataPoints.add(point);
// Print the parsed values
println("Parsed Angle: " + angle);
println("Parsed h_dot: " + h_dot);
}
}
}
there is a problem that pink circle should follow the exact path before and after drawing happen , but the graph is not clear , like lot of lines , please can you see this .Thank you very much
Some observations:
-
Is that a red dot overlying the xAxis arrow? Iâm not sure you really need those arrows. The values are clearly increasing on both axes.
-
What is the significance of the red dots? If they are data points, why do we only see two of them?
like lot of lines
3) I see multiple (more than one) blue lines. In the draw() function I do not see code for redrawing the background. Commonly data is recorded left to right with the x value incremented with time. When the data reaches the right side of the graph, the background is redrawn, thereby erasing the old data, and new data resumes being plotted left to right. In your case, you might not want to erase the entire graph and re-draw everything. An alternative would be to refresh the background only on the plot area, sparing the axes and labels. Either method should eliminate multiple data lines.
the red dot i will remove it , since the mechanism moving up and down continuosuly so the graph once generated , it should be same till mechanism stopped ,the pink dot on graph just to show path
i have create button which will generate table , it is tested and work well , however i want to have separate window for table , please guide
thankyou
import processing.serial.*;
import processing.core.PFont; // Import PFont for setting the font
Serial port;
ArrayList<PVector> dataPoints;
float graphX; // X-coordinate of the graph
float graphY; // Y-coordinate of the graph
float graphWidth; // Width of the graph
float graphHeight;
// x axis label range
int xMin = 0;
int xMax = 100;
int xStep = 10;
// y axis label range
int yMin = 0;
int yMax = 5;
int yStep = 1;
PFont boldFont; // Declare a variable for the bold font
Button generateButton;
float buttonX;
float buttonY;
boolean showTable;
Table dataTable;
void setup() {
size(750, 500); // Set the size of the window
buttonX = graphX + graphWidth + 300;
buttonY = graphY - graphHeight + 20;
graphX = width * 0.2; // Set the initial X-coordinate of the graph
graphY = height * 0.8; // Set the initial Y-coordinate of the graph
graphWidth = width * 0.6; // Width of the graph
graphHeight = height * 0.6; // Height of the graph
printArray(Serial.list()); // Print available serial ports in the console
port = new Serial(this, "COM5", 9600); // Replace "COM3" with the appropriate port name
port.bufferUntil('\n'); // Set the character to buffer until newline
// Initialize data points list
dataPoints = new ArrayList<PVector>();
// Load a bold font
boldFont = createFont("Arial Bold", 12); // Replace "Arial Bold" with the name of your desired bold font
// Create generate button
generateButton = new Button("Generate Table", 50, 50, 120, 30);
showTable = false;
}
void draw() {
background(255); // Set the background color to white
// Set the stroke color and weight for axes and origin
stroke(0); // Set the stroke color to black
strokeWeight(1); // Set the stroke weight to 1
generateButton.display();
// Update the position of the graph based on mouse movement
if (mousePressed) {
graphX += mouseX - pmouseX; // Update the X-coordinate of the graph based on mouse movement on the X-axis
graphY += mouseY - pmouseY; // Update the Y-coordinate of the graph based on mouse movement on the Y-axis
}
// Draw the x-axis
line(graphX, graphY, graphX + graphWidth, graphY);
// Draw the arrowhead at the end of the x-axis
float arrowSize = 8; // Size of the arrowhead
triangle(graphX + graphWidth - arrowSize, graphY - arrowSize/2,
graphX + graphWidth - arrowSize, graphY + arrowSize/2,
graphX + graphWidth, graphY);
textAlign(RIGHT);
fill(0);
textFont(boldFont); // Set the text font to bold
textSize(12); // Set the font size for "Angle"
text("Angle(θ)", graphX + graphWidth/2 + 24, graphY + 42);
// Draw the y-axis
line(graphX, graphY, graphX, graphY - graphHeight);
// Draw the arrowhead at the end of the y-axis
triangle(graphX - arrowSize/2, graphY - graphHeight + arrowSize,
graphX + arrowSize/2, graphY - graphHeight + arrowSize,
graphX, graphY - graphHeight);
textAlign(RIGHT);
fill(0);
textFont(boldFont); // Set the text font to bold
textSize(12); // Set the font size for "Velocity of Mechanism"
text("Velocity of Mechanism (m / s)", graphX - 25, graphY - graphHeight + 152);
// Write x-axis values
textAlign(CENTER);
fill(0);
stroke(0);
for (int i = xMin; i <= xMax; i += xStep) {
float xPos = map(i, xMin, xMax, graphX, graphX + graphWidth );
line(xPos, graphY, xPos, graphY + 8);
text(i, xPos, graphY + 25);
int numSubDivisions = 10; // Number of smaller divisions within each major division
float majorDivisionWidth = graphWidth / (float)(xMax - xMin) * xStep;
float subDivisionWidth = majorDivisionWidth / numSubDivisions;
for (int j = 0; j < numSubDivisions; j++) {
float subXPos = xPos + (j * subDivisionWidth);
if (subXPos < graphX + graphWidth ) {
line(subXPos, graphY, subXPos, graphY + 4);
}
}
}
// Write y-axis values
textAlign(RIGHT, CENTER);
fill(0);
stroke(0);
for (int i = yMin; i <= yMax; i += yStep) {
float yPos = map(i, yMin, yMax, graphY, graphY - graphHeight);
line(graphX - 8, yPos, graphX, yPos);
text(i, graphX - 12, yPos);
int numSubDivisions = 10; // Number of smaller divisions within each major division
float majorDivisionWidth = graphHeight / (float)(yMax - yMin) * yStep;
float subDivisionWidth = majorDivisionWidth / numSubDivisions;
for (int k = 0; k < numSubDivisions; k++) {
float subYPos = yPos + (k * subDivisionWidth);
if (graphY > subYPos) {
line(graphX - 4, subYPos, graphX, subYPos );
}
}
}
// Draw latest point
if (dataPoints.size() > 0) {
PVector latestPoint = dataPoints.get(dataPoints.size() - 1);
float x = map(latestPoint.x, xMin, xMax, graphX, graphX + graphWidth);
float y = map(latestPoint.y, yMin, yMax, graphY, graphY - graphHeight);
fill(255, 0, 0);
ellipse(x, y, 8, 8);
}
// Draw data points
noFill();
stroke(0, 0, 255);
for (int i = 1; i < dataPoints.size(); i++) {
PVector prevPoint = dataPoints.get(i - 1);
PVector point = dataPoints.get(i);
float prevX = map(prevPoint.x, xMin, xMax, graphX, graphX + graphWidth);
float prevY = map(prevPoint.y, yMin, yMax, graphY, graphY - graphHeight);
float x = map(point.x, xMin, xMax, graphX, graphX + graphWidth);
float y = map(point.y, yMin, yMax, graphY, graphY - graphHeight);
line(prevX, prevY, x, y);
}
// Display table if showTable is true
if (showTable) {
drawTable();
}
}
void serialEvent(Serial port) {
String data = port.readStringUntil('\n'); // Read the received data until newline character
if (data != null) {
data = data.trim();
println("Data received: " + data);
// Parse the data string
int commaIndex = data.indexOf(',');
if (commaIndex != -1) {
String angleStr = data.substring(0, commaIndex);
String hDotStr = data.substring(commaIndex + 1);
// Convert the parsed values to floats
float angle = float(angleStr);
float h_dot = float(hDotStr);
// Create a PVector with angle and h_dot values
PVector point = new PVector(angle, h_dot);
// Add the point to the data points list
dataPoints.add(point);
// Print the parsed values
println("Parsed Angle: " + angle);
println("Parsed h_dot: " + h_dot);
}
}
}
void mousePressed() {
if (generateButton.isClicked()) {
generateTable();
showTable = true;
}
}
void generateTable() {
dataTable = new Table();
dataTable.addColumn("Angle");
dataTable.addColumn("Velocity of Mechanism");
for (PVector point : dataPoints) {
TableRow row = dataTable.addRow();
float mappedAngle = map(point.x, graphX, graphX + graphWidth, xMin, xMax);
row.setFloat("Angle", mappedAngle);
row.setFloat("Velocity of Mechanism", point.y);
}
}
void drawTable() {
float tableX = 50;
float tableY = 100;
float columnWidth = 100;
float rowHeight = 30;
fill(255);
stroke(0);
rect(tableX, tableY, columnWidth * 2, rowHeight);
textAlign(CENTER, CENTER);
fill(0);
textFont(boldFont);
textSize(12);
float headerX = tableX + columnWidth / 2;
float headerY = tableY + rowHeight / 2;
text("Angle (θ)", headerX, headerY);
text("Velocity of Mechanism", headerX + columnWidth, headerY);
for (int i = 0; i < dataTable.getRowCount(); i++) {
TableRow row = dataTable.getRow(i);
float rowX = tableX;
float rowY = tableY + rowHeight * (i + 1);
float mappedAngle = row.getFloat("Angle");
float angleDegrees = map(mappedAngle, xMin, xMax, graphX, graphX + graphWidth);
text(nf(angleDegrees, 0, 2), rowX + columnWidth / 2, rowY + rowHeight / 2);
text(nf(row.getFloat("Velocity of Mechanism"), 0, 2), rowX + columnWidth * 1.5, rowY + rowHeight / 2);
}
}
class Button {
String label;
float x, y, width, height;
Button(String label, float x, float y, float width, float height) {
this.label = label;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
void display() {
// Draw button
rectMode(CORNER);
fill(200);
stroke(0);
rect(buttonX, buttonY, width, height);
// Draw label
textAlign(CENTER, CENTER);
fill(0);
textFont(boldFont);
textSize(12);
text(label, buttonX + width / 2, buttonY + height / 2);
}
boolean isClicked() {
return mouseX >= buttonX && mouseX <= buttonX + width && mouseY >= buttonY && mouseY <= buttonY + height;
}
}
As far as a separate window goes you could a) use a class which extends PApplet or b) add a separate JFrame window to the default Processing window. Do you want the window to be shown all the time or only when the generate table button is pressed? Have you considered the length of that table? It could run into the thousands of data points depending on how long the user waits to hit the button. Youâre not going to be able to get a window long enough to show all the data. Otherwise, you would need a table with a vertical scrollbar to display the data in a conventional sized window. The other option would be to not to show all the data but only the last 32 points (or similar limitation), depending on window size.
the rows should be 18 , columns 2 , and when i press button the table should pop out , right now both windows in same spot thats why do not good looking
Another option would be to widen out your main window and print the data over to the right; itâs only two columns. You could print the data into a rectangle (with or without colored fill) to make it stand out. If you used a separate JFrame window you would probably have to use a JTable on a separate thread. If you used a separate class which extends PApplet you could likely use the same table, but when the user closed the second window I believe it will also close the main window. It might be easier to experiment with the different options in a separate project until you figure out which method you prefer.
thats perfect idea going to try this
i can not make separate window for generate table , please can you guide me
One possibility is to make a hybrid window: part with JFrame and JTable and part with default AWT canvas so that you can still use draw():
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
javax.swing.JFrame frame;
java.awt.Canvas canvas;
int _wndW = 700;
int _wndH = 600;
void table(int x, int y, int w, int h) {
String data[][] = {
{"Boat", "Yellow"},
{"Car", "Magenta"},
{"House", "White"}
};
String header[] = {"ITEM", "COLOR"};
JTable table = new JTable(data, header);
table.setSelectionForeground(Color.WHITE);
JScrollPane scrlPane = new JScrollPane(table);
scrlPane.setBounds(x, y, w, h);
frame.add(scrlPane);
// **** Listener **** //
ListSelectionModel cellSelectionModel = table.getSelectionModel();
cellSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cellSelectionModel.addListSelectionListener(new ListSelectionListener() {
void valueChanged(ListSelectionEvent evnt) {
String selectedData = null;
int[] selectedRow = table.getSelectedRows();
int[] selectedColumns = table.getSelectedColumns();
for (int i = 0; i < selectedRow.length; i++) {
for (int j = 0; j < selectedColumns.length; j++) {
selectedData = (String) table.getValueAt(selectedRow[i], selectedColumns[j]);
println(selectedData);
}
}
}
}
);
}
void buildWnd() {
table(10, 10, 130, _wndH - 50);
}
void setup() {
size(_wndW, _wndH);
surface.setTitle("Swing JFrame Components with Default AWT Canvas");
frame = (javax.swing.JFrame) ((processing.awt.PSurfaceAWT.SmoothCanvas) surface.getNative()).getFrame();
canvas = (processing.awt.PSurfaceAWT.SmoothCanvas) ((processing.awt.PSurfaceAWT)surface).getNative();
frame.setBounds(600, 150, _wndW, _wndH); // Makes it possible to add swing components
canvas.setBounds(150, 0, _wndW - 150, _wndH); // Default canvas used for draw()
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
buildWnd(); // Builds components on EventDispatchThread
}
}
);
}
void draw() {
background(209);
fill(color(255, 0, 0));
stroke(0);
strokeWeight(4.0);
circle(250, 255, 200);
}
Second option is to create separate windows: one default Processing window and other JFrame window that you could add a JTable to. Can post this code later if you decide to go that way.
i would like to go for separate window please
Source code for default Processing window and auxillary JFrame window with JTable. Not sure about EventDispatchThread for Swing component, but since weâre only using one component may be able to get by without it.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import controlP5.*;
ControlP5 cp5;
JFrame frame;
int _wndW = 600;
int _wndH = 600;
void table(int x, int y, int w, int h) {
String data[][] = {
{"Boat", "Yellow"},
{"Car", "Magenta"},
{"House", "White"}
};
String header[] = {"ITEM", "COLOR"};
JTable table = new JTable(data, header);
table.setSelectionForeground(Color.WHITE);
JScrollPane scrlPane = new JScrollPane(table);
scrlPane.setBounds(x, y, w, h);
frame.add(scrlPane);
// **** Listener **** //
ListSelectionModel cellSelectionModel = table.getSelectionModel();
cellSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cellSelectionModel.addListSelectionListener(new ListSelectionListener() {
void valueChanged(ListSelectionEvent evnt) {
String selectedData = null;
int[] selectedRow = table.getSelectedRows();
int[] selectedColumns = table.getSelectedColumns();
for (int i = 0; i < selectedRow.length; i++) {
for (int j = 0; j < selectedColumns.length; j++) {
selectedData = (String) table.getValueAt(selectedRow[i], selectedColumns[j]);
println(selectedData);
}
}
}
}
);
}
void setup() {
size(_wndW, _wndH); // default window
surface.setTitle("Default Window");
cp5 = new ControlP5(this);
cp5.addButton("showWnd")
.setLabel("Show JFrame")
.setPosition(30, 10)
.setSize(120, 24)
;
// Auxillary window for table
frame = new JFrame("JFrame Demo");
frame.setBounds(500, 300, 300, 350);
frame.setVisible(false); // Don't show initially
}
void draw() {
fill(0, 255, 0);
circle( width/2, height/2, 300);
}
void showWnd() {
frame.setVisible(true);
table(10, 10, 130, 200);
}
this is also good
âOne possibility is to make a hybrid window: part with JFrame and JTable and part with default AWT canvas so that you can still use draw():â
please can you tell how can i manage this code in my code
Draw your graph in the default canvas with draw() just like before. Put the table data into the table (it has a scrollbar when it gets full so should hold a lot of data). You may have to read about how to populate a JTable with your data.
i should draw in original code or make new code in processing ?
import javax.swing.JFrame;
import javax.swing.JTable;
JFrame frame;
JTable table;
void setup() {
size(700, 500);
frame = new JFrame("Table");
String[] columnNames = {"Angle", "Velocity of Mechanism"};
Object[][] data = { { 0, 0 }, { 10, 1 }, { 20, 2 }, { 30, 3 }, { 40, 4 }, { 50, 5 } };
table = new JTable(data, columnNames);
frame.add(table.getTableHeader());
frame.add(table);
frame.pack();
frame.setVisible(true);
}
void draw() {
background(255);
// Draw everything as usual
// ...
// Get the data from the JTable and update the Processing sketch
for (int i = 0; i < dataPoints.size(); i++) {
TableRow row = dataTable.getRow(i);
float mappedAngle = row.getFloat("Angle");
float angleDegrees = map(mappedAngle, xMin, xMax, graphX, graphX + graphWidth);
float velocity = row.getFloat("Velocity of Mechanism");
// Use the data to draw something on the Processing canvas
// ...
}
}
is this fine , please check
Iâm unable to run your demo. The two examples that I posted is called âboilerplateâ code and is the base code for whatever you are going to add on top of it. Pick one of the examples and add your previous working graph code to it. The circle code in draw() can be deleted. It was used just to show that you can use standard Processing graphics and donât need Java graphics code. Your previous code should work just fine and you donât need to write anything new for the graphics. Where you could have problems is populating the JTable because this will be new for you.
yes sure thank you very much going to try it now JTable