Making canvas' drawline clickable - java

Based on this answer, I created a arrayList of rectF.
Technique to make a canvas drawLine() clickable?
here's the logic of my code :
List<RectF> rectFs;
Point pt1;
Point pt2;
then
path.moveTo(pt1.x, pt1.y);
path.lineTo(pt2.x, pt2.y);
path.computeBounds(rectF, true);
rectFs.add(rectF);
and then, I have this method to check the clicked and the rectF arrayList.
void lineHighighted(Point pt) {
int ct = 0;
for(RectF rectF : rectFs) {
if(rectF.contains(pt.x, pt.y)) {
ct++;
Log.d(tag, ct + "HERE");
}
}
}
my problem is, sometimes, the whole arraylist is selected or "called" even I didn't touch that "line".
Any wrong in my code?
Thanks in advance.
ADDITIONAL :
I found out that after adding this code in my canvas :
path.moveTo(coor1[0], coor1[1]);
path.lineTo(coor2[0], coor2[1]);
canvas.drawPath(path, paint2);
path.computeBounds(rectf, true);
my previous result :
it becomes like this :

It might be!Because i don't see your code of interaction with canvas ill post the code which fully working.The logic is that one line mustn't overlay another one in case to proper function.hope i could help you.
// setting where I will draw the ImageView for taking pictures
// rec is used for onInterceptTouchEvent. I pass this from the
// highest to lowest layer so that when this area of the screen
// is pressed, it ignores the TouchView events and passes it to
// this activity so that the button can be pressed.
rec.set((int)((double)mScreenWidth*.85),
(int)((double)mScreenHeight*.10) ,
(int)((double)mScreenWidth*.85)+mButtonDrawable.getMinimumWidth(),
(int)((double)mScreenHeight*.70)+mButtonDrawable.getMinimumHeight());
mButtonDrawable = null;
By This Logic you can use whatever you want in this logic it lets click happen not being overlaid

Related

Double buffering swt

I'm creating simple app i have Tree object where i store filenames when user choose one SWTImageCanvas.loadImage(path) is being called. Every image has some points defined so points are displayed as gc.fillOval. When user move mouse over oval it name is being displayed i achive this by setting some additional variable and using SWTImageCanvas.redraw() method. Such redrawing cause blinking of canvas so i thought about double buffering i have read some tutorials about it but when i'm trying to run it my image is hovered by white layer with ovalls on it here is my drawing function
private void drawStations(Event e) {
Rectangle clientRect = mainSWTImageCanvas.getClientArea();
if(mainSWTImageCanvas.getSourceImage()!=null)
{
if(mainSWTImageCanvas.getScreenImage()!=null)
mainSWTImageCanvas.getScreenImage().dispose();
Image screenImage = new Image(mainSWTImageCanvas.getDisplay(),clientRect.width,clientRect.height);
this.gc = new GC(screenImage);
//drawing ovals on gc
.
.
.
this.gc.drawImage(screenImage, 0, 0);
this.gc.dispose();
e.gc.drawImage(screenImage, 0, 0);
}
It turns out that double buffering in swt display can by done by passing SWT.DOUBLE_BUFFERED in constructor.

Setting text on Label (Actor) stops drawing

I just can't figure this, and I am pulling my hair out right now!!
I have a Stage with a Label added to it, I set everything up and the first time I call Stage.draw() everything works fine. However, as soon as I set the text of the Label nothing gets drawn. Funny thing is, when I don't change the text it draws perfectly as expected, but when I call label.setText("THE TEXT") it just doesn't draw.
I have stepped through my code and I have noted down the height, width, x and y values before and after setting text of the Label, and they are all the same (before and after).
Also, when I draw the Stage it's drawn above a Sprite, and positioning the Sprite is based on the Label's position.
The Sprite draws fine before I set text on the Label and after.
PS: I have also made sure that the Sprite is not drawn "over" the Label.
This is my setup:
I have a MainGame class that renders a Player class, when ever the back button is pressed the Sprite with the Stage gets drawn, or should get drawn.
spriteBatch.begin();
player.update(spriteBatch, delta);
spriteBatch.end();
// the pause menu is drawn with a separate sprite batch as it needs to be in middle relative to the screen and above everything else
if (player.isPaused()){
messageSpriteBatch.begin();
messageSprite.draw(messageSpriteBatch);
messageSpriteBatch.end();
messageStage.draw(); // the stage doesn't seem to be getting drawn
}
Player class - update method
if (!paused){
// removed for clarity
}else{
// on MainGame class we render a small box with one of the following messages
// READY
// PAUSE
// QUIT?
// GAME OVER
if (Gdx.input.justTouched()){
paused = false;
}
spriteBatch.setProjectionMatrix(camera.combined);
camera.update();
}
messageSpriteBatch = new SpriteBatch();
messageStage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
messageFont = new BitmapFont(Gdx.files.internal("fonts/fontfile.fnt"));
messageStyle = new LabelStyle();
messageStyle.font = messageFont;
messageLabel = new Label("READY", messageStyle);
This is how I initialise my Label, Sprite and Stage:
float fontScaleX = Gdx.graphics.getWidth()/SCALE_X_DIVIDER;
float fontScaleY = Gdx.graphics.getHeight()/SCALE_Y_DIVIDER;
messageLabel.setFontScale(fontScaleX*1.4f, fontScaleY*4.2f);
messageLabel.setPosition((messageStage.getWidth()/2)-((messageLabel.getWidth()/2)*messageLabel.getFontScaleX()), (messageStage.getHeight()/2)-((messageLabel.getHeight()/2)*messageLabel.getFontScaleY())+(player.getScoreboard().getSize().y/2));
messageStage.addActor(messageLabel);
messageStage.act();
messageTexture = new Texture(Gdx.files.internal("images/message_background.png"));
messageSprite = new Sprite(messageTexture);
messageSprite.setSize((messageLabel.getWidth()*messageLabel.getFontScaleX())*1.5f, (messageLabel.getHeight()*messageLabel.getFontScaleY())*3);
messageSprite.setPosition(messageLabel.getX()-(messageSprite.getWidth()/6), messageLabel.getY()-messageSprite.getHeight()/2);
Please help me, before I get bald xD
Well the width and height of the label is usually set once when creating the Label, matching the width and height of the initial text passed to the Constructor. You of course can make it bigger by setting the width and height later on. Then you could also use alignments by the way...
Are you using any special characters when changing the text, so the font has a problem with that?
Maybe posting some code could give more insights...
Haha, well, I found out what was up, it was my font file, you see when I was editing it, I used the text READY, so when I saved it, I didn't know that the text written is what is saved, so when I looked at the font.png file, I found that it only contained the letters ADERY.
Thanks for the help anyway =]

