I am trying to program an androd application where if there is input on two places of the screen in sucsession then it will draw a line between the two points. I have already set up "X" and "Y" values that work and columns and rows are defined by the "X" and "Y" values. After those i have an IF statement that needs to draw a line between the two points. Say if column one and row two are selected and then colum one and row three are selcted I want a line to be drawn between the two points. Also I am not totally sure how to use the MotionEvent stuff or how to put the touch actions into the IF statement.
final View touchView = findViewById(R.id.touchView);
touchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
String.valueOf(event.getX() + String.valueOf(event.getY()));
double c = event.getX();
double column = Math.floor(event.getX()/(480/12));
double r = event.getY();
double row = Math.floor(event.getY()/(630/12));
if (column == 0 && row == 2 //there should be more stuff here
) {
//I dont know how to draw a line in here, please help
}
return true;
}
});
}
Rather than explain the details here, I'll point you to these pieces of sample code from the ApiDemos sample project that comes with the SDK, that probably do exactly what you want:
DrawPoints.java
TouchPaint.java
The basic idea is to store X and Y coordinates in your touch event handler, invalidate the View, and then draw the lines in the onDraw method using Canvas operations such as drawLine.
You do neew to have a tool to draw the line, most suitable for you it seems to be Canvas. If you don't know anything about Canvas together with Android yet i suggest you to look into some examles that Android leaves us. Ones you have done that, this is going to be a simple task.
Related
Im trying to translate a square 'p' 5 units left or right depending on what key has been pressed . The problem is that when 'right' or 'left' is pressed it will translate 5 units in that direction but when I press again I can't move and I have to press 'left' to move right again so I never get anywhere.
Does anyone know why this is?
Task PlyThread=new Task() {
#Override
protected Object call() throws Exception {
myScene.setOnKeyPressed(event -> {
switch (event.getCode()){
//case UP: p.setTranslateY(((p.getY())-5)) ; break;
case LEFT: p.setTranslateX(((p.getX())-5)) ; break;
case RIGHT: p.setTranslateX(((p.getX())+5)) ;break;
}
});
return null;
}
};new Thread(PlyThread).start();
Ok, I assume that "Rectangle" is javafx.scene.shape.Rectangle. In this case setTranslateX() only modifies transformation matrix and does not change the rectangle coordinate X. Value of property X remains unchanged and next call to setTranslateX(getX()+5) does exactly the same job as the one before.
You need to work either with translations or with coordinates, i.e. either use setTranslateX()/getTranslateX() or setX()/getX().
Both choices may have other consequences, beyond moving rectangle on the screen, but I have no experience with JavaFX, so unfortunately I cannot elaborate more.
Got this BOID application going in Processing with some steering algorithms.
The boids are stored
in two separate ArrayLists for each colour.
The red boid (predator) has a
pursue function:
class Creature {
int prey = 1;
PVector pursue(ArrayList boids) {
PVector steer = new PVector();
if (prey < boids.size()) {
Creature boid = (Creature) boids.get(prey);
steer = PVector.sub(boid.location, location);
steer.mult(maxpursue);
}
return steer;
}
This function gets the red boids to stand on top of the targeted white boid.
The problem is getting this white boid to disappear when all the red boids are on top of it. (Like shown in the image above)
I can add a new boid or predator with the following, but i cannot remove?:
void mousePressed() {
if (mouseButton == LEFT){
Creature predator = new Creature(mouseX, mouseY, 2);
planet.boids.add(predator);
} else if (mouseButton == RIGHT) {
Creature boid = new Creature(mouseX, mouseY, 1);
planet.boids.add(boid);
planet.boids.remove(boid); // This line does not work?
}
}
The code you posted doesn't make a ton of sense. You want to remove an existing Boid, so why on earth are you creating a new one and then immediately removing it?
You haven't posted an MCVE, so I can only answer in a general sense, but here's what you need to do:
Step 1: Refactor your code so that it makes more sense. Comment every single line if you have to, just to be sure you know exactly what the code is doing. But you shouldn't be doing things like adding a new Boid and then removing it in the very next line. Break your problem down into smaller steps, and make sure each step works perfectly by itself before trying to mix it with other funtionality.
Step 2: Create a function that takes a single white Boid and the List of red Boids, and returns true if that white Boid should be removed. Test this function by itself using hard-coded values in a standalone example sketch.
Step 3: Iterate over your white Boids and call the function you created in step 2 for each one. If the function returns true, then remove that white Boid. You might want to use an Iterator for this step.
If you get stuck on one of those steps, then post an MCVE along with a specific question, and we'll go from there. It's hard to answer general "how do I do this" type questions, but it's much easier to answer specific "I tried X, expected Y, but got Z instead" type questions- especially if we have an MCVE we can actually run on our own machines instead of some disconnected snippets.
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
I found this little sample code, to do drawing with your finger:
http://marakana.com/tutorials/android/2d-graphics-example.html
Here is some of the relevant code:
List<Point> points = new ArrayList<Point>();
#Override
public void onDraw(Canvas canvas) {
for (Point point : points) {
canvas.drawCircle(point.x, point.y, 5, paint);
}
}
public boolean onTouch(View view, MotionEvent event) {
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d(TAG, "point: " + point);
return true;
}
I was looking through it, and saw that they are adding points to an ArrayList, then looping through the ArrayList, this doesn't seem like it is a very optimized approach to this. Is there a better approach or is this a good approach?
After testing on my Samsung GS3, I colored the whole screen in with a circle size of 20, and the closer it got to full color the slower it took to draw, and then circles were becoming spaced out.
No, this makes sense in this example.
He loops through all the points he wants to draw.
This means he adds every point to the array, so he can loop through all the objects at once.
You'll often see this in game programming.
This is also very expandable.
You can add as many points as you want
It supports polymorphism
You don't have to make variables for multiple points > Less code
First, use stroke (not circles) to draw the line. Second, approximate. Here's a summary:
Change Paint to use a stroke with width=5. That reduces the need to draw so many circles.
Pick a threshold, for example 3px after which you'll add a point in onTouch().
if (Math.abs(previousX - event.getX()) < THRESHOLD
&& Math.abs(previousY - event.getY()) < THRESHOLD) {
return;
}
previousX = event.getX();
previousY = event.getY();
// drawing update goes here
This should reduce number of (unnoticeable) points.
Use Picture or Path class to draw the line to, and use Canvas.drawPath() or Canvas.drawPicture(). This, especially for large number of points, will really speed the drawing since all drawing commands will be passed to the internal drawing function in one call.
Simplify the shape at need. For example, you could delete eldest points (which would be a perfect case to use circular buffer), use the Ramer-Douglas-Peucker algorithm which is pretty easy to implement, gives good results and has complexity of O(nlogn).
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)
{
}
}
}