Processing PApplet call in nested classes - nested

I'm using Processing 3 to make a GUI for a servo controller instead of using a pre-made library. It's based on having a packaging class organize several subclasses which use registerMethod mouse events to operate (as opposed to the simpler use of mousePressed() in the main sketch). What I'm getting hung up on is the PApplet naming/terms for each class to ensure that they can function both inside a subclass as well as on their own when called from the main. In my example the package is just a single button, as well as a direct button call for comparison. I do know that most current Java-users consider Applet use outdated, but since I'm just using the Processing IDE, I'd like to understand this concept better as well as try to avoid using something more complicated (but maybe less confusing) like an Interface.
PackServ tryMe;
Butt bOne;
void setup() {
size(200, 150);
tryMe = new PackServ(this);
bOne = new Butt(this);
}
void draw() {
background (250);
tryMe.Add(20, 10, 50);
line(100,10,100,100);
fill(130,255,170);
rect(120,10,50,60,5);
bOne.Add("B2", 145,35,25);
stroke(20); textSize(14); fill(25);
text("single", 130,100);
text("package", 20,100);
}
public class PackServ extends PApplet {
PApplet SerApp;
Butt Butt1, Butt2;
String theName;
int pkX, pkY, pkW;
PackServ(PApplet pa) {
this.SerApp = pa;
theName = "The Slider";
pkX = 20;
pkY = 20;
pkW = 100;
}
void Add(int _x, int _y, int _w) {
pkX = _x; pkY = _y; pkW = _w;
Butt1 = new Butt (this);
drawIt();
}
void drawIt() {
SerApp.fill(200);
SerApp.strokeWeight(1);
SerApp.rect(pkX, pkY, pkW, 60, 5);
Butt1.Add("B1", pkX+25, pkY+25, 25);
}
}
public class Butt
{
PApplet butApp;
int theX, theY, theW, theH, bRad;
boolean pressed = false;
color n;
color h = color(240, 210, 10);
color f = color (40, 90, 190);
color a = color (240, 20, 20);
int oBb, li;
String theLabel;
Butt (PApplet butApplet) {
this.butApp = butApplet;
butApp.registerMethod("mouseEvent",this);
n = f;
}
void Add(String _myName, int x, int y, int siz) {
theLabel = _myName;
theX = x;
theY = y;
bRad = siz;
fill(75);
textSize(9);
buttonLook();
}
boolean overB(int mx, int my) {
if (dist (mx, my, theX, theY) <= bRad) {
return true;
} else {
return false;
}
}
void buttonLook() {
if (overB(mouseX, mouseY) && pressed) {
n = a;
oBb = 3; li = 100;
} else if (overB(mouseX, mouseY)) {
text(theLabel, theX-10, theY+25);
n = h;
} else {
n = f; oBb=1; li=25;
}
strokeWeight(oBb);
stroke(li);
fill(n);
ellipse(theX, theY, bRad, bRad);
}
void mouseEvent(MouseEvent e) {
pressed = false;
int mx = e.getX(), my = e.getY();
switch (e.getAction()) {
case MouseEvent.PRESS:
pressed = overB(mx, my);
break;
}
}
}