Slick2d, How can i draw a string on screen for a few seconds?

I've been trying to figure this out, all I want to do is be able to draw a string for longer than just a frame, but when I call it in the method I want it to flash up then disappear immediately, any advice would be appreciated :) I'm using something like this:
g.drawString("You got a Key!", 100, 100);
I'm doing this in a method which is called after an Item is picked up
public void addItemFound(Graphics g){
ip.mainInventory[ip.getFirstEmptyStack()] = getItemStackFound();
System.out.println(this.getItemFound() + " added");
g.drawString("You Got a Key!", 100, 100);
}
That's the full method if you were interested :) Thanks!Also apologies for the dumb question, i'm a newbie to this :P
I believe that the best way to do this project would be to draw the scene at regular intervals e.g. 10 milliseconds using a Thread.sleep(). This way, you can simply add a variable to show the message for, say, 100 loops (1 second) like this:
private LinkedList<String> drawStringList= new LinkedList<>();
private LinkedList<Integer> drawStringTimeout= new LinkedList<>();
private LinkedList<Integer[]> drawStringPos= new LinkedList<>();
public void addText(String stringToWrite, int posX, int posY, int timeOut) {
drawStringList.add(stringToWrite);
int[] pos = new int[2];
pos[0] = posX;
pos[1] = posY;
drawStringPos.add(pos);
drawStringTimeout.add(timeOut);
}
private void mainLoop() {
...items to be drawn here...
for(int i=0;i<drawStringList.size();i++){
g.drawString(drawStringList.get(i),drawStringPos.get(i)[0],drawStringPos.get(i)[1]);
drawStringTimeout.set(i,drawStringTimeout.get(i)-1);
if(drawStringTimeout.get(i)<=0) {
drawStringList.remove(i);
drawStringTimeout.remove(i);
drawStringPos.remove(i);
}
}
try { Thread.sleep(10); } catch (Exception e) {}
}
In this code, you must add the string you want to draw to drawStringList, add the number of loops you want it to stay for to drawStringTimeout and add the position you would like to draw it in to drawStringPos as an array (you could use a point if you wanted to). I have made a method to do this.
I don't know what Dan300 is trying to tell you to do but that's way, way, way over complicated. Slick2D works on gamestates:
http://slick.ninjacave.com/javadoc/org/newdawn/slick/state/GameState.html
The gamestate has a method called render(). The render() is called every single cycle of the loop to update your screen with drawing information. If you want to draw the text on the screen for a longer time you should be drawing the text somewhere within the stack space of this render() function.
What is happening now is you have a function with one specific purpose that only exists every so briefly: add an item to the player. The game comes across this statement and when adding an item within that 1 cycle the text will be drawn. But the next cycle when the player isn't picking up an item it won't come by that drawString statement and you won't have your string on your screen longer than 1 game cycle.

Android Missile sprite

