Beginner needs help regarding simple object programming.

Hello everyone !

First this is a little background on this project : I began using Processing to use with my arduino project to create a simple desktop monitoring "widget" that would display all kind of informations the arduino sensors would send. I'm quite new to programming and newer in Processing.

Here is my problem :

I wish to create an object ( called "bloc" ) that is simply a little rectangle with some attributes like title, colors and so on. Problem starts when I tried to implement a click&drag fonctionality, allowing for easy repositioning of the "bloc" inside the canvas.

I got it to work, but this imply I have to declare a bunch of extra stuff in the main code that kinda of erase the purpose of using an object and I feel I'm missing something that would allow me to get that code inside the "bloc" class file.

So anyway please feel free to help me on this, and idea/tips regarding the project would be greatly appreciated too, thanks !

Main file : objected.pde

PFont font;
Bloc a;              // At this time the bloc a needs xa ya ca da IN the main file to run
int xa=0;            // if I move those values and the "if mousepressed" in the bloc class file
int ya=0;            // it will work until mouse isn't pressed and it will then come back to default values
int ca=100;          // of the main program, because i'm unable to communicate variables between
int da=100;          // main file and class file.

void setup()
{
  size(400,1015);
  font = loadFont("Impact-48.vlw");
  textFont(font, 48);
  a= new Bloc();
}

void draw()
{
  background(255);
  if ((mousePressed == true) && xa < mouseX && mouseX < xa+ca && ya < mouseY && mouseY < ya+da ) {

        xa= mouseX -(ca/2) ;
        ya= mouseY -(da/2) ;
      }
 a.display(xa,ya,ca,da,0,0,240); 
 a.title("Test");
}

Secondary file : bloc.pde

class Bloc {
  int x;
  int y;
  color theme;
  float xmiddle;


    Bloc(){


    }

    void display(int a , int b , int c, int d, int Rtheme, int Gtheme, int Btheme){        // display a bloc on the screen ( xpos , ypox , lengh, height, Rtheme, Gtheme, Btheme )
      x=a;
      y=b;
      xmiddle = x + (c/2) ;
      theme = color (Rtheme,Gtheme,Btheme);
      stroke(theme);
      fill(255);
      rect(x,y,c,d);

    }

    void title(String a) {                                                                // set the title of the bloc
      PFont titlefont = loadFont("Corbel-30.vlw");
      textFont(titlefont);
      fill(theme);
      textAlign(CENTER, TOP);
      text(a,xmiddle,y-30);

    }


    void move() {

    }
}