I'm not totally sure what you're asking, so let me try to answer a few different things that you seem a bit confused about.
I do know that most current Java-users consider Applet use outdated
Please note that other than its name, PApplet has nothing to do with applets. Historically a PApplet was an applet, but as of Processing 3 that's no longer the case. PApplet is its own thing and has nothing to do with applets.
Let's take a closer look at this code:
public class PackServ extends PApplet {
PApplet SerApp;
PackServ(PApplet pa) {
this.SerApp = pa;
...
It doesn't make a ton of sense to extend PApplet and also take a PApplet argument into the constructor. This means that you now have two PApplet instances, which is almost never what you want to do.
Instead, my guess is you probably want to get rid of the extends PApplet part and only use Processing's classes using your serApp variable.
I believe that's the crux of your confusion: the PApplet class offers a bunch of handy functions like draw() and ellipse(), basically most variables and functions in the Processing reference. So you do need an instance of PApplet, but that instance is created for you when you use the Processing editor. You don't need to create your own instance by extending the PApplet class.

Related

Calling a String in Processing

I'm new to processing/java/code but was hoping for some help with my sketch.
I am trying to create an ink-looking sketch, with letters/characters displayed, then faded out instead of particles themselves. Inspired by https://openprocessing.org/sketch/1576908 I've run into errors with the entire particle constructor with an error on the line void update(p):
//update the velocity and location of particle
void update(p){
this.acceleration.add(createVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.push(new particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5));
}
}
Here is my full code
Thank you!
String[] particles = {"a", "b", "c", "d"} ; //string of particles
int velocity;
int acceleration;
int location;
int alpha;
int p;
void setup() {
size(600, 600);
background(255);
}
void draw() {
if(mousePressed) {
// spawn a new particle and add it to the array
particles.push(text(particles, mouseX, mouseY, 75));
textSize(random(20, 40));
}
// update and show the particles
for(int i=particles.length-2; i>=0; i--) {
particles[i].update(particles);
particles[i].show();
if(particles[i].alpha<=2) particles.splice(i, 5); // remove the dead particle
}
}
//particle class
class particle{
//constructor called when creating an instance of this class
// x & y are the location, r is the rate of decay, a is the starting alpha value
particle(float x, float y, float r, float a){
this.location = createVector(x,y) ;
this.velocity = createVector(random(-1,1),random(-1,1));
this.acceleration = createVector();
this.alpha = this.palpha=a ;
this.amp=4; // size of the particle
this.rate = r;
}
//update the velocity and location of particle
void update(p){
this.acceleration.add(createVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.push(new particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5));
}
}
//show the particles
void show(){
noStroke() ;
fill(0,35,25, this.alpha) ;
ellipse(this.location.x, this.location.y, this.amp);
}
} // end particle class```
You have at least two separate questions here:
how to port the p5.js sketch to Processing ?
how to add text for each particle ?
In the future I recommend breaking the problem down to simpler/shorter problems that can be tackle independently.
How let's look at the syntax errors Processing presents:
1.
particles.push(text(particles, mouseX, mouseY, 75));
errors with
The function "text()" expects parameters like: "text(int, float, float, float)"
The issue here is slightly masked. It looks like instead of calling text(yourTextString, yourTextX, yourTextY); you have different parameters. In reality there are two issues here:
push() is JavaScript Array's function. You need to use an ArrayList and its add() method instead in Processing (Java).
currently the particle class doesn't handle text. You can add a String text property which you can supply with a modified contructor: Particle(float x, float y, float r, float a, String text) (and you'd assign the constructor argument to the instance property (e.g. this.text = textl)
createVector exists in p5.js. In Processing you can switch this to new PVector(). Additionally you need to declare the variables initialised in the constructor as part of the class (e.g. location, velocity, acceleration, alpha, palpha, amp, rate).
ellipse(this.location.x, this.location.y, this.amp); is missing the last argument: ellipse(this.location.x, this.location.y, this.amp, this.amp);
This is a modified version of your code with the above notes applied:
// original sketch by OpenProcessing user Prasad
// https://openprocessing.org/sketch/1576908
String[] particlesText = {"a", "b", "c", "d"} ; //string of text
// array of particles
ArrayList<Particle> particles = new ArrayList<Particle>();
int velocity;
int acceleration;
int location;
int alpha;
int p;
void setup() {
size(600, 600);
background(255);
}
void draw() {
if(mousePressed) {
// spawn a new particle and add it to the array
// use % to loop over text (e.g .a,b,c,d,a...etc)
int textIndex = particles.size() % particlesText.length;
// grab the text from the array
String text = particlesText[textIndex];
// add a new particle providing text as well
particles.add(new Particle((float)mouseX, (float)mouseY,5.0, 75.0, text));
textSize(random(20, 40));
}
// update and show the particles
for(int i=particles.size()-2; i>=0; i--) {
Particle particle = particles.get(i);
particle.update(particles);
particle.show();
if(particle.alpha<=2) particles.remove(i); // remove the dead particle
}
}
//particle class
class Particle{
PVector location;
PVector velocity;
PVector acceleration;
float alpha;
float palpha;
float amp;
float rate;
String text = "";
//constructor called when creating an instance of this class
// x & y are the location, r is the rate of decay, a is the starting alpha value
Particle(float x, float y, float r, float a, String text){
this.location = new PVector(x,y) ;
this.velocity = new PVector(random(-1,1),random(-1,1));
this.acceleration = new PVector();
this.alpha = this.palpha=a ;
this.amp=4; // size of the particle
this.rate = r;
this.text = text;
}
//update the velocity and location of particle
void update(ArrayList<Particle> p){
this.acceleration.add(new PVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.add(new Particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5, this.text));
}
}
//show the particles
void show(){
noStroke() ;
fill(0,35,25, this.alpha);
//render the ellipse
ellipse(this.location.x, this.location.y, this.amp, this.amp);
// render the text
textSize(this.amp * 6);
text(this.text, this.location.x, this.location.y);
}
} // end particle class
(Note that you can choose not to render the ellipses and you can tweak the text size to something that makes more sense aesthetically. Also, when you're using other people's code, always credit them.)