I am trying to make a onTouchEvent to create a missile that will launch from my character sprite and forward.
I have this working using
if (missdraw = true){
canvas.drawBitmap(missile,missilex,missileY,null);
missilex = missilex + 14;
missdraw = false;
}
in my onDraw method, but the problem is it will only create one at a time.
I tried to create a class to deal with this, but this just causes an error and crashes when i try to fire.
here is what i use for the class: (this is in the ondraw in my gameview)
for (Batcher missile : missiles ){
missile.onDraw(canvas);
}
this is in the class
public Batcher(List<Batcher> temps, ScreenActivity newView, float x,
float y, Bitmap missile){
this.x = 1;
this.y = 2;
this.missile = missile;
}
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(missile, x,y, null);
}
I would appreciate any help, but also if you could explain how it would work, instead of just code, as im quite new to programming, and really need to understand what im doing and why im doing it, rather than just copying peoples code because it works.
Cheers Phil.
Your concepts are pretty good, actually. There are a few things I don't quite understand about the code samples you posted up, I'll try to translate into what I'd do and you can tell me if I'm doing it wrong :)
in your game class you need (and it looks like you have) a list of Missiles:
LinkedList<Batcher> missiles;
In your onTouch(), however a missile is created -
missiles.add(new Batcher(missilex, missiley, missile));
you now have a collection of missiles. Note that I didn't include the list in the constructor of your batcher, because an object should never need to know that it's a part of a collection. All it needs to know is how to draw itself and where. Since I assume that all of your missiles will be added to or removed from the screen frequently, while only having a few on screen at a time, I've used a LinkedList, which is fast for adding and removing, but slow for accessing a specific missile. If you needed to access specific items in the collection and the collection didn't change very much, you would use an ArrayList instead. on to onDraw - as you have it the missile draws itself, which is fine, but I prefer to let the View do the drawing, with the missile telling it where it should be drawn -
for (Batcher missile : missiles ){
missile.setX(missile.getX() + 14); // to make it move
if (missile.getX() > canvas.gedWidth()) { //check if it's left the screen
missiles.remove(missile); // Remove it
}
else { //perform drawing
canvas.drawBitmap(missile.getBitmap(), missile.getX(), missile.getY(), null);
}
}
Hopefully that'll do it for you, but feel free to let me know if there's anything you'd like me to explain more!

Has anyone done crosshairs that follow the mouse in JFreeChart?

We are using JFreeChart to make XY plots and we have a feature request to do a crosshair that moves along with the mouse and highlights the data point that most closely maps to the x-value of the mouse. You can see a similar example at Google Finance - http://www.google.com/finance?q=INDEXDJX:.DJI,INDEXSP:.INX,INDEXNASDAQ:.IXIC.
Those Google charts only highlight the current value (we want to do that and also show crosshairs), but they show the live mouse interaction we are looking for.
Anyone have any elegant suggestions?
Thanks.
I got this working using a mouse listener and the CrosshairOverlay class. After I get back from holiday travel, I will post my code. It ended up being not too difficult.
Sorry, I forgot about this!
First, you want to calculate the x, y values for where you want your crosshair. For me, I wanted it to move along the points of our line, so I calculated the closest x value and used that data pair for x, y.
Then I call this method:
protected void setCrosshairLocation(double x, Double y) {
Crosshair domainCrosshair;
List domainCrosshairs = crosshairOverlay.getDomainCrosshairs();
if (domainCrosshairs.isEmpty()) {
domainCrosshair = new Crosshair();
domainCrosshair.setPaint(BlueStripeColors.LIGHT_GRAY_C0);
crosshairOverlay.addDomainCrosshair(domainCrosshair);
}
else {
// We only have one at a time
domainCrosshair = (Crosshair) domainCrosshairs.get(0);
}
domainCrosshair.setValue(x);
if (y != null) {
Crosshair rangeCrosshair;
List rangeCrosshairs = crosshairOverlay.getRangeCrosshairs();
if (rangeCrosshairs.isEmpty()) {
rangeCrosshair = new Crosshair();
rangeCrosshair.setPaint(BlueStripeColors.LIGHT_GRAY_C0);
crosshairOverlay.addRangeCrosshair(rangeCrosshair);
}
else {
// We only have one at a time
rangeCrosshair = (Crosshair) rangeCrosshairs.get(0);
}
rangeCrosshair.setValue(y);
}
}
Note that crosshairOverlay is an instance of CrosshairOverlay.
JFreeChart can't render a sub-section of a chart, so you'll want to do something that doesn't require repainting the chart. You could write your chart to a BufferedImage and store that in memory, then have a custom component which uses the buffered chart as the background image, and draws crosshairs and other popup windows over it.
There are methods in JFreeChart to get the data point for a given coordinate on a rendered chart. Don't recall what these are off the top of my head. Depending on your needs, you might consider rendering your own chart data, it's not as hard as you'd think.
The first thing that comes to my mind would be to write a custom Cursor and set it on your chart. It can have a reference to the chart and highlight the x value that's consistent with the Cursor's x/y location.
This worked for me. I set the
chartPanel.addChartMouseListener(new ChartMouseListener() {
public void chartMouseMoved(ChartMouseEvent event)
{
try
{
double[] values = getCrossHairValue(event);
plot.clearRangeMarkers();
plot.clearDomainMarkers();
Marker yMarker = new ValueMarker(values[1]);
yMarker.setPaint(Color.darkGray);
plot.addRangeMarker(yMarker);
Marker xMarker = new ValueMarker(values[0]);
xMarker.setPaint(Color.darkGray);
plot.addDomainMarker(xMarker);
chartPanel.repaint();
} catch (Exception e)
{
}
}
}

Categories