I want make undo/redo on pbitmap/canvas, but i have got problems with sending a linkedarray between drawhandler.java to panel.java ..
errors:
Can only iterate over an array or an instance of java.lang.Iterable
LinkedArray cannot be resolved to a type
public void onDrawAll(LinkedArray paths, Paint paint); <-----the error is on this line
All my code can be seen here
Maybe you wanted to write LinkedList instead of LinkedArray?
I don't know in the standard java api a such class LinkedArray, or I am missing something, or that class is from a third party library you use.
public interface OnDrawListener
{
public void onDrawShape(Shape shape, Paint paint); // narišeš shape dokončno
public void onDrawShapeTemp(Shape shape, Paint paint); // narišeš shape, in ga potem ko je narisan, izbrišeš, če shape ni freehand
public void onDrawAll(LinkedArray<Path> paths, Paint paint); <-----there is errror
}
Related
I have the following situation I want to solve. I wrote my own small drawing engine based on a Canvas. I created for every renderable a base class, for example, line, text, point, etc. From these base classes, I created a few derived entity classes. I also implemented a layer management system which is based on an observer-pattern to toggle the visibility of the derived entity classes. So far so good.
Every derived entity class has its own onDraw function where something is drawn on the canvas e.g
#Override
public void onDraw(Canvas canvas) {
if(isVisible) {
if (p1X != 0 && p1Y != 0 && p2X != 0 && p2Y != 0) {
canvas.drawLine(
p1X,
p1Y,
p2X,
p2Y,
paint
);
}
}
}
The crucial part I want to improve is
if(isVisible){
...
}
I really want to do something like this
#isVisible
#Override
public void onDraw(Canvas canvas) {
...
}
If I would do this in Python, I would write a Decorator to wrap the onDraw function.
But well, I want to write in Java and I'm a little bit clueless about how to do it. Maybe with an annotation (as I have shown it above as an idea), or are there other ways to do it?
I am developing a Watch Face for android wear. I want to make the Canvas hardware accelerated.
In manifest I declared it like bellow
<application
android:hardwareAccelerated="true"
..>
<service
android:name=".WatchFaceMain"
android:hardwareAccelerated="true"
..>
</application>
But when I checked it from inside of My onDraw(Canvas canvas, Rect bounds) method canvas.isHardwareAccelerated() returns false. which clearly means my canvas is not hardware accelerated.
#Override
public void onDraw(Canvas canvas, Rect bounds) {
...
boolean isAccelarated = canvas.isHardwareAccelerated();
.......
}
How do I make this canvas Hardware Accelerated?
Finally found a solution for this issue. Though it wasn't a straight forward or easy solution.
First I got to copy the whole android.support.wearable.watchface.CanvasWatchFaceService class from librar, which my WatchFaceMain class extended.
Then I had to edit the draw() Method inside Engine Class like bellow
public abstract class CanvasWatchFaceService extends WatchFaceService {
.....
public class Engine extends android.support.wearable.watchface.WatchFaceService.Engine {
...
private void draw(SurfaceHolder holder) {
this.mDrawRequested = false;
Canvas canvas = holder.getSurface().lockHardwareCanvas();
if(canvas != null) {
try {
this.onDraw(canvas, holder.getSurfaceFrame());
} finally {
holder.getSurface().unlockCanvasAndPost(canvas);
}
}
}
}
}
I edited two lines inside onDraw like bellow.
from
Canvas canvas = holder.lockCanvas();
To
Canvas canvas = holder.getSurface().lockHardwareCanvas();
And From
holder.unlockCanvasAndPost(canvas);
To
holder.getSurface().unlockCanvasAndPost(canvas);
I still wonder why did CanvasWatchFaceService didn't offer any easier way to request for a hardware accelerated canvas!
More detail solution is available here in this Article.
Hopefully this answer helps someone else too.
With newer versions of the SDK, it's much easier. The CanvasWatchFaceService.Engine class has a boolean useHardwareCanvas constructor parameter. In your subclass, call the constructor as needed:
public Engine() {
super(true);
}
With the new APIs https://developer.android.com/reference/kotlin/androidx/wear/watchface/WatchFaceService, use CanvasType.HARDWARE
override suspend fun createWatchFace(
surfaceHolder: SurfaceHolder,
watchState: WatchState,
complicationSlotsManager: ComplicationSlotsManager,
currentUserStyleRepository: CurrentUserStyleRepository
) = WatchFace(
WatchFaceType.ANALOG,
object : Renderer.CanvasRenderer2<MySharedAssets>(
surfaceHolder,
currentUserStyleRepository,
watchState,
CanvasType.HARDWARE,
interactiveDrawModeUpdateDelayMillis = 16,
clearWithBackgroundTintBeforeRenderingHighlightLayer = true
) {
This is my current render method on my level in my Libgdx game. I am trying to draw a BitmapFont on my level's top right corner but all I'm getting is a bunch of white boxes.
#Override
public void render(
float delta ) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
this.getBatch().begin();
//myScore.getCurrent() returns a String with the current Score
font.draw(this.getBatch(), "Score: 0" + myScore.getCurrent(), 600, 500);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
this.getBatch().end();
}
I would like to add the score font into some kind of an actor and then do a scene.addActor(myScore) but I don't know how to do that.
I followed Steigert's tutorial to create the main game class that instantiates the scene, font, in the AbstractLevel class that is then extended by this level.
So far, I'm not using any custom font, just the empty new BitmapFont(); to use to default Arial font. Later I would like to use my own more fancy font.
Try moving the font.draw to after the stage.draw. Adding it to an actor would be very simple, just create a new class and Extend Actor Like such
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Actor;
public class Text extends Actor {
BitmapFont font;
Score myScore; //I assumed you have some object
//that you use to access score.
//Remember to pass this in!
public Text(Score myScore){
font = new BitmapFont();
font.setColor(0.5f,0.4f,0,1); //Brown is an underated Colour
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
font.draw(batch, "Score: 0" + myScore.getCurrent(), 0, 0);
//Also remember that an actor uses local coordinates for drawing within
//itself!
}
#Override
public Actor hit(float x, float y) {
// TODO Auto-generated method stub
return null;
}
}
Hope this helps!
Edit 1:
Also try System.out.println(myScore.getCurrentScore()); Just to make sure that that isn't the issue. You can just get it to return a float or an int and when you do the "Score:"+ bit it will turn it into a string itself
Well, in this case, you may need to call this.getBatch().end first. Like this:
mSpriteBatch.begin();
mStage.draw();
mSpriteBatch.end();
//Here to draw a BitmapFont
mSpriteBatch.begin();
mBitmapFont.draw(mSpriteBatch,"FPS",10,30);
mSpriteBatch.end();
I don't know why, but it works for me.
I have solved similar problem with white boxes by closing batch before starting drawing stage. That is because the stage.draw() starts another batch and invalidates the previous batch not ended with end().
So in current example I would move this.getBatch().end() before drawing stage:
...
font.draw(this.getBatch(), "Score: 0" + myScore.getCurrent(), 600, 500);
this.getBatch().end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
If you are using Scene2D try using stage and actors. There is no need to write long codes, check for the MTX plugin that is very easy to use. You can create an awesome user experience
http://moribitotechx.blogspot.co.uk/
I use a surfaceview to draw a pie chart in Android. In order to know how big the pie slice should be I need to pass a parameter to the onDraw() method. How can I do this? Inside the onDraw() I make a query to a datahelper-class that fetches the right data.
I tried to call a static function in one Activity from the onDraw, and which function returned an integer. But I want something more dynamic, so I can send the integers I need to from the Activity to the onDraw and just get the result in form of a pie chart.
Any suggestions?
One of solutions can be like this:
public class MySurfaceView extends SurfaceView
{
private MyParameter parameter;
public void setParameter(MyParameter parameter)
{
this.parameter=parameter;
}
#Override
public void onDraw(Canvas canvas)
{
if(this.parameter==null)
return; //nothing to draw...
//draw here...
}
}
//somewhere in code
MySurfaceView sView=(SurfaceView )findViewById(R.id.pie_chart);
//
sView.setParameter(new MyParameter(100,2000, false));
}
#Override
protected void onDraw(Canvas canvas)
{
//Note:I do not want to use the canvas object from this function param
//If i do so its working , But i would like to understand why the following is not working
Canvas c =new Canvas();
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
c.drawText("HELLO CANVAS",200,300,paint);
}
MORE CODE
public class graphicProj extends Activity {
private Canvas canvas;
#Override
public void onCreate(Bundle savedInstanceState) {
{
....
SimpleView simpleview_obj = new SimpleView(this);
setContentView(simpleview_obj);
simpleview_obj.onDraw(canvas);
.....
new GetData().execute();
}
private static class SimpleView extends View {
private ShapeDrawable mDrawable = new ShapeDrawable();
....
protected void onDraw(Canvas canvas) {
//draw graphic objects
....
}
}
public class GetData extends AsyncTask<Void, String, Void> {
#Override
protected void onPreExecute() {
Log.d("PROJ","STARTIN");
}
#Override
protected Void doInBackground(Void... unused) {
////My calculation and reading frm DataStream
}
#Override
protected void onProgressUpdate(String... data) {
//I Keep updating the result...
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
canvas.drawText(result, 200, 300, paint);
}
#Override
protected void onPostExecute(Void unused) {
Log.d("PROJ","END");
}
}
}
Not here or in your other question have you provided enough information on why you can't do that. There is no reason to draw on a new canvas instead of the already existing one.
The code is not working because your new Canvas c isn't assigned to anything. Its like creating a String myString for a log but never using Log.d(tag, myString)
edit (after reading all the comments)
If you calculate a value in your onCreate() and want to display that value in your onDraw(), that simply do that. Store the result in a member variable and you can access it in the onDraw().
Otherwise: Please provide your complete code. I guess you just do it way more complex than it should be...
edit2
Your code is a bit messy and does a lot of stuff in areas where you shouldn't do it. So drawing inside the onProgressUpdate() is seriously wrong. You should encapsulate your calculation and drawing.
What you should do (I recommend using SurfaceView instead of View, anyway...):
You should start your AsynchTask which updates the string you want to draw. The string should be a variable inside your View, where you use it for drawing.
The drawing itself should be called by a drawing thread (I remember: use the SurfaceView instead of the View as a parent class). Inside that onDraw() you should just use your paint object, the given canvas and the string you want to draw (don't forget to make the paint variable also a member variable to prevent recreating the same object over and over again for performance/memory reasons).
If you do not know how to work with a SurfaceView or if you want to learn how you could work with a drawing thread please read my tutorial about 2d drawing: www.droidnova.com/2d-tutorial-series
A short last sentence: You did a lot of things in the right way, you just mixed up with the places where you do it. You should try to rethink what you really want to achieve and how it could be done the easiest way. Maybe my tutorial helps to clear your mind a bit.