I don't quite get how this bit of code works. I understand the outcome (to add a new object using the mouse coordinates), but can you explain to me how the lines beginning with 'MouseInfo...' and 'addObject..' work? Is a new MouseInfo object created for each click event called 'mouse'?
public void act()
{
// Add your action code here.
if( Greenfoot.mouseClicked(this)) {
MouseInfo mouse = Greenfoot.getMouseInfo();
addObject( new Frog(), mouse.getX(), mouse.getY());
}
}
When you invoke Greenfoot.getMouseInfo() you receive a MouseInfo object from the Greenfoot class. It could be a new Object for every click or one that gets reused and updated as the user clicks.
The MouseInfo object has the methods getX() and getY() which return the coordinates of the click. Finally the addObject method adds a new frog at the specified position.
Related
I'm relatively new to java and android programming, and i wanted to get coordinates based on a point that i tapped on HERE maps. I really hoped you guys could help me out with this.
Edit :
This is the code that i tried to implement, however, it returned me with the error : Error:(354, 53) error: cannot find symbol variable PointF :
private void addDestination() {
image.setImageResource(R.drawable.marker);
GeoCoordinate endpoint = map.pixelToGeo(PointF);
MapMarker destination = new MapMarker(endpoint,image);
if (destination != null)
{
map.removeMapObject(destination);
}
else
{
map.addMapObject(destination);
}
}
PointF is a datatype, so calling "map.pixelToGeo(PointF)" doesn't make sense, you need to call it with concrete data.
In a short:
You need to listen for click events (or longpress, or whatever event you wanna handle), and you get PointF data that's reflecting the screen coordinates. Then you can convert the screen coordinates via pixelToGeo into geocoordinates that you can use to add mapmarker or whatever you wanna do with it on the map.
Some code to help you getting started:
Listening to click events on the map (to retrieve the PointF screencoordinates) are done via registering the gestureListener to your mapview. Means, after successfull mapengine init, you do something like that:
yourMapViewInstance.getMapGesture().addOnGestureListener(yourGestureHandlerImpementation, 10, true);
and in your gestureHandler implementation, you can override several events (click, longpress, etc.), so for example you can do for longpress the following:
private MapGesture.OnGestureListener yourGestureHandlerImpementation = new MapGesture.OnGestureListener.OnGestureListenerAdapter()
{
#Override
public boolean onLongPressEvent(PointF p) {
GeoCoordinate c = map.pixelToGeo(p);
// c is your geoccordinate on the map, where you clicked on the screen
// [...]
}
}
How can I add mouseListener to a MapMarker (MepMarkerDot or MapMarkerCircle) that makes it like button?
I tried this soloution but it makes whole map clickable (mouse Event works on all the map).
You're on the right path to start with TrashGod's MouseListener solution, but you need to add a little more code, the key part being, that you need to get the Point location of where the user pressed, something the MouseEvent#getPoint() method will tell you, and then based on that information, and the bounds of the "active" area of the component decide whether to respond. Something like:
#Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint(); // this is where the user pressed
if (isPointValid(p)) {
// do something
}
System.out.println(map.getPosition(e.getPoint()));
}
private boolean isPointValid(Point p) {
// here you have code to decide if the point was pressed in the area of interest.
}
Note that if your code uses Shape derived objects, such as Ellipse2D or Rectangle2D, you can use their contains(Point p) method to easily tell you if the point press was within the Shape or not. Or if there are several locations that you want to check, you may have a collection of Shapes, iterate through them within your mousePressed or (if you have it) isPointValid method, and check containment within the for loop.
I found this nice example:
https://www.programcreek.com/java-api-examples/index.php?source_dir=netention-old1-master/swing/automenta/netention/swing/map/Map2DPanel.java
It has an interface MarkerClickable and its own LabeledMarker which implements MapMarker and MarkerClickable:
public boolean onClick(final Coordinate p, final MouseEvent e) {
for (final MapMarker x : getMap().getMapMarkerList()) {
if (x instanceof MarkerClickable) {
final MarkerClickable mc = (MarkerClickable)x;
final Rectangle a = mc.getClickableArea();
if (a == null)
continue;
if (a.contains(e.getPoint())) {
mc.onClicked(e.getPoint(), e.getButton());
return false;
}
}
}
return true;
}
I'm working on a project for a simple game where you can go to different rooms by using buttons (north, east, west, south). Within the makeFrame() method of my gui I'm creating the panel, buttons etc. I then set the default room to "hall" for example and the actionlistener calls the method goRoom and passing the direction and currentRoom to that method. The goRoom method change the currentRoom to another room depending on the currentRoom. I included print statements to see if it works and so far it works fine.
Everytime the game starts the default room is the hall.
So when you click a button to go for example "North", the northButton is called in which then we call the goRoom method passing the direction (north) and the default room "hall" (as the game just starts and uses the default room).
Then the room changes from hall to state room (within the method goRoom). When I try to press another button the currentRoom reset to the default value (hall).
I think the action listener get the value from the makeFrame() method instead of the updated value from the goRoom method. The code is below:
public class StoreGUI extends JFrame
{
public String currentRoom;
public StoreGUI()
{
makeFrame();
}
private void makeFrame()
{
currentRoom = "hall";
....
northButton = new JButton("Go North");
northButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
direction = "north";
goRoom(direction, currentRoom); }
});
toolbar.add(northButton);
westButton ....
southButton ....
eastButton ....
picture.setIcon(new ImageIcon("image/hall.png"));
frame.getContentPane().add(picture);
frame.pack();
frame.setVisible(true);
}
private void goRoom(String direction, String currentRoom)
{
// get current room and check which direction button the user has pressed
if (direction == "north"){
if(currentRoom == "hall"){
// Inserts the image icon and change currentRoom
imgageTitle = "image/stateRoom.png";
currentRoom = "stateRoom";
}
....
}
What the problem could be? How can I fix that? I'm pretty sure it's something really simple but I'm stack.
String comparison in Java is done with String#equals not ==. This will compare the actual text of the String and not its memory reference...
For example, instead of
if (direction == "north") {....
Use
if ("north".equals(direction)) {...
If you don't care about the case, you could use...
if ("north".equalsIgnoreCase(direction)) {...
Having said all that, you could actually use a enum to represent the directions, which restricts what values you can actually pass to the goRoom.
You could also use a Action to define each button's actions, which also means you could use them Key Bindings or menus without having to duplicate any code...but that's just me...
Updated
You're also shadowing your values...
private void goRoom(String direction, String currentRoom)
{
//...
currentRoom = "stateRoom";
Changing the value of currentRoom will have no effect beyond the scope of the method. This is because you're not actually changing the content of the String object, but changing it's memory reference.
Instead, either change the name of the parameter or, simply don't bother passing, as you already have access to the instance field of the same name...
private void goRoom(String direction)
{
//...
currentRoom = "stateRoom";
Hi I want to build on java mouse click logger. I need to print the coordinates of mouse clicks in a file. Can you tell me how I can make this. Which APIs to use some examples or links. I need to get all the mouse clicks not only in one window.
you could implement the MouseListener interface and overwrite the mouseClicked function:
public class MyMouseListener implements MouseListener {
// [...]
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e.getLocationOnScreen());
}
// [...]
}
Adapt that example to your needs. THe getLocationOnScreen Method returns a "Point" object which you can ask for x/y coordinates.
I'm working on a GUI for a card game and am using the ACM's student graphics library for the sake of familiarity. I have written a program that draws my solitaire game to the screen, and am having trouble making it interactive.
Background:
There are a lot of classes here, and I'll do my best to describe them each.
Top level JFrame containing the application.
GCanvas (that holds all the graphics objects)
SolitaireGameControl (GCompound holding all the other GCompounds making up the solitaire game)
Array of PileViews, a pile of cards (GCompound consisting of an array of Cards)
Cards (GCompound consisting of rectangles and labels)
(GCompound: a collection of graphics objects treated as one object. (If car was a GCompound, it would have GOval[] wheels, GRect body and so when I add it to the canvas, it displays as one object))
A card as seen from the top-level class would look like a bit like this: jFrame.gCanvas.solitaireGameControl.pileViews[pile number].cardView
What I've been trying to do is add a MouseListener to every single card, so that when a card is clicked and a MouseEvent is fired, MouseEvent e.getSource() = the card that was clicked.
Here's how it looks now:
public SolitaireGameControl(SolitaireGame game) {
this.game = game; // Model of the game.
this.pileViews = PileView.getPileViews(game.drawPiles); // ArrayList of PileViews (the pile of cards)
for(PileView pv : pileViews) {
for(CardView cv : pv.cardViews) {
cv.addMouseListener(this); // add a mouseListener to the card
}
}
this.addMouseListener(this); // if I don't include this, nothing happens when I click anything. If I do include this, this whole object is the source.
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e.getSource()); // should return the card I clicked.
}
When I run this program, the source of every event is SolitaireGameControl, granted I leave in the this.addMouseListener(this);. If I take out this statement, nothing is printed at all, leading me to believe that the mouseListeners I have added are only working one level deep. (The first GCompound on the canvas, not the GCompounds inside it.)
Therefore, my question is as follows: Is there a way to get a MouseListener for a GCompound inside of a GCompound inside of a GCompound, and have MouseEvent's getSource to correctly identify the card? If not, is there a way to restructure my program to make it work as intended? (I know I should really be using a better graphics library for starters.)
That would make sense. From my experience, if I put some components inside a top-level container, the container is the one that receives input events.
Have you tried an approach where you do something like:
/* This is the mouse listener for the top-level container. */
#Override
public void mouseClicked(MouseEvent e) {
for(PileView pv : pileViews) {
for(CardView cv : pv.cardViews) {
if(cv.getBounds().contains(e.getPoint())) {
cv.dispatchEvent(e);
}
}
}
}
... and then handle mouse clicks on a 'CardView' level normally.
When the top-level container receives a mouse event, it checks if the mouse interacted with a card based on the location of the event (if the card's area contains the point). If it did, it passes down the mouse event to the card's mouse listener.
I'm assuming that the elements near the beginning of 'pv.cardViews' are the cards that are more to the front.