here is my code
public class SimpleJoglApp extends JFrame {
public static void main(String[] args) {
final SimpleJoglApp app = new SimpleJoglApp();
// show what we've done
SwingUtilities.invokeLater(new Runnable() {
public void run() {
app.setVisible(true);
}
});
}
public SimpleJoglApp() {
// set the JFrame title
super("Test App");
// kill the process when the JFrame is closed
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// only two JOGL lines of code ... and here they are
GLCanvas glcanvas = new GLCanvas();
glcanvas.addGLEventListener(new SecondGLEventListener());
// add the GLCanvas just like we would any Component
getContentPane().add("Center", glcanvas);
setSize(500, 300);
}
public void centerWindow(Component frame) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
frame.setLocation((screenSize.width - frameSize.width) >> 1, (screenSize.height - frameSize.height) >> 1);
}
public class SecondGLEventListener implements GLEventListener {
/**
* Interface to the GLU library.
*/
private GLU glu;
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
glu = new GLU();
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glViewport(0, 0, 500, 300);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluOrtho2D(0.0, 500.0, 0.0, 300.0);
}
/**
* Take care of drawing here.
*/
public void display(GLAutoDrawable drawable) {
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glPointSize(20.0f);
for (int i = 0; i < 10; i++) {
red -= .09f;
green -= .12f;
blue -= .15f;
if (red < 0.50) {
red = 0.5f;
}
if (green < 0.15) {
green = 0.5f;
}
if (blue < 0.15) {
blue = 0.5f;
}
gl.glPushMatrix();
gl.glColor3f(red, green, blue);
gl.glTranslatef(10.0f, 500.0f, 0.0f); // Move left 1.5 units, up 1.5 units, and back 8 units
gl.glBegin(GL.GL_QUADS); // Begin drawing quads
gl.glVertex3f((10f * i) + 10, 20.0f, 0.0f); // Top left vertex
gl.glVertex3f((40f * i) + 10, 20f, 0.0f); // Top right vertex
gl.glVertex3f((40f * i) + 10, -20f, 0.0f); // Bottom right vertex
gl.glVertex3f((10f * i) + 10, -20.0f, 0.0f); // Bottom left vertex
gl.glEnd();
gl.glPopMatrix();
}
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}
}
`
//~ Formatted by Jindent --- http://www.jindent.com
the code always produces the following error
Error: Could not find or load main class org.yourorghere.SimpleJoglApp
Java Result: 1
What am i doing wrong?
You never set the jframe.setvisible(true);
Also: Error: Could not find or load main class org.yourorghere.SimpleJoglApp Java Result: 1
has nothing to do with java. Just fix your classes set up.
Related
I have a bunch of ellipses that initially are lined on top of a path and should move along the QPainterPath. I have it working for the first ellipse but I can't figure out how to get the correct position for the other ellipses.
Is there a way to check if it passed the end of the path and move it back to the beginning?
class Animation : public QAbstractAnimation
{
public:
Animation(const QPainterPath& path, QObject *parent = Q_NULLPTR);
virtual void updateCurrentTime(int ms) override;
virtual int duration() const override;
QPainterPath mPath;
QVector<EllipseGraphicsItem*> mAnimationElements;
};
Animation::Animation (const QPainterPath& path, QObject *parent) : QAbstractAnimation(parent)
, mPath(path)
{
qreal pos = 0;
qreal length = mPath.length();
while (pos < length)
{
qreal percent = path.percentAtLength(pos);
QPointF pointAtPercent = path.pointAtPercent(percent);
pos += 40;
EllipseGraphicsItem * item = new EllipseGraphicsItem(parentItem());
mAnimationElements.append(item);
item->setPos(pointAtPercent);
}
}
void Animation::updateCurrentTime(int ms)
{
QPointF point = mPath.pointAtPercent(qreal(ms) / 6000);
if (mAnimationElements.size() > 0)
mAnimationElements[0]->setPos(point);
for (int i = 0; i < mAnimationElements.size(); i++) {
// how to update each circle's position?
}
}
Start the animation:
QPainterPath path;
path.moveTo(10, 10);
path.lineTo(QPointF(500, 10));
path.lineTo(QPointF(500, 700));
path.lineTo(QPointF(10, 700));
Animation *animation = new Animation(path, this);
animation->setLoopCount(-1);
animation->start();
Imho, it would be easier to use a QGraphicsObject with a QPropertyAnimation:
Use a property that varies between 0 and the length of the path and place your elements by calculating their positions from its value and their position in the list.
A quick example :
class AnimatedEllipses: public QGraphicsObject
{
Q_OBJECT
Q_PROPERTY(int progress READ progress WRITE setProgress)
private:
QGraphicsPathItem path;
QList<QGraphicsEllipseItem*> ellipses;
int propProgress;
public:
int progress() const { return propProgress;}
void setProgress(int value)
{
propProgress = value;
int index = 0;
for (QGraphicsEllipseItem* ellipse: ellipses)
{
// Keep value between 0 and length.
int lgt = (propProgress + index * 40) % int(path.path().length());
qreal percent = path.path().percentAtLength(lgt);
++index;
ellipse->setPos(path.path().pointAtPercent(percent));
}
}
AnimatedEllipses(QPainterPath const& path): QGraphicsObject(), path(path), propProgress(0)
{
qreal pos = 0;
qreal length = path.length();
while (pos < length)
{
qreal percent = path.percentAtLength(pos);
QPointF pointAtPercent = path.pointAtPercent(percent);
pos += 40;
QGraphicsEllipseItem * item = new QGraphicsEllipseItem(-10, -10, 20, 20, this);
item->setPos(pointAtPercent);
ellipses << item;
}
QPropertyAnimation* animation = new QPropertyAnimation(this, "progress");
animation->setStartValue(0);
animation->setEndValue(length);
animation->setDuration(10000);
animation->setLoopCount(-1);
animation->start();
}
// QGraphicsItem interface
public:
QRectF boundingRect() const { return path.boundingRect();}
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget){}
};
The modulo allows you to create an infinte loop for each ellipse.
So I have looked at other similar questions on stackoverflow but none seem to help. The problem is that the animation doesn't occur, but once I click somewhere in the QGraphicsView, it updates to the end position.
I'm animating QGraphicsRectItem with QPropertyAnimation, so I made a new class and extended QObject and QGraphicsRectItem:
class MyGraphicsRectItem : public QObject, public QGraphicsRectItem {
Q_OBJECT
Q_PROPERTY(QPointF position READ position WRITE setPosition)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
public:
...
QPointF position();
void setPosition(QPointF animBox);
QRectF geometry();
void setGeometry(QRectF geo);
...
}
One common problem with regarding this problem is that QPropertyAnimation goes out of scope when the function finishes, but I think I circumvented this problem using QAbstractAnimation::DeleteWhenStopped. In my MainWindow.cpp, I have:
group = new QParallelAnimationGroup;
for (int i = 0; i < 10 ; i += 1) {
MyGraphicsRectItem *temp = dynamic_cast<MyGraphicsRectItem*>(histZToItem[i]);
QPropertyAnimation *anim = new QPropertyAnimation(temp, "position");
anim->setDuration(500);
anim->setStartValue(temp->pos());
QPropertyAnimation *geo = new QPropertyAnimation(temp, "geometry");
geo->setDuration(500);
geo->setStartValue(temp->rect());
geo->setEndValue(QRectF(0, 0, colWidth, -80));
if (i > anchorID) {
anim->setEndValue(QPointF(40 + spaceWidth * (i) + colWidth * (i - 1), graphScene->height() - 40));
} else {
anim->setEndValue(QPointF(40 + spaceWidth * (i + 1) + colWidth * (i), graphScene->height() - 40));
}
group->addAnimation(geo);
group->addAnimation(anim);
}
group->start(QAbstractAnimation::DeleteWhenStopped);
Any ideas?
Edit
Here are my implementations for position, setPosition, geometry and setGeometry:
QPointF MyGraphicsRectItem::position()
{
return QGraphicsRectItem::pos();
}
void MyGraphicsRectItem::setPosition(QPointF animPos)
{
QGraphicsRectItem::setPos(animPos);
}
QRectF MyGraphicsRectItem::geometry()
{
return rect();
}
void MyGraphicsRectItem::setGeometry(QRectF geo)
{
setRect(geo);
}
EDIT 2
Here's the constructor:
MyGraphicsRectItem::MyGraphicsRectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent) :QGraphicsRectItem(x, y, width, height, parent) {
setAcceptHoverEvents(true);
}
I'm trying to write button class, one that would switch between on and off states using boolean function.
Switch should happen after if(mousePressed). I can get it to work one way, but I'm lost while trying to get it to switch back to previous state.
When I change one of the if(mousePressed) to if(keyPressed) everything works just fine.
Thank you for your time good Sir.
bclass button;
int offset = 20;
void setup() {
rectMode(CORNERS);
noStroke();
size(300, 100);
button = new bclass(offset, offset, width-offset, height-offset);
}
void draw() {
button.display();
button.state(mouseX, mouseY);
}
class bclass {
float x;
float y;
float w;
float h;
boolean state = false;
bclass(float x_, float y_, float w_, float h_) {
x = x_;
y = y_;
w = w_;
h = h_;
}
void display() {
if (state) {
fill(255, 0, 0);
} else {
fill(0);
}
rect(x, y, w, h);
}
void state(int mx, int my) {
if (!state) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = true;
}
}
}
if (state) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = false;
}
}
}
}
}
Change your state method to:
void state(int mx, int my) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = !state; // change state to opposite value
delay(100); // delay 100ms (mousePressed lasts some millis)
}
}
}
But better solution will be to use Processing's mouseClicked() event:
public void draw() {
button.display();
}
public void mouseClicked() {
button.state(mouseX, mouseY);
}
class bclass {
...
void state(int mx, int my) {
if (mx > x && mx < x + w) {
state = !state;
}
}
}
In this solution button.state() is called only from mouseClicked(), and mouseClicked() is called by Processing when it discovers such event.
I have to do some projet to draw regular polygon with Canvas in JavaFX, and I have doubt how to design a circle with canvas using GraphicsContext
I have this point class containing the two axes (x, y)
public class Point2D {
private float mX;
private float mY;
public Point2D () {
this (0,0);
}
public Point2D (float x, float y) {
mX = x;
mY = y;
}
public float getX() {
return mX;
}
public float getY() {
return mY;
}
}
And I have this circle Class and I have doubt to made the method public void drawCircle(GraphicsContext gc)
public class Circle{
private Point2D mCenter;
private Color color;
private float mRadius;
public Circle (Point2D center, Color color, float radius ) {
this.mCenter = center;
this.color = color;
this.mRadius = radius;
}
public void drawCircle(GraphicsContext gc) { // My Doubt is here
Canvas canvas = new Canvas();
gc = canvas .getGraphicsContext2D();
gc.setFill(Color.WHITE);
gc.setStroke(Color.BLACK);
}
}
In Main JavaFX
public class PaintGeometricoFX extends Application {
private BorderPane root;
#Override
public void start(Stage primaryStage) {
Point2D p = new Point2D(0, 0);
Float radius = 4.0f;
Circle circle = new Circle(p.getX(), p.getY(),Color.BLACK,radius)
Canvas canvas = new Canvas();
GraphicsContext gc = imagem.getGraphicsContext2D();
circle.drawCircle(gc);
root.setCenter(canvas);
Scene scene = new Scene(root, 1152, 800);
primaryStage.setTitle("PAINT");
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Stroking:
getGraphicsContext2D().strokeOval(center.x-radius, center.y-radius, radius * 2, radius * 2);
Filling:
getGraphicsContext2D().fillOval(center.x-radius, center.y-radius, radius * 2, radius * 2);
Note the 3rd and 4th parameters are diameters not radii. I had a discrepancy between ScalaFx and the correct ScalaJs output. But I checked the JavaFx documentation and it works the same:
fillOval
public void fillOval(double x,
double y,
double w,
double h)
Fills an oval using the current fill paint.
This method will be affected by any of the global common or fill attributes as specified in the Rendering Attributes Table.
Parameters:
x - the X coordinate of the upper left bound of the oval.
y - the Y coordinate of the upper left bound of the oval.
w - the width at the center of the oval.
h - the height at the center of the oval.
Stroking:
getGraphicsContext2D().strokeOval(center.x-radius, center.y-radius, radius, radius);
Filling:
getGraphicsContext2D().fillOval(center.x-radius, center.y-radius, radius, radius);
I'm trying to plot some sensor data that's being read in through the serial port. I found this Processing example code of a 2D plotter, and I'm trying to alter it to work for my application.
The programming is a bit over my head though. I can see that it's getting data for the three lines from the three equation classes. I'd like to replace the part where is reads the mouseX with a variable or something that points to the newest sensor update. The sensor data is continuously updated in the void Draw() loop.
/**
* RollingGraph
* This sketch makes ise of the RollingLine2DTrace object to
* draw a dynamically updated plot.
*/
import org.gwoptics.graphics.graph2D.Graph2D;
import org.gwoptics.graphics.graph2D.traces.ILine2DEquation;
import org.gwoptics.graphics.graph2D.traces.RollingLine2DTrace;
class eq implements ILine2DEquation{
public double computePoint(double x,int pos) {
return mouseX;
}
}
class eq2 implements ILine2DEquation{
public double computePoint(double x,int pos) {
return mouseY;
}
}
class eq3 implements ILine2DEquation{
public double computePoint(double x,int pos) {
if(mousePressed)
return 400;
else
return 0;
}
}
RollingLine2DTrace r,r2,r3;
Graph2D g;
void setup(){
size(600,300);
r = new RollingLine2DTrace(new eq() ,100,0.1f);
r.setTraceColour(0, 255, 0);
r2 = new RollingLine2DTrace(new eq2(),100,0.1f);
r2.setTraceColour(255, 0, 0);
r3 = new RollingLine2DTrace(new eq3(),100,0.1f);
r3.setTraceColour(0, 0, 255);
g = new Graph2D(this, 400, 200, false);
g.setYAxisMax(600);
g.addTrace(r);
g.addTrace(r2);
g.addTrace(r3);
g.position.y = 50;
g.position.x = 100;
g.setYAxisTickSpacing(100);
g.setXAxisMax(5f);
}
void draw(){
background(200);
g.draw();
}
Not exactly sure if that code you have is what you need, but here is a simple program that takes in serial input and makes a line graph. Hope this helps.
import processing.serial.*;
Serial myPort;
int x = 0;
void setup() {
size(600, 400);
println(Serial.list()); //list of available serial ports
String portName = Serial.list()[0]; //replace 0 with whatever port you want to use.
myPort = new Serial(this, portName, 9600);
}
void draw() {
}
void serialEvent(Serial myPort) {
int inByte = myPort.read();
println(inByte);
stroke(90, 76, 99);
//vertical line with height varying according to input
line(x, height, x, height - inByte);
if (x >=width) {
x=0;
background(0);
}
x++;
}