在selectMarkerIfHover方法中,if语句允许“ lastSelected”不为null的情况。
在我的生命中,我看不到任何可能发生这种情况的情况,因为它似乎总是以null开头,或者在mouseMoved方法中设置为null。我需要了解在调用selectMarkerIfHover方法时lastSelected怎么可能为空。我到处都在寻求帮助以解决此问题,但是它是如此具体,我找不到答案。
public class EarthquakeCityMap extends PApplet {
// You can ignore this. It's to get rid of eclipse warnings
private static final long serialVersionUID = 1L;
// IF YOU ARE WORKING OFFILINE, change the value of this variable to true
private static final boolean offline = false;
/** This is where to find the local tiles, for working without an Internet connection */
public static String mbTilesString = "blankLight-1-3.mbtiles";
//feed with magnitude 2.5+ Earthquakes
private String earthquakesURL = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.atom";
// The files containing city names and info and country names and info
private String cityFile = "city-data.json";
private String countryFile = "countries.geo.json";
// The map
private UnfoldingMap map;
// Markers for each city
private List<Marker> cityMarkers;
// Markers for each earthquake
private List<Marker> quakeMarkers;
// A List of country markers
private List<Marker> countryMarkers;
// NEW IN MODULE 5
private CommonMarker lastSelected;
private CommonMarker lastClicked;
public void setup() {
// (1) Initializing canvas and map tiles
size(900, 700, OPENGL);
if (offline) {
map = new UnfoldingMap(this, 200, 50, 650, 600, new MBTilesMapProvider(mbTilesString));
earthquakesURL = "2.5_week.atom"; // The same feed, but saved August 7, 2015
}
else {
map = new UnfoldingMap(this, 200, 50, 650, 600, new Google.GoogleMapProvider());
// IF YOU WANT TO TEST WITH A LOCAL FILE, uncomment the next line
//earthquakesURL = "2.5_week.atom";
}
MapUtils.createDefaultEventDispatcher(this, map);
// (2) Reading in earthquake data and geometric properties
// STEP 1: load country features and markers
List<Feature> countries = GeoJSONReader.loadData(this, countryFile);
countryMarkers = MapUtils.createSimpleMarkers(countries);
// STEP 2: read in city data
List<Feature> cities = GeoJSONReader.loadData(this, cityFile);
cityMarkers = new ArrayList<Marker>();
for(Feature city : cities) {
cityMarkers.add(new CityMarker(city));
}
// STEP 3: read in earthquake RSS feed
List<PointFeature> earthquakes = ParseFeed.parseEarthquake(this, earthquakesURL);
quakeMarkers = new ArrayList<Marker>();
for(PointFeature feature : earthquakes) {
//check if LandQuake
if(isLand(feature)) {
quakeMarkers.add(new LandQuakeMarker(feature));
}
// OceanQuakes
else {
quakeMarkers.add(new OceanQuakeMarker(feature));
}
}
// could be used for debugging
printQuakes();
// (3) Add markers to map
// NOTE: Country markers are not added to the map. They are used
// for their geometric properties
map.addMarkers(quakeMarkers);
map.addMarkers(cityMarkers);
} // End setup
public void draw() {
background(0);
map.draw();
addKey();
}
/** Event handler that gets called automatically when the
* mouse moves.
*/
@Override
public void mouseMoved()
{
// clear the last selection
if (lastSelected != null) {
lastSelected.setSelected(false);
lastSelected = null;
}
selectMarkerIfHover(quakeMarkers);
selectMarkerIfHover(cityMarkers);
}
// If there is a marker under the cursor, and lastSelected is null
// set the lastSelected to be the first marker found under the cursor
// Make sure you do not select two markers.
//
private void selectMarkerIfHover(List<Marker> markers)
{
// TODO: Implement this method
// Abort if there's already a marker selected
if (lastSelected != null) {
return;
}
for(Marker m : markers) {
CommonMarker marker = (CommonMarker)m;
if(marker.isInside(map,mouseX,mouseY)) {
lastSelected = marker;
marker.setSelected(true);
return;
}
}
}
/** The event handler for mouse clicks
* It will display an earthquake and its threat circle of cities
* Or if a city is clicked, it will display all the earthquakes
* where the city is in the threat circle
*/
@Override
public void mouseClicked()
{
// TODO: Implement this method
// Hint: You probably want a helper method or two to keep this code
// from getting too long/disorganized
if(lastClicked != null) {
unhideMarkers();
lastClicked = null;
}
else if(lastClicked == null) {
checkEarthquakes();
if(lastClicked == null) {
checkCities();
}
}
}
// Helper method that will check if an earthquake marker was clicked on
// and respond appropriately
private void checkEarthquakes() {
if (lastClicked != null) return;
// Loop over the earthquake markers to see if one of them is selected
for (Marker m : quakeMarkers) {
EarthquakeMarker marker = (EarthquakeMarker)m;
if (!marker.isHidden() && marker.isInside(map, mouseX, mouseY)) {
lastClicked = marker;
// Hide all the other earthquakes and hide
for (Marker mhide : quakeMarkers) {
if (mhide != lastClicked) {
mhide.setHidden(true);
}
}
for (Marker mhide : cityMarkers) {
if (mhide.getDistanceTo(marker.getLocation())
> marker.threatCircle()) {
mhide.setHidden(true);
}
}
return;
}
}
}
// Helper method that will check if a city marker was clicked on
// and respond appropriately
private void checkCities() {
if (lastClicked != null) return;
// Loop over the earthquake markers to see if one of them is selected
for (Marker marker : cityMarkers) {
if (!marker.isHidden() && marker.isInside(map, mouseX, mouseY)) {
lastClicked = (CommonMarker)marker;
// Hide all the other earthquakes and hide
for (Marker mhide : cityMarkers) {
if (mhide != lastClicked) {
mhide.setHidden(true);
}
}
for (Marker mhide : quakeMarkers) {
EarthquakeMarker quakeMarker = (EarthquakeMarker)mhide;
if (quakeMarker.getDistanceTo(marker.getLocation())
> quakeMarker.threatCircle()) {
quakeMarker.setHidden(true);
}
}
return;
}
}
}
// loop over and unhide all markers
private void unhideMarkers() {
for(Marker marker : quakeMarkers) {
marker.setHidden(false);
}
for(Marker marker : cityMarkers) {
marker.setHidden(false);
}
}
// helper method to draw key in GUI
private void addKey() {
// Remember you can use Processing's graphics methods here
fill(255, 250, 240);
int xbase = 25;
int ybase = 50;
rect(xbase, ybase, 150, 250);
fill(0);
textAlign(LEFT, CENTER);
textSize(12);
text("Earthquake Key", xbase+25, ybase+25);
fill(150, 30, 30);
int tri_xbase = xbase + 35;
int tri_ybase = ybase + 50;
triangle(tri_xbase, tri_ybase-CityMarker.TRI_SIZE, tri_xbase-CityMarker.TRI_SIZE,
tri_ybase+CityMarker.TRI_SIZE, tri_xbase+CityMarker.TRI_SIZE,
tri_ybase+CityMarker.TRI_SIZE);
fill(0, 0, 0);
textAlign(LEFT, CENTER);
text("City Marker", tri_xbase + 15, tri_ybase);
text("Land Quake", xbase+50, ybase+70);
text("Ocean Quake", xbase+50, ybase+90);
text("Size ~ Magnitude", xbase+25, ybase+110);
fill(255, 255, 255);
ellipse(xbase+35,
ybase+70,
10,
10);
rect(xbase+35-5, ybase+90-5, 10, 10);
fill(color(255, 255, 0));
ellipse(xbase+35, ybase+140, 12, 12);
fill(color(0, 0, 255));
ellipse(xbase+35, ybase+160, 12, 12);
fill(color(255, 0, 0));
ellipse(xbase+35, ybase+180, 12, 12);
textAlign(LEFT, CENTER);
fill(0, 0, 0);
text("Shallow", xbase+50, ybase+140);
text("Intermediate", xbase+50, ybase+160);
text("Deep", xbase+50, ybase+180);
text("Past hour", xbase+50, ybase+200);
fill(255, 255, 255);
int centerx = xbase+35;
int centery = ybase+200;
ellipse(centerx, centery, 12, 12);
strokeWeight(2);
line(centerx-8, centery-8, centerx+8, centery+8);
line(centerx-8, centery+8, centerx+8, centery-8);
}
// Checks whether this quake occurred on land. If it did, it sets the
// "country" property of its PointFeature to the country where it occurred
// and returns true. Notice that the helper method isInCountry will
// set this "country" property already. Otherwise it returns false.
private boolean isLand(PointFeature earthquake) {
// IMPLEMENT THIS: loop over all countries to check if location is in any of them
// If it is, add 1 to the entry in countryQuakes corresponding to this country.
for (Marker country : countryMarkers) {
if (isInCountry(earthquake, country)) {
return true;
}
}
// not inside any country
return false;
}
// prints countries with number of earthquakes
private void printQuakes() {
int totalWaterQuakes = quakeMarkers.size();
for (Marker country : countryMarkers) {
String countryName = country.getStringProperty("name");
int numQuakes = 0;
for (Marker marker : quakeMarkers)
{
EarthquakeMarker eqMarker = (EarthquakeMarker)marker;
if (eqMarker.isOnLand()) {
if (countryName.equals(eqMarker.getStringProperty("country"))) {
numQuakes++;
}
}
}
if (numQuakes > 0) {
totalWaterQuakes -= numQuakes;
System.out.println(countryName + ": " + numQuakes);
}
}
System.out.println("OCEAN QUAKES: " + totalWaterQuakes);
}
// helper method to test whether a given earthquake is in a given country
// This will also add the country property to the properties of the earthquake feature if
// it's in one of the countries.
// You should not have to modify this code
private boolean isInCountry(PointFeature earthquake, Marker country) {
// getting location of feature
Location checkLoc = earthquake.getLocation();
// some countries represented it as MultiMarker
// looping over SimplePolygonMarkers which make them up to use isInsideByLoc
if(country.getClass() == MultiMarker.class) {
// looping over markers making up MultiMarker
for(Marker marker : ((MultiMarker)country).getMarkers()) {
// checking if inside
if(((AbstractShapeMarker)marker).isInsideByLocation(checkLoc)) {
earthquake.addProperty("country", country.getProperty("name"));
// return if is inside one
return true;
}
}
}
// check if inside country represented by SimplePolygonMarker
else if(((AbstractShapeMarker)country).isInsideByLocation(checkLoc)) {
earthquake.addProperty("country", country.getProperty("name"));
return true;
}
return false;
}
}
答案 0 :(得分:0)
selectMarkerIfHover
被mouseMoved
调用两次,第一次是因为您指出始终为空,但是如果if(marker.isInside(map,mouseX,mouseY)) {
内的条件selectMarkerIfHover
为真,则{{ 1}}被设置为值(lastSelected
),因此当lastSelected = marker;
第二次调用selectMarkerIfHover
时,它肯定不是null。