Processing: createShape() behavior changes when Class file extends PShape - processing

I'm just learning Processing. My background is in ActionScript. I'm creating a custom class which draws complex objects. As part of this class, I call createShape() a couple of times. Things worked fine until I decided I needed the custom class to extend PShape. Now it will not recognize the createShape() syntax I'm using, and returns an error that says "createShape() expects parameters like: createShape(PApplet, PShape)"
Here's the function, which returns a PShape object. It works fine.
class MyClass
{
...
PShape makeTriangle1( float w, color c )
{
strokeJoin(BEVEL);
PShape t = createShape(TRIANGLE, 0, 0, w, 0, 0, topBar);
t.setFill(c);
return t;
}
}
But when I do this, it returns the error I've quoted above:
class MyClass extends PShape
{
...
PShape makeTriangle1( float w, color c )
{
strokeJoin(BEVEL);
PShape t = createShape(TRIANGLE, 0, 0, w, 0, 0, topBar);
t.setFill(c);
return t;
}
}
Any ideas? Thanks!

The PShape class has a function named createShape(). You can view it on line 1441 here:
static protected PShape createShape(PApplet parent, PShape src) {
PShape dest = null;
if (src.family == GROUP) {
dest = parent.createShape(GROUP);
PShape.copyGroup(parent, src, dest);
} else if (src.family == PRIMITIVE) {
dest = parent.createShape(src.kind, src.params);
PShape.copyPrimitive(src, dest);
} else if (src.family == GEOMETRY) {
dest = parent.createShape(src.kind);
PShape.copyGeometry(src, dest);
} else if (src.family == PATH) {
dest = parent.createShape(PATH);
PShape.copyPath(src, dest);
}
dest.setName(src.name);
return dest;
}
Notice the arguments for that function are a PApplet and a PShape.
When you extend PShape and call createShape() inside that class, Processing thinks you're trying to call this function. Since your arguments don't match up, you get the error.
To fix this error, you could pass your sketch PApplet into the MyClass class and specifically call the sketch-level createShape() function:
int topBar = 100;
MyClass mc;
void setup() {
size(500, 500);
mc = new MyClass(this);
}
void draw() {
background(0);
shape(mc.makeTriangle1(100, #ff0000), 200, 200);
}
class MyClass extends PShape{
PApplet sketch;
public MyClass(PApplet sketch){
this.sketch = sketch;
}
PShape makeTriangle1( float w, color c )
{
strokeJoin(BEVEL);
PShape t = sketch.createShape(TRIANGLE, 0, 0, w, 0, 0, topBar);
t.setFill(c);
return t;
}
}
However, I would strongly suggest that you refactor your code so that you don't need to extend PShape anymore. It seems very strange to extend a Processing class like that. Chances are you should be using composition instead of inheritance. In other words, your class has-a PShape, not your class is-a PShape.

Related

Select image and create object. Processing 2.0

here is a code snippet from my Image class:
class Image{
public int width;
public int height;
public PImage img;
Image(PApplet parent){
width = 512;
height = 512;
img = new PImage();
img = parent.loadImage("test.jpg");
img.resize(width, height);
}
}
I draw it in the main file in such a way:
image(image.img, 287, 280);
I'd like to choose the image having clicked it:
void mousePressed() {
if (gui.btnOver1) {
selectInput("Choose file:", "fileSelected");
}
}
However, I don't know how to use this function in an OOP way:
void fileSelected(File selection) {
if (selection == null) {
println("Window was closed or the user hit cancel.");
} else {
img = loadImage(selection.getAbsolutePath());
img.loadPixels();
}
}
Thanks for help.
what about adding a method to your class like:
class Image{
public int width;
public int height;
public PImage img;
Image(PApplet parent){
width = 512;
height = 512;
img = new PImage();
img = parent.loadImage("test.jpg");
img.resize(width, height);
}
public void loadNew(path){
img = loadImage(path);
// I don't think you need to .updatePixels() after .loadImage()
}
}
Then you use it like that:
void fileSelected(File selection) {
if (selection == null) {
println("Window was closed or the user hit cancel.");
} else {
// assuming you have an 'image' object of the type Image
image.loadNew(selection.getAbsolutePath());
}
}
Note:
It's been a while since I wrote my last line of Processing code and it may be a bit wrong, but it should answer your question
You could even have a function to draw the Image object, rather than calling the property imgof your image,
like that:
// a method of your class
public void draw(int x, int y){
image(img, x, y);
}
and then inside the main draw() you will call
// always your image object here
image.draw(20, 34);
I hope it helps!

Null Pointer exception in Processing in Array. Tried everything

I am making a 2d side scrolling game and I'm stuck. Im writing the class for the objects which will spawn increasingly and which the Player has to avoid. But sadly I am getting a Nullpointerexception and I cannot figure out why.Before I cleaned up the code in the main and transformed it to a class, the whole thing was working. I think I'm initializing the Array correctly and no variables are left undefined. I've only been using processing for the past months so I might have overseen something.
Thanks a lot for your help
public class Blockfield {
private int Blockcount;
private PImage Blockpic;
private Block block[];
//Constructor
public Blockfield (int Blockcount) {
this.Blockcount = Blockcount;
//new array
block = new Block [Blockcount];
for ( int i=0; i < Blockcount; i++) {
block[i] = new Block( width+Blockpic.width, random (height));
}
}
//Draw method for this class
public void draw () {
for (int i =frameCount/100; i >0; i--) {
image ( Blockpic, block[i].x, block[i].y);
//moves blocks right to left
block[i].x -=7 ;
//spawns block when they leave the screen
if (block[i].x < 0) {
block[i] = new Block( width+Blockpic.width, random (height));
}
}
}
}
class Block {
float x, y;
Block ( float x, float y) {
this.x= x;
this.y= y;
}
}
Main:
Blockfield blockfield;
PImage Blockpic;
void setup () {
size (1291, 900);
blockfield = new Blockfield(100);
Blockpic = loadImage("block2.png");
}
void draw () {
background ( 10);
}
The problem was that I was trying access Blockpic.width in your Blockfield constructor before Blockpic had been assigned. The solution was to load the Image within the constructor of the class.
Working code:
public class Blockfield {
private int Blockcount;
private PImage Blockpic;
private Block block[];
//Constructor
public Blockfield (int Blockcount) {
this.Blockcount = Blockcount;
Blockpic = loadImage("block2.png");
//new array
block = new Block [Blockcount];
for ( int i=0; i < Blockcount; i++) {
block[i] = new Block( width+Blockpic.width, random (height));
}
}
//Draw method for this class
public void draw () {
for (int i =frameCount/100; i >0; i--) {
image ( Blockpic, block[i].x, block[i].y);
//moves blocks right to left
block[i].x -=7 ;
//spawns block when they leave the screen
if (block[i].x < 0) {
block[i] = new Block( width+Blockpic.width, random (height));
}
}
}
}
class Block {
float x, y;
Block ( float x, float y) {
this.x= x;
this.y= y;
}
}
Thanks to everyone for the help!!!

how to crop image with particular shape in Blackberry?

Hi all thanks to read my answer hope you can help me
I am working on Image cropping in blackberry. In my application contain 3 main things.
1)Load the image on the screen
2)select the shape of the cropping area
3)display that cropping image on next screen with out losing its shape
Step1: i can done the image loading part
step2: using Menu i just add the 4 types of shapes
1)Circle
2)Rectangle with rounded shape
3)Star
4)Cloud
using menu when he click on any menu item ,then that particular shape image will display on the screen.
we can give the movement to that image because we have to provide him to select any portion of the image.
step3: After fix the position then we will allow the user to crop using menu.
when he click on menu item " CROP". then we have to crop the image according the shape and that image should display on the next screen
Note: Following code working only for Rectangular shape but i want to
use all shapes
This is my sample code ::
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;
public class ClipMove extends MainScreen{
Bitmap circle_frame,rectangle_frame,star_frame,cloud_frame,image,selected_frame;
BitmapField frmae_field;
private int padding_x=0,padding_y=0;
private VerticalFieldManager vrt_mgr;
public ClipMove() {
//Here my shape images are transparent
circle_frame=Bitmap.getBitmapResource("circle.gif");
rectangle_frame=Bitmap.getBitmapResource("rect1.png");
star_frame=Bitmap.getBitmapResource("star.gif");
cloud_frame=Bitmap.getBitmapResource("cloud.gif");
//this is my actual image to crop
image=Bitmap.getBitmapResource("sample.jpg");
vrt_mgr=new VerticalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight());
setExtent(Display.getWidth(),Display.getHeight());
}
};
vrt_mgr.setBackground(BackgroundFactory.createBitmapBackground(image));
add(vrt_mgr);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("Rect",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=rectangle_frame;
frmae_field=new BitmapField(rectangle_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Circle",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=circle_frame;
frmae_field=new BitmapField(circle_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Star",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=star_frame;
frmae_field=new BitmapField(star_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Cloud",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=cloud_frame;
frmae_field=new BitmapField(cloud_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Crop",0,0) {
public void run() {
// TODO Auto-generated method stub
Field f=vrt_mgr.getField(0);
// XYRect rect=getFieldExtent(f);
XYRect rect=new XYRect(padding_x, padding_y,frmae_field.getBitmapWidth(),frmae_field.getBitmapHeight());
Bitmap crop = cropImage(image, rect.x, rect.y,
rect.width, rect.height);
synchronized (UiApplication.getEventLock()) {
UiApplication.getUiApplication().pushScreen(new sampleScreen(crop,selected_frame));
}
}
});
}
protected boolean navigationMovement(int dx, int dy, int status, int time) {
if(frmae_field!=null){
padding_x=padding_x+dx;
padding_y=padding_y+dy;
XYEdges edge=new XYEdges(padding_y, 0, 0, padding_x);
frmae_field.setPadding(edge);
vrt_mgr.invalidate();
return true;
}else {
return false;
}
}
public void DisplayMessage(final String str)
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.inform(str);
}
});
}
public XYRect getFieldExtent(Field fld) {
int cy = fld.getContentTop();
int cx = fld.getContentLeft();
Manager m = fld.getManager();
while (m != null) {
cy += m.getContentTop() - m.getVerticalScroll();
cx += m.getContentLeft() - m.getHorizontalScroll();
if (m instanceof Screen)
break;
m = m.getManager();
}
return new XYRect(cx, cy, fld.getContentWidth(), fld.getContentHeight());
}
// this logic only useful for rectangler shape
public Bitmap cropImage(Bitmap image, int x, int y, int width,int height) {
Bitmap result = new Bitmap(width, height);
Graphics g = Graphics.create(result);
g.drawBitmap(0, 0, width, height, image, x, y);
return result;
}
}
//this is my next screen to show the croped image
class sampleScreen extends MainScreen
{
VerticalFieldManager manager;
public sampleScreen(final Bitmap img,final Bitmap back) {
manager=new VerticalFieldManager(){
protected void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, img.getWidth(), img.getHeight(), img, 0, 0);
super.paint(graphics);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout( img.getWidth(), img.getHeight());
setExtent( img.getWidth(), img.getHeight());
}
};
BitmapField field=new BitmapField(back);
field.setPadding(0, 0, 0, 0);
manager.add(field);
add(manager);
}
}
My screen shots:
By using another dummy image, it is possible to determine which pixels of the original image needs to be deleted (we can make them transparent). Though It may not be the optimal solution, but it can be applied for any geometric figure we can draw on BlackBerry.
Check following steps:
Create a new Bitmap image (dummyImage) of same dimension as the
source image (myImage).
Draw (fill) the target geometric shape on it using a defined color
(fillColor).
Now for each pixel of myImage, if the same pixel of dummyImage
contains fillColor then keep it unchanged, else make this pixel
fully transparent by assigning zero (0) to it.
Now myImage is almost ready, need to trim this image for
transparent pixel removal.
Following code will apply a circular crop on a image. (but won't trim the transparent pixels).
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
class MyScreen extends MainScreen {
private Bitmap myImage = Bitmap.getBitmapResource("img/myImage.jpeg");
private BitmapField _bf;
public MyScreen() {
_bf = new BitmapField(myImage);
adjustBitmapMargin();
add(_bf);
}
private void adjustBitmapMargin() {
int x = (Display.getWidth() - myImage.getWidth()) / 2;
int y = (Display.getHeight() - myImage.getHeight()) / 2;
_bf.setMargin(y, 0, 0, x);
}
protected void makeMenu(Menu menu, int instance) {
menu.add(miCropCircle);
super.makeMenu(menu, instance);
}
private MenuItem miCropCircle = new MenuItem("Crop - Circle", 0, 0) {
public void run() {
cropImage();
}
};
private void cropImage() {
int width = myImage.getWidth();
int height = myImage.getHeight();
// get original data from the image
int myImageData[] = new int[width * height];
myImage.getARGB(myImageData, 0, width, 0, 0, width, height);
// get default color of a newly created bitmap
int defaultColors[] = new int[1 * 1];
(new Bitmap(1, 1)).getARGB(defaultColors, 0, 1, 0, 0, 1, 1);
int defaultColor = defaultColors[0];
int fillColor = Color.RED;
int diameter = 200;
// dummy data preparation
Bitmap dummyImage = new Bitmap(width, height);
Graphics dummyImageGraphics = Graphics.create(dummyImage);
dummyImageGraphics.setColor(fillColor);
int startX = width / 2 - diameter / 2;
int startY = height / 2 - diameter / 2;
dummyImageGraphics.fillArc(startX, startY, diameter, diameter, 0, 360);
int dummyData[] = new int[width * height];
dummyImage.getARGB(dummyData, 0, width, 0, 0, width, height);
// filling original data with transparent value.
int totalPixels = width * height;
for (int i = 0; i < totalPixels; i++) {
if (dummyData[i] == defaultColor) {
myImageData[i] = 0;
}
}
// set new data
myImage.setARGB(myImageData, 0, width, 0, 0, width, height);
// redraw screen
_bf.setBitmap(myImage);
adjustBitmapMargin();
invalidate();
// free up some memory here
defaultColors = null;
dummyImage = null;
dummyData = null;
dummyImageGraphics = null;
}
}
Output of the above code:

CDC Help for color an object

hi
There is a function in C++ Visual studio CDC::ExtFloodFill(int x, int y, COLORREF crColor,UINT nFillType);
my question is that what we suppose to write in place of
int x , int y, COLORREF crColor, UINT nFillType
Like if I have a Object Which I want to Color How to do it
enter code here
#include "afxwin.h"
class fr : public CFrameWnd
{
public:
CPoint st;
CPoint en;
fr()
{
Create(0,"First Frame");
}
//////////////////////
void OnLButtonDown(UINT fl,CPoint p )
{
st.x=p.x;
st.y=p.y;
}
//////////////////////
void OnLButtonUp(UINT fl,CPoint r)
{
en.x=r.x;
en.y=r.y;
CClientDC d(this);
d.Ellipse(st.x,st.y,en.x,en.y);
}
void OnRButtonDown(UINT fl,CPoint q)
{
CClientDC e(this);
e.ExtFloodFill(............);
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(fr,CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()
class app : public CWinApp
{
public:
int InitInstance()
{
fr*sal;
sal=new fr;
m_pMainWnd=sal;
sal->ShowWindow(1);
return true;
}
};
app a;
For your example, ExtFloodFill (or any other version of FloodFill) isn't really the right choice.
Instead, you normally want to set the current brush to the color/pattern you want, then draw your object (and it'll automatically be filled with the current brush). Let's say, for example, that you want to draw a red ellipse:
CMyView::OnDraw(CDC *pDC) {
CBrush red_brush;
red_brush.CreateSolidBrush(RGB(255, 0, 0));
pDC->SelectObject(red_brush);
pDC->Ellipse(0, 0, 100, 50);
}
Edit: Okay, if you really insist it has to be a flood-fill, and you're doing it in response to a button click, you'd probably do something like this:
void CYourView::OnRButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CBrush blue_brush;
blue_brush.CreateSolidBrush(RGB(0, 0, 255));
dc.SelectObject(blue_brush);
dc.ExtFloodFill(point.x, point.y, RGB(0, 0,0), FLOODFILLBORDER);
CView::OnRButtonDown(nFlags, point);
}

QGraphicsScene/QGraphicsView performance

I am using QGraphicsScene/QGraphicsView pair in my project
I have performance issue with this pair.
I added my custom graphics items to scene and displayed the contents with view. After that my custom graphics items paint method continuously called by scene(just like infinite loop). This makes %25 of CPU usage(approximately 400 items on scene). What may cause this behaviour?
Here is one my item implementation:
class LevelCrossingItem : public QGraphicsWidget
{
public:
LevelCrossingItem(QString _id,qreal _x,qreal _y);
~LevelCrossingItem();
QRectF boundingRect() const;
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = 0 */);
void readStateBits();
bool isClosed();
bool isGateArmBroken();
bool isOpenedDuringRouteTanzimCompleted();
bool hasDataConsistencyWarning();
int type() const {return Type;}
private slots:
void setVisible(bool);
private:
enum {Type = FIELDLEVELCROSSING};
QString m_id;
QString m_source;
short m_closedState;
short m_brokenGateArmState;
short m_openedDuringRouteTanzimCompletedState;
short m_dataConsistencyWarningState;
QBitArray stateBitArray;
qreal x,y;
QSvgRenderer *renderer;
};
#include "levelcrossing.h"
LevelCrossingItem::LevelCrossingItem(QString _id,qreal _x,qreal _y):m_id(_id),x(_x),y(_y),stateBitArray(4)
{
m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
renderer = new QSvgRenderer;
setStateArray(stateBitArray);
setZValue(-0.5);
}
LevelCrossingItem::~LevelCrossingItem()
{
delete renderer;
}
void LevelCrossingItem::setVisible(bool visible)
{
QGraphicsItem::setVisible(visible);
}
QRectF LevelCrossingItem::boundingRect() const
{
return QRectF(QPointF(x,y),sizeHint(Qt::PreferredSize));
}
QSizeF LevelCrossingItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
return QSizeF(50,270);
}
void LevelCrossingItem::readStateBits()
{
m_closedState = property("Closed").toInt();
m_brokenGateArmState = property("Broken").toInt();
m_openedDuringRouteTanzimCompletedState = property("OpenedOnRouteWarning").toInt();
m_dataConsistencyWarningState = property("DataConsistencyWarning").toInt();
stateBitArray.setBit(0,qvariant_cast<bool>(m_closedState));
stateBitArray.setBit(1,qvariant_cast<bool>(m_brokenGateArmState));
stateBitArray.setBit(2,qvariant_cast<bool>(m_openedDuringRouteTanzimCompletedState));
stateBitArray.setBit(3,qvariant_cast<bool>(m_dataConsistencyWarningState));
setStateArray(stateBitArray);
}
void LevelCrossingItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
Q_UNUSED(option);
Q_UNUSED(widget);
readStateBits();
m_closedState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("closed")
: m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
m_brokenGateArmState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("broken")
: m_source = m_source;
if(m_openedDuringRouteTanzimCompletedState == Positive)
{
setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),true);
if(stateChanged())
emit itemAlarmOccured(m_id,LevelCrossingIsOpenDuringTanzimCompleted);
}
else
setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),false);
if(m_dataConsistencyWarningState == Positive)
{
setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),true);
if(stateChanged())
emit itemAlarmOccured(m_id,LevelCrossingDataConsistency);
}
else
setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),false);
renderer->load(m_source);
renderer->render(painter,boundingRect());
}
bool LevelCrossingItem::isClosed()
{
return m_closedState == Positive;
}
bool LevelCrossingItem::isGateArmBroken()
{
return m_brokenGateArmState == Positive;
}
bool LevelCrossingItem::isOpenedDuringRouteTanzimCompleted()
{
return m_openedDuringRouteTanzimCompletedState == Positive;
}
bool LevelCrossingItem::hasDataConsistencyWarning()
{
return m_dataConsistencyWarningState == Positive;
}
I read x and y coordinates from xml file. For this item x and y coordinates are 239,344 respectively
Most likely your graphics item has mistakes in the implementation. I had similar behavior, but I was unable to figure out what exactly causes it. I suspect that this happens when you draw outside of the bounding rect. This triggers some clean up routine, which in turn causes redraw of the item, and here goes the loop. Eventually I resolved the issue by carefully inspecting the implementation of my custom graphics item and making sure that:
These is no painting outside of the MyGraphicsItem::boundingRect. Use painter->setClipRect(boundingRect())
MyGraphicsItem::shape does not cross with the MyGraphicsItem::boundingRect.
If you override any other QGraphicsItem functions, make sure that your implementation is correct.
Hope this helps. Feel free to post the source code of your graphics item, it will be easier to find the problem.

Resources