MQL4 Drawing a Dynamic Rectangle_Label with a Text in It

I am trying to draw a Rectangle Label with a text in it every tick.. I want a text to fit exactly in to a Rectangle_Label.. As a text i am using Label.. But cant get it to work exactly.. It is not correctly situated..
In Fact i would like to create a class that would do it all in one... Just like a rectangle with text in it that would be always having same co ordinance and size etc..
Any help would be greatly appreciated...
bool createRectangleLabel(long chart_ID,string name,string labelName,int shift,double price,string text,double xSize,double ySize,double xOffSet,double yOffSet,double xDistance,double yDistance)
{
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price))
{
Print(xDistance+" "+yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YSIZE,ySize);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XSIZE,xSize);
ObjectSetString(chart_ID,labelName,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
return true;
}
else
{
Print("createRectangleLabel return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}
bool createLineText(long chart_ID,string name,string labelName,int shift,double price,string text)
{
int xDistance=0;
int yDistance=0;
int xSize,xOffSet;
int ySize,yOffSet;
bool i=ChartTimePriceToXY(chart_ID,0,TimeCurrent(),price,xDistance,yDistance);
if(ObjectCreate(chart_ID,name,OBJ_LABEL,0,TimeCurrent()-shift,price))
{
ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,yDistance);
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,10);
xSize = ObjectGet(name,OBJPROP_XSIZE);
ySize = ObjectGet(name,OBJPROP_YSIZE);
xOffSet = ObjectGet(name,OBJPROP_XOFFSET);
yOffSet = ObjectGet(name,OBJPROP_YOFFSET);
TextGetSize(name,xSize,ySize);
createRectangleLabel(chart_ID,name,labelName,shift,price,text,xSize,ySize,xOffSet,yOffSet,xDistance,yDistance);
return true;
}
else
{
Print("createLineText return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}
You cannot call ObjectCreate() every tick - it would return an error 4200.
If you check the object exists before creating, that would help. Alternative approach would be to try to create the object and assign it with some necessary properties (e.g., color of the object, anchor etc) in one block, and move it in another.
if(ObjectFind(chart_id,labelName)<0){
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price)){
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);//etc.
}
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);//if you need to move the object or take other steps each tick, e.g. update text - do it here
}
You're thinking along the right lines when you say that you'd like to create a class. Fortunately for you, the standard library already includes all the classes you need to make chart objects. Documentation
Example Indicator:
#property strict
#property indicator_chart_window
#include <ChartObjects\ChartObjectsTxtControls.mqh>
class MyRectLabel : public CChartObjectRectLabel
{
CChartObjectLabel m_label;
public:
bool Create(long chart, const string name, const int window,
const int X, const int Y, const int sizeX, const int sizeY)
{
if(!CChartObjectRectLabel::Create(chart,name,window,X,Y,sizeX,sizeY))
return false;
return m_label.Create(chart, name + "_", window, X + 8, Y + 12);
}
bool Color(const color clr){
return m_label.Color(clr);
}
bool Description(const string text){
return m_label.Description(text);
}
bool FontSize(const int size){
return m_label.FontSize(size);
}
bool ToolTip(const string text){
return (this.ToolTip(text) && m_label.Tooltip(text));
}
};
//+------------------------------------------------------------------+
MyRectLabel rect_label;
//+------------------------------------------------------------------+
int OnInit()
{
if(!rect_label.Create(0, "rlabel", 0, 5, 25, 100, 50)
|| !rect_label.BackColor(clrWhiteSmoke)
|| !rect_label.Description("LABEL!")
|| !rect_label.Tooltip("I am a rectangle label")
|| !rect_label.Color(clrBlack)
|| !rect_label.FontSize(18)
)
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int start()
{
static double last_price = 0.;
rect_label.Description(DoubleToString(Bid, _Digits));
if(Bid > last_price)
rect_label.Color(clrLimeGreen);
else
rect_label.Color(clrRed);
last_price = Bid;
return 0;
}

How to declare fields?

I write a GUI program in Vala. When I compile it, compiler produces this error:
The name e1 does not exist in the context of Subtract.minus
The code is:
using Gtk;
class Subtract:Window{
public Subtract(){
this.title="Subtract program";
this.destroy.connect(Gtk.main_quit);
var e1=new Entry();
var e2=new Entry();
var lbl=new Label("Result");
var btn=new Button.with_label("Subtract");
var box=new Box(Gtk.Orientation.VERTICAL,5);
box.add(e1);
box.add(e2);
box.add(lbl);
box.add(btn);
this.add(box);
btn.clicked.connect(minus);
}
public void minus(){
int a=int.parse(e1.get_text());
int b=int.parse(e2.get_text());
int result=a-b;
lbl.set_label(result.to_string());
}
public static int main(string[]args){
Gtk.init(ref args);
var win=new Subtract();
win.show_all();
Gtk.main();
return 0;
}
}
How can I make the variables accessible from the minus method.
You have to declare the variables for your widgets (at least e1, e2 and lbl) as fields:
using Gtk;
class Subtract: Window {
// Fields (sometimes also called "attributes")
private Entry e1;
private Entry e2;
private Label lbl;
private Button btn;
private Box box;
public Subtract () {
title = "Subtract program";
destroy.connect (Gtk.main_quit);
// You don't have to use "this." to access fields in Vala
// I.e. "this.e1" is equivalent to "e1" in the code below
e1 = new Entry ();
e2 = new Entry ();
lbl = new Label ("Result");
btn = new Button.with_label ("Subtract");
box = new Box (Gtk.Orientation.VERTICAL, 5);
box.add (e1);
box.add (e2);
box.add (lbl);
box.add (btn);
add (box);
btn.clicked.connect (minus);
}
public void minus () {
// The compiler happily accepts "e1" (etc.) here now
// since I have declared them as fields
int a = int.parse (e1.get_text ());
int b = int.parse (e2.get_text ());
int result = a - b;
lbl.set_label (result.to_string ());
}
public static int main (string[] args) {
Gtk.init (ref args);
var win = new Subtract ();
win.show_all ();
Gtk.main ();
return 0;
}
}
PS: The correct technical term is "scope" here. Your code had the variables at the scope of the constructor, my code as the variables as class scoped fields which makes them visible across all the methods of the class.
The Vala compiler calls it "context", which is roughly the same in this case.

lerpColor() / fill() throwing NullPointerException with Processing

This is the code for a class:
class Circle extends PApplet {
//var declarations
Circle(int duration, int from, int to, PApplet parent, int x, int y, int length, int height){
this.ani = new Tween(parent, 1.3f, Tween.SECONDS, Shaper.QUADRATIC);
Class s = Shaper.QUADRATIC;
this.from = from;
this.to = to;
this.len = length;
this.height = height;
this.x = x;
this.y = y;
}
void update(){
int c = lerpColor(this.from, this.to, this.ani.position(), RGB);
fill(c);
ellipse(this.x, this.y, this.len, this.height);
}
}
When I run update() on a properly seeded version of Circle (see below example), I get this stack trace:
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.core.PApplet.fill(PApplet.java:13540)
at ellipses.Circle.update(Ellipses.java:85)
at ellipses.Ellipses.draw(Ellipses.java:39)
at processing.core.PApplet.handleDraw(PApplet.java:2128)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:190)
at processing.core.PApplet.run(PApplet.java:2006)
at java.lang.Thread.run(Thread.java:662)
It tells me that inside fill(), something is null when it shouldn't be. I would at first assume the value passed to fill() is somehow wrong. The value to fill() comes from lerpColor(), so presumably I've used lerpColor() wrongly.
My instance of Circle looks like this:
int c1 = color(45, 210, 240);
int c2 = color(135, 130, 195);
cir = new Circle(1, c1, c2, this, 100, 200, 140, 140);
cir.update();
So how can I use fill()/lerpColor correctly?
(BTW, I'm using processing in eclipse with proclipsing.)
Well first of all I am not entirely sure why would you need to extend the PApplet from a class that does not seem to be one of your windows, but i digress.
If I understand what you are trying to do, the problem lies with the fill function and not with lerpColor. If you are trying to call the fill function of your main PApplet and this Circle class is not it, then you need to tell it on which PApplet to call it. i.e. the parent that you already send in. I'd do something like this.
class Circle extends PApplet {
//var declarations
Tween ani;
int from, to, x, y, len, heightz;
PApplet parr; // prepare to accept the parent instance
Circle(int duration, int from, int to, PApplet parent, int x, int y, int length, int height) {
this.ani = new Tween(parent, 1.3f, Tween.SECONDS, Shaper.QUADRATIC);
Class s = Shaper.QUADRATIC;
this.from = from;
this.to = to;
this.len = length;
this.heightz = height;
this.x = x;
this.y = y;
parr = parent; // store the parent instance
}
void update() {
color c = lerpColor(this.from, this.to, this.ani.position(), RGB);
parr.fill(c); // call fill on the parent
parr.ellipse(this.x, this.y, this.len, this.height); // this one obviously suffers from the same problem...
}
I hope this helps!
pk

get layout height and width at run time android

How can I get width and height of a linear layout which is defined in xml as fill_parent both in height and width? I have tried onmeasure method but I dont know why it is not giving exact value. I need these values in an Activity before oncreate method finishes.
Suppose I have to get a LinearLayout width defined in XML. I have to get reference of it by XML. Define LinearLayout l as instance.
l = (LinearLayout)findviewbyid(R.id.l1);
ViewTreeObserver observer = l.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
init();
l.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
protected void init() {
int a= l.getHeight();
int b = l.getWidth();
Toast.makeText(getActivity,""+a+" "+b,3000).show();
}
callfragment();
}
The width and height values are set after the layout has been created, when elements have been placed they then get measured. On the first call to onSizeChanged the parms will be 0 so if you use that check for it.
Little more detail here
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/nNEp6xBnPiw
and here http://developer.android.com/reference/android/view/View.html#Layout
Here is how to use onLayout:
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int width = someView.getWidth();
int height = someView.getHeight();
}
To get it work, you need to check whether the desired height value is bigger than 0 - and first then remove the onGlobalLayout listener and do whatever you want with the height. The listener calls its method continuously and by the first call it is not guaranteed that the view is measured properly.
final LinearLayout parent = (LinearLayout) findViewById(R.id.parentView);
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int availableHeight = parent.getMeasuredHeight();
if(availableHeight>0) {
parent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//save height here and do whatever you want with it
}
}
});
You could add on layout change listener to your layout and get the newest height and width or even the one before last change.
Added in API level 11
Add a listener that will be called when the bounds of the view change
due to layout processing.
LinearLayout myLinearLayout = (LinearLayout) findViewById(R.id.my_linear_layout);
myLinearLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// Preventing extra work because method will be called many times.
if(height == (bottom - top))
return;
height = (bottom - top);
// do something here...
}
});
A generic approach using Kotlin based on MGDroid's answer for API 16+.
/**
* Align height of a container from wrap-content to actual height at runtime.
* */
private fun <T: ViewGroup> alignContainerHeight(container: T) {
container.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
// Obtain runtime height
val availableHeight = container.measuredHeight
if (availableHeight > 0) {
container.viewTreeObserver.removeOnGlobalLayoutListener(this)
setContainerHeight(container, availableHeight)
}
}
})
}
/**
* Note: Assumes that the parent is a LinearLayout.
* */
private fun <T : ViewGroup> setContainerHeight(container: T, availableHeight: Int) {
val availableWidth = container.measuredWidth
val params = LinearLayout.LayoutParams(availableWidth, availableHeight)
// Note: getLayoutParams() returns null if no parent exists
if (container.layoutParams != null) {
container.layoutParams = params
}
}

Resources