Answers

  • In this post there is a drag and drop example.

    https://forum.processing.org/two/discussion/comment/54354/

  • edited December 2015

    Thanks vk for the quick answer !

    What I saw in your code is that you set the class inside the main code. I did use a different file for the classe code ( using the "new tab" inside processing ) it helps me getting things nice and clean in my head (lol).

    I guess my question can be shorten to : " is there a way to have a variable that can be defined in the child code and used in the main file. Can a variable have a "full scope" so to speak.

    PS : Edited

  • edited December 2015

    This code shows two Bloc(s) which can be dragged independently.

    Notice the class takes care of itself :)

    Bloc bloc1, bloc2; 
    Bloc hasFocus = null;
    
    void setup() {
      size(400, 1015);
      textSize(48);
      bloc1 = new Bloc(20, 120, 100, 60, color(10, 160, 10));
      bloc1.title("Green");
      registerMethod("mouseEvent", bloc1);
      bloc2 = new Bloc(120, 520, 100, 60, color(10, 10, 160));
      bloc2.title("Blue");
      registerMethod("mouseEvent", bloc2);
    }
    
    void draw() {
      background(255);
    
      bloc1.display();
      bloc2.display();
    }
    
    public class Bloc {
      int px, py, w, h;
      color theme;
      String text;
      boolean dragging = false;
    
      Bloc(int x, int y, int wide, int high, color col) {
        px = x;
        py = y;
        w = wide;
        h = high;
        theme = col;
      }
    
      void display() { 
        stroke(theme);
        fill(255);
        rect(px, py, w, h);
        fill(theme);
        textSize(24);
        textAlign(CENTER, TOP);
        text(text, px, py, w, h - 24);
      }
    
      public void mouseEvent(MouseEvent event) {
        switch(event.getAction()) {
        case MouseEvent.PRESS:
          if (isOver(mouseX, mouseY) && hasFocus == null) {
            dragging = false;
            hasFocus = this;
          }
          break;
        case MouseEvent.CLICK:
          if (hasFocus == this) {
            dragging = false;
            hasFocus = null;
          }
          break;
        case MouseEvent.RELEASE:  
          if (hasFocus == this) {
            dragging = false;
            hasFocus = null;
          }
          break;
        case MouseEvent.DRAG:
          if (hasFocus == this) {
            px += (mouseX - pmouseX);
            py += (mouseY - pmouseY);
          }
          break;
        }
      }
    
      void title(String title) {
        text = title;
      }
    
      boolean isOver(int x, int y) {
        return (x > px && x < px + w && y > py && y < py + h);
      }
    }
    
  • BTW it is better that variable names represent the data they hold.

  • _vk_vk
    edited December 2015 Answer ✓

    Tabs in PDE are a convenience, as long as they are NOT named something.java, they will all be wrapped in one class by the pre-processor. So there is no difference in declaring your class in a tab or not. :)

  • edited December 2015

    Thanks you guys for all your answers, and thanks for the clarifiction on tabs vk !

    I managed to get everything nice and neat like I wanted.

    My problem was i needed to set initial parameters for the object ( x, y, height and lenght ) but then be able to interact with those without altering the values for other objects.

    I managed to do that with some kind of triggers : as long as no trigger is triggered ( lol ) the object will use initial values. And if a trigger is trigerred ( re-lol ) it will then start to use custom and class local variables.

    I put the code for reference, I tried and make it clean but that's far away from quark and his fancy blue functions haha, but still it allows me to keep it clean on the main file.

    Thanks again and merry christmas =)

    Main file :

    PFont font;
    Bloc a,b;            
    
    void setup()
    {
      size(400,1015);
      font = loadFont("Impact-48.vlw");
      textFont(font, 48);
      a= new Bloc();
      b= new Bloc();
    }
    
    void draw()
    {
      background(50,80,170);
    
     a.display(50,50,150,100,0,0,240); 
     a.title("Test");
     a.move();
     b.display(50,200,150,100,0,0,240); 
     b.title("Test2");
     b.move();
    }
    

    Class file :

    class Bloc {
      int x;    // x coordinate
      int y;    // y coordinate
      int l;    // lenght
      int h;    // height
      color theme;
      boolean i = false;   // drag&drop trigger
      boolean jx = false;   // resize triggers 
      boolean jy = false;   //
      int move_tolerance = 10;    // this sets the "fatness" of the resize borders
        Bloc(){
           }
    
        void display(int xini , int yini , int lini, int hini, int Rtheme, int Gtheme, int Btheme){        // display a bloc on the screen ( xpos , ypox , lengh, height, Rtheme, Gtheme, Btheme )
          theme = color (Rtheme,Gtheme,Btheme);
          stroke(theme);
          fill(255);
            if ( i == false ) {            // those are the triggers for the bloc to start using custom x/y/l/h
              x=xini;
              y=yini;
            }
    
            if ( jx == false ){
             l=lini; 
            }
    
            if ( jy == false ){
              h=hini;
            }
          rect(x,y,l,h); 
    
        }
    
        void title(String a) {                                                                // set the title of the bloc
          PFont titlefont = loadFont("Corbel-30.vlw");
          textFont(titlefont);
          fill(theme);
          textAlign(CENTER, TOP);
          text(a,x+(l/2),y-30);
    
        }
    
    
        void move() {                                                                                            
           if ((mousePressed == true) && x+move_tolerance < mouseX && mouseX < x+l-move_tolerance && y +move_tolerance< mouseY && mouseY < y+h-move_tolerance ) {    // allow the bloc to click and drag
                x= mouseX -(l/2) ;
                y= mouseY -(h/2) ;
                i=true;
           }
    
           if ((mousePressed == true) && (x+l-move_tolerance < mouseX && mouseX < x+l+move_tolerance ) && (y-move_tolerance<mouseY && mouseY < y+h+move_tolerance)) {   // allow to resize the block clicking the stroke lenght wise
                l = l + mouseX - pmouseX;
                jx = true;
          }
          if ((mousePressed == true) && (y+h-move_tolerance < mouseY && mouseY < y+h+move_tolerance ) && (x-move_tolerance<mouseX && mouseX < x+l+move_tolerance)) {    // allow to resize the block clicking the stroke height wise
              h = h + mouseY - pmouseY;
              jy = true;
    
          }
      }
    }
    
  • hmm...

    room for improvement

    Your thinking on the display() method is too complicated

    you pass parameters to the constructor (see tutorials objects) and they are then used in the class. They can be changed.

  • I will try and improve on this, the constructor is this line ?

    Bloc(){
           }
    

    If so you're right I didn't quite get the grasp on it and left it empty. This is a learning process and I just started but I really wanted to work in "OOP" fashion to start on good bases.

    So far I think Processing is really a fantastic tool, it allows a complete noob like me to code a nice looking interface quite simply and that's awesome =)

  • edited December 2015

    You coulda even removed the empty Block's constructor.
    Java automatically creates an empty 1 when it's omitted! :ar!

  • edited December 2015

    Nice to know GoToLoop =)

    I built up the class constructor and included the properties of the bloc inside ( position, size, color ) so it's really nice. I also got rid of the triggers things ( since the object are created in the setup, inital values won't be reset, that was my mistake ).

    This is off of the original topic but I have another question :

    When I use processing main fonctions ( like text(), background() etc ... ) they have this nice feature that allow for different forms of argument. For example background() can take one argument ( grey variants ) or three for RGB color. Is it possible for me to create a class/function with the same properties ? For example my block class now take 7 arguments ( 4 for placement and size and 3 for color ) it is possible for me to code so that if i only provide the placement argument it wil understand and use some kind of default value for color ? My answer would be to create a clone with a name variant but it would be nice to have it all inside the same function/class.

    Thanks to anyone patient enough to answer me =)

  • _vk_vk
    edited December 2015

    Hi. I totally think going to OOP is a good idea. I't does makes things easier... I'm not really good in technical stuff, or even in advanced OOP concepts, but here a simple example that should answer your question. See the comments.

    // any key to use alternative display() method
    //==========
    
    // we don't have variables width and height before setup() runs...
    // this version needs them, so just declare it here (global scope)
    Sample s1;
    
    //this overloaded version (see comments below)
    // does not need width or height. I can init it here
    Sample s2 = new Sample("s2", new PVector(100, 100));
    
    boolean say = false;
    
    
    void setup() {
      size(400, 400);
    
      // we init that here, after size()
      s1 = new Sample("s1");
      background(255);
    }
    
    void draw () {
      background(255);
    
      s1.display();  
    
      //call optional display() methods based in boolean
      if (!say) {
        s2.display();
      } else { 
        s2.display("hello");
      }
    }
    
    void keyPressed() {
      say = !say;
    }
    
    
    //by convention classes have Capital letters
    class Sample {
      // Stuff here is called properties i think or fields, not sure...
      // these are unique per instance.
    
      // Pvector is very handy when dealing with position
      // they hold all info together and have a lot of methods too
      PVector pos; 
    
      String id;
      color c;
      int wh;
    
      // The constructor has no return type(void/int/etc)
      // And the same name of the class, here is one:
      Sample(String _id) {
        // here we pass the incoming value to this instance field (or propertie?)
        id = _id;
    
        // this construct. has no pos parameters - the stuff inside the () 
        // so it will self init pos and size
        // PVectors are objects and need to be initialized with new.
        wh = int(random(30, 90));
        pos = new PVector(random(width - wh), random(height - wh));
    
        //color self inited also
        c = 70;
      }//end of Sample(String _id)
    
    
      // The question about fill(255) and fill(255,0,0) is about
      // overloading (that's the word to google). In short 
      // u can make methods with the same name if they got different parameters
      // the program will use the matching one. Another word to google, signature.
      // Constructors may be overloaded to:
      // This one will get one more parameter, a Pvector to set it's pos
      Sample(String _id, PVector _p) {
    
        // I'm calling the above constructor here to init other stuff
        // weird... this() calls this class matching constructor
        // I could just repeat the line   wh = int(random(40, 60));
        // and the others here, but...
        // another word, well not really a word: DRY
        // Don't Repeat Yourself see wikipedia
        this(_id);
    
        // here we pass the incoming value to class field (or propertie?)
        pos.x = _p.x; 
        pos.y = _p.y;
      }//end of Sample(String _id, PVector _p)
    
      void display() {
        fill(c);
        rect(pos.x, pos.y, wh, wh*1.35);
    
        fill(200);
        textSize(18);
        text(id, pos.x +10, pos.y + wh - 10);
      }//end of display()
    
    
      //an overloaded display()
      void display(String n) {
        display();
    
        fill(200, 100, 100);
        textSize(18);
        float leng = textWidth(id);
        text(n, leng + pos.x +15, pos.y + wh - 10);
      }//end of display(String n)
    
    }////end of Sample class
    

    And as you can see //comments are awesome!

    :)

  • edited December 2015

    ... they have this nice feature that allows for different forms of argument.

    That's called overloading, which is a type of polymorphism.
    More than 1 method/constructor can use the same name as long as each 1 got its own signature.
    Signature includes parameter's quantity, order & datatype. Returning datatype counts as well.

  • You guys are awesome ! Thanks a lot for the example vk. I will look about PVector as it seems a nice tool to organize parameters but for now, as I have no idea about it, I kept it within my range of understanding ^^. GoToLoop you man deserve a medal in pedagogy. Your answer was perfect =)

    So I did implement this in my code :

    Main :

    PFont font;
    Bloc a,b;    
    Sinusoide s;
    
    void setup()
    {
      size(400,1015);
      font = loadFont("ClearSans-Medium-20.vlw");
      textFont(font, 20);
      a= new Bloc(50,50,150,100,80,110,20);    // this use "full" constructor
      b= new Bloc(50,200,150,100);                   // this the "light" version
      s= new Sinusoide();
      frameRate(120);
    }
    
    void draw()
    {
      background(0);
       a.display(); 
       a.title(" Test ");
       a.move();
       b.display(); 
       b.title("Arduino");
       b.move();
       b.content("Caracteristics :\n x:" + b.spitx() + "\n y:"+ b.spity() + "\n l:" + b.spitl() + "\n h:" + b.spith());
    

    Class File :

    class Bloc {
      int x, y, l, h;                             // Placement and size of the bloc
      float w;                                    // Used for text width 
      color theme, themelight, themedark;         // Different colors of the box
      int move_tolerance = 10;                    // This sets the "fatness" of the resize borders
    
    
    
    
      Bloc(int tempx, int tempy, int templ, int temph, int rtheme, int gtheme, int btheme) {        // First "full" constructor
    
        x=tempx;
        y=tempy;
        l=templ;
        h=temph;
        theme = color ( rtheme, gtheme, btheme );
        themelight = color (rtheme+30, gtheme+30, btheme+30);
        themedark = color (rtheme-30, gtheme-30, btheme-30);
      }
    
    
      Bloc(int tempx, int tempy, int templ, int temph) {                                           // Optional "light" constructor that generates color itself
        int r = int(random(30, 225));
        int g = int(random(30, 225));
        int b = int(random(30, 225));
        x=tempx;
        y=tempy;
        l=templ;
        h=temph;
        theme = color (r, g, b);
        themelight = color (r+30, g+30, b+30);
        themedark = color (r-30, g-30, b-30);
      }
    
    
    
      void display() {                                                                             // Displays the bloc
        stroke(theme);
        strokeWeight ( 3 );
        strokeJoin (BEVEL);
        fill(themelight);
        rectMode(CORNER);
        rect(x, y, l, h);
      }
    
      void title(String a) {                                                                      // Sets the title of the bloc and its matching box
        w = textWidth(a);
        rectMode(CENTER);
        stroke(theme);
        strokeWeight ( 3 );
        strokeJoin (ROUND);
        fill(themelight);
        rect(x+(l/2), y-12, w+25, 24); 
        PFont titlefont = loadFont("ClearSans-Medium-20.vlw");
        textFont(titlefont);
        fill(themedark);
        textAlign(CENTER, TOP);
        text(a, x+(l/2), y-20);
      }
    
    
      void move() {
        int dx = mouseX - pmouseX;
        int dy = mouseY - pmouseY;
        if ((mousePressed == true) && x+move_tolerance < mouseX && mouseX < x+l-move_tolerance && y +move_tolerance< mouseY && mouseY < y+h-move_tolerance ) {       // Allows the bloc to click and drag
          x= x + dx  ;
          y= y + dy ;
        }
    
        if ((mousePressed == true) && (x+l-move_tolerance < mouseX && mouseX < x+l+move_tolerance ) && (y-move_tolerance<mouseY && mouseY < y+h+move_tolerance)) {   // Allows to resize the block clicking the stroke lenght wise
          l = l + dx;
        }
        if ((mousePressed == true) && (y+h-move_tolerance < mouseY && mouseY < y+h+move_tolerance ) && (x-move_tolerance<mouseX && mouseX < x+l+move_tolerance)) {    // Allows to resize the block clicking the stroke height wise
          h = h + dy;
        }
      }
    
      void content(String a) {                                                                      // Displays a string inside the box
        PFont contentfont = loadFont("ClearSans-15.vlw");
        textFont(contentfont);
        fill(themedark);
        textAlign(LEFT);
        rectMode(CORNER);
        text(a, x+10, y+10, l-20, h-20);
      }
    
      int spitx() {                                                                                // Those 4 functions return local class var to the main code.
        return x;
      }
      int spity() {
        return y;
      }
      int spitl() {
        return l;
      }
      int spith() {
        return h;
      }
    }
    

    I tried and keep things nice and clean ( discovered the miraculous auto format tool xD ).

    Once again thank you guys for your awesome help.

  • edited December 2015

    For example my block class now take 7 arguments ( 4 for placement and size and 3 for color )

    If you think 7 arguments are too many, why not take those 4 bounds' parameters and turn 'em into 1 Rectangle. Then those 3 last RGB attributes as 1 Color?

    1. http://docs.Oracle.com/javase/8/docs/api/java/awt/Rectangle.html
    2. http://docs.Oracle.com/javase/8/docs/api/java/awt/Color.html

    Here's a sketch example w/ 3 classes: BlocA, BlocB, & BlocC.

    1. BlocA: constructor demands 7 arguments.
    2. BlocB: constructor demands 2 arguments: BlocB (Rectangle r, Color _c)
      Then it extracts each property from those 2 and assign them to their respective fields:
      int x, y, w, h; & color c;
    3. BlocC: Same as BlocB. But keeps the 2 parameters and gets rid of the 5 fields.

    // forum.Processing.org/two/discussion/14127/
    // beginner-needs-help-regarding-simple-object-programming
    
    // 2015-Dec-24
    
    import java.awt.Color;
    import java.awt.Rectangle;
    
    void setup() {
      Rectangle r = new Rectangle(width>>1, height>>1, width>>2, height>>2);
      println(r);
    
      Color c = new Color(0xA0, 0300, 50);
      println(c);
    
      BlocA ba = new BlocA(width>>1, height>>1, width>>2, height>>2, 0xA0, 0300, 50);
      BlocB bb = new BlocB(r, c);
      BlocC bc = new BlocC(r, c);
    
      exit();
    }
    
    class BlocA {
      int x, y, w, h;
      color c;
    
      BlocA(int _x, int _y, int _w, int _h, color r, color g, color b) {
        x = _x;
        y = _y;
        w = _w;
        h = _h;
        c = color(r, g, b);
      }
    }
    
    class BlocB {
      int x, y, w, h;
      color c;
    
      BlocB(Rectangle r, Color _c) {
        x = r.x;
        y = r.y;
        w = r.width;
        h = r.height;
        c = _c.getRGB();
      }
    }
    
    class BlocC {
      final Rectangle r;
      Color c;
    
      BlocC(Rectangle _r, Color _c) {
        r = new Rectangle(_r);
        c = _c;
      }
    }
    
  • Hey =)

    I didn't see your answer at the time GoToLoop but you're absolutly right, packing those paramaters into a rectangle and color object was the way to go for a cleaner code.

    Thanks again for the help =)

Sign In or Register to comment.