Skip to content

Instantly share code, notes, and snippets.

@starks981
Created September 12, 2018 15:34
Show Gist options
  • Save starks981/3037fabada4aa9c628e59ccfa8ecafe0 to your computer and use it in GitHub Desktop.
Save starks981/3037fabada4aa9c628e59ccfa8ecafe0 to your computer and use it in GitHub Desktop.
Weather App using Openweathermap.org API
package weatherapp;
// Imports for the class
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
// CurrentConditionsConnection Class
public class CurrentConditionsConnection {
// Declare the private variables needed for the class
private static String currentTemp;
private static String description;
private static String humidity;
private static String cityName;
private static String icon;
// BuildCurrentConnection Method
public static void buildCurrentConnection(String zip) {
// Declare a string and stringbuilder to handle the get request
String inputLine;
StringBuilder response = new StringBuilder();
// Try-catch block
try {
// Create a URL object with the zip collected from the opening scene
URL url = new URL("http://api.openweathermap.org/data/2.5/weather?zip=" + zip + "&units=imperial&APPID=6eb402785cda7bb438558f56aa0235c8");
// Attempt to open the connection with the openweathermap API
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// If the connection was successful (200 response) read the JSON
if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
// Create a buffered reader to read the JSON
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
// feed response into the StringBuilder while there is a response to read
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// Close the bufferedreader
in.close();
}
// Set the connected variable to TRUE
WeatherApp.connected = true;
// Call the Weather Info Method
weatherInfo(response.toString());
}
// If the connection was invalid show error message
catch(Exception e) {
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Error");
alert.setHeaderText("Zip Code Not Valid.\nPlease Re-enter");
alert.showAndWait();
// Set the Connected variable to FALSE
WeatherApp.connected = false;
}
}
// WeatherInfo method
public static void weatherInfo(String currentWeather) {
// call the RetrieveData method to parse the JSON response
currentTemp = retrieveData("temp", currentWeather);
description = retrieveData("description", currentWeather).replaceAll("\"","");
humidity = retrieveData("humidity", currentWeather);
cityName = retrieveData("name", currentWeather).replaceAll("\"","");
icon = retrieveData("icon", currentWeather).replaceAll("}","").replaceAll("\"", "").replaceAll("]","");
}
// RetrieveData method
public static String retrieveData(String data, String currentWeather) {
// Return the parsed string
return currentWeather.substring(currentWeather.indexOf(":",currentWeather.indexOf(data))+1,
currentWeather.indexOf(",",currentWeather.indexOf(data)));
}
// Getters
public String getCurrentTemp() {
return currentTemp;
}
public String getDescription() {
return description;
}
public String getHumidity() {
return humidity;
}
public String getCityName() {
return cityName;
}
public String getIcon() {
icon = "http://openweathermap.org/img/w/" + icon + ".png";
return icon;
}
}
package weatherapp;
// Imports for the class
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
// HourlyConditionsConnection Class
public class HourlyConditionsConnection {
// Declare the variables for the class
private static String[] description = new String[4];
private static int[] descIndex = new int[4];
private static String[] temp = new String[4];
private static int[] tempIndex = new int[4];
private static String[] hourly = new String[4];
private static int[] hourlyIndex = new int[4];
private static String[] icons = new String[4];
private static int[] iconsIndex = new int[4];
// BuildHourlyConnection Method
public static void buildHourlyConnection(String zip) {
// Declare a string and stringbuilder to handle the get request
String inputLine;
StringBuilder response = new StringBuilder();
// Try-catch block
try {
// Create a URL object with the zip collected from the opening scene
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast?zip=" + zip + "&units=imperial&APPID=6eb402785cda7bb438558f56aa0235c8");
// Attempt to open the connection with the openweathermap API
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// If the connection was successful (200 response) read the JSON
if(con.getResponseCode() == HttpURLConnection.HTTP_OK) {
// Create a buffered reader to read the JSON
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
// feed response into the StringBuilder while there is a response to read
while((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// Close the bufferedreader
in.close();
}
}
// If the connection was invalid show error message
catch(Exception e) {
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Error");
alert.setHeaderText("Zip Code Not Valid.\nPlease Re-enter");
alert.showAndWait();
}
// Call the Weather Info Method
weatherInfo(response.toString());
}
// WeatherInfo method
public static void weatherInfo(String currentWeather) {
// Call the findIndex method to find the index needed for the retrievedata method
for(int i = 0; i < 4; i++) {
// Start with the second occurence of the word (first occurence would be current conditions)
iconsIndex[i] = findIndex(currentWeather, "icon", i + 1);
descIndex[i] = findIndex(currentWeather, "description", i + 1);
tempIndex[i] = findIndex(currentWeather, "temp_max", i + 1);
hourlyIndex[i] = findIndex(currentWeather, "dt_txt", i + 1);
}
// Call the RetrieveData method to parse the JSON response
icons = retrieveData(iconsIndex, currentWeather);
description = retrieveData(descIndex, currentWeather);
temp = retrieveData(tempIndex, currentWeather);
hourly = retrieveData(hourlyIndex, currentWeather);
}
// FindIndex method
public static int findIndex(String str, String substr, int n) {
// Set pos equal to the first index of the substring
int pos = str.indexOf(substr);
// Loop to find the appropriate index for the array
while(--n > 0 && pos != -1) {
// find the appropriate position of the substring to populate the array
pos = str.indexOf(substr, pos + 1);
}
// Returns the found index
return pos;
}
// Retrieve Data method
public static String[] retrieveData(int[] index, String currentWeather) {
// Array to handle the data parsing
String[] arr = new String[4];
// Loop to populate the array with appropriate data, using indices found in respective index arrays
for(int i = 0; i < arr.length; i++) {
arr[i] = currentWeather.substring(currentWeather.indexOf(":", index[i])+1, currentWeather.indexOf(",", index[i]))
.replaceAll("}","").replaceAll("\"", "").replaceAll("]","");
}
// Return the populated array
return arr;
}
// Getters
public String[] getIcons() {
for(int i = 0; i < icons.length; i++) {
icons[i] = "http://openweathermap.org/img/w/" + icons[i] + ".png";
}
return icons;
}
public String[] getDescription() {
return description;
}
public String[] getTemp() {
return temp;
}
public String[] getHourly() {
for(int i = 0; i < hourly.length; i++) {
hourly[i] = hourly[i].substring(hourly[i].indexOf(" "), hourly[i].indexOf(":")).trim();
int temp = Integer.parseInt(hourly[i]);
temp = temp - 5;
if(temp > 12) {
hourly[i] = temp - 12 + ":00";
}
else if (temp < 0) {
hourly[i] = 12 + temp + ":00";
}
else if (temp <= 12) {
hourly[i] = temp + ":00";
}
}
return hourly;
}
}
.root{
-fx-background-image: url("/Resources/bckgrnd1.jpg");
-fx-font-weight: bold;
}
#zip{
-fx-font: 15px Arial;
-fx-font-weight: bold;
-fx-fill: #5d445d;
}
.button{
-fx-background-color: #5d445d;
-fx-text-fill: #F1E3F3;
}
.button:hover{
-fx-background-color: #F1E3F3;
-fx-text-fill: #5d445d;
}
.button:focused{
-fx-background-color: #F1E3F3;
-fx-text-fill: #5d445d;
}
.label{
-fx-font: 13px Arial;
-fx-font-weight: bold;
-fx-text-fill: #674172;
}
.separator *.line{
-fx-background-color: #e79423;
-fx-background-radius: 5;
-fx-border-style: solid;
}
package weatherapp;
/*
* Homemade Weather Application
* Author - Chris Starkey
* Work Started 8-2-2018
* Work Completed 9-12-2018
*/
// Imports for the application
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
// Weather App Class
public class WeatherApp extends Application {
// Main Stage
Stage window;
// Zip Code Scene, Current Conditions Scene
Scene zipCodeScene, currentConditions;
// Create the root node
GridPane root = new GridPane();
// Text asking to enter the zip code
Text zipTxt = new Text("Enter Zip Code:");
// Text field for zip code entry
TextField zipTxtFld = new TextField("(e.g. 22802)");
// Button to trigger the call to the API
Button enterBtn = new Button("Enter");
// HBox to house the Enter button
HBox hboxBtn = new HBox();
// Connection Confirmation boolean
static boolean connected = true;
// Main Method
public static void main(String[] args) {
launch();
}
// Override the start method
public void start(Stage myStage) {
// Set the main stage
window = myStage;
// Set the title of the stage
window.setTitle("Stark-U-Weather Forecast");
// Align the root node in the center
root.setAlignment(Pos.CENTER);
// Set a horizontal gap between controls
root.setHgap(10);
// Set a vertical gap between controls
root.setVgap(10);
// Set padding of the root node
root.setPadding(new Insets(25, 25, 25, 25));
// Set the alignment of the hbox
hboxBtn.setAlignment(Pos.BOTTOM_RIGHT);
// Add the Enter Button to the Hbox
hboxBtn.getChildren().add(enterBtn);
// Add the components to the root node
root.add(zipTxt, 0, 0);
root.add(zipTxtFld, 0, 1);
root.add(hboxBtn, 0, 2);
// Add a CSS ID to the ZipTxt
zipTxt.setId("zip");
// On Button click attempt a GET request
enterBtn.setOnAction(ae -> {
// Collect zip code to send to the buildConnection method.
CurrentConditionsConnection.buildCurrentConnection(zipTxtFld.getText());
// If the connection was successful, attempt the second get request
if(connected) {
HourlyConditionsConnection.buildHourlyConnection(zipTxtFld.getText());
// Call the currentConditions Scene method to display the second scene
buildCurrentConditionsScene();
}
});
// Create the zip code scene
zipCodeScene = new Scene(root, 615, 350);
// Add the scene to the stage
window.setScene(zipCodeScene);
// Attach the stylesheet to the scene
zipCodeScene.getStylesheets().add("/Resources/Stylesheet.css");
// Do not let the stage be resized
window.setResizable(false);
// Show the main stage
window.show();
}
public void buildCurrentConditionsScene(){
// Create a new CurrentConditionsConnection object
CurrentConditionsConnection connection = new CurrentConditionsConnection();
// Create the labels, buttons and images for the scene
Label currentLabel = new Label("Current Temp: " + connection.getCurrentTemp());
Label descriptionLabel = new Label(connection.getDescription());
Label humidityLabel = new Label("Current Humidity: " + connection.getHumidity() + "%");
Label cityLabel = new Label("City: " + connection.getCityName());
Image iconImg = new Image(connection.getIcon());
ImageView imgView = new ImageView(iconImg);
HBox hbox = new HBox(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().addAll(zipTxt, zipTxtFld, enterBtn);
// Create the root node for the scene
GridPane ccRoot = new GridPane();
// Set the Vertical and Horizontal gaps between nodes
ccRoot.setVgap(10);
ccRoot.setHgap(10);
// Align the root node in the Center
ccRoot.setAlignment(Pos.CENTER);
// Add the elements to the root node
ccRoot.add(cityLabel, 0,2,2,1);
ccRoot.add(currentLabel, 2, 3,2,1);
ccRoot.add(humidityLabel, 2, 4,2,1);
ccRoot.add(descriptionLabel, 5, 3);
ccRoot.add(imgView, 5, 4);
ccRoot.add(hbox, 3, 0, 5, 1);
// Center the elements within their grid
GridPane.setHalignment(cityLabel, HPos.CENTER);
GridPane.setHalignment(descriptionLabel, HPos.CENTER);
GridPane.setHalignment(imgView, HPos.CENTER);
// Create a new HourlyConditionsConnection object
HourlyConditionsConnection hrlyConnection = new HourlyConditionsConnection();
// Create arrays to house the hourly details
String[] icons = hrlyConnection.getIcons();
String[] description = hrlyConnection.getDescription();
String[] temp = hrlyConnection.getTemp();
String[] hrlyTime = hrlyConnection.getHourly();
// Loop to populate the arrays, center the elements, and add them the root node
for(int i = 0; i < 4; i++) {
Label hrlyTimeLabel = new Label(hrlyTime[i]);
GridPane.setHalignment(hrlyTimeLabel, HPos.CENTER);
ccRoot.add(hrlyTimeLabel, 2+i, 7);
Label hrlyTempLabel = new Label(temp[i]);
GridPane.setHalignment(hrlyTempLabel, HPos.CENTER);
ccRoot.add(hrlyTempLabel, 2+i, 8);
Image hrlyIconImg = new Image(icons[i]);
ImageView hrlyIconView = new ImageView(hrlyIconImg);
GridPane.setHalignment(hrlyIconView, HPos.CENTER);
ccRoot.add(hrlyIconView, 2+i, 9);
Label hrlyDescriptionLabel = new Label(description[i]);
GridPane.setHalignment(hrlyDescriptionLabel, HPos.CENTER);
ccRoot.add(hrlyDescriptionLabel, 2+i, 10);
}
// Create forecast header, center it and add it to the root node
Label upcomingLbl = new Label("Upcoming Forecast");
GridPane.setHalignment(upcomingLbl, HPos.CENTER);
ccRoot.add(upcomingLbl, 0,5,2,1);
// Create the time label, center it and add it to the root node
Label timeLbl = new Label("Time:");
GridPane.setHalignment(timeLbl, HPos.CENTER);
ccRoot.add(timeLbl , 0,7,2,1);
// Create the temp label, center it and add it to the root node
Label tempLbl = new Label("Temp:");
GridPane.setHalignment(tempLbl, HPos.CENTER);
ccRoot.add(tempLbl , 0,8,2,1);
// Create two horizontal lines and add them to the root node
Separator sepHor = new Separator();
GridPane.setConstraints(sepHor,0,1);
GridPane.setColumnSpan(sepHor,9);
ccRoot.getChildren().add(sepHor);
Separator sepHor2 = new Separator();
GridPane.setConstraints(sepHor2,0,6);
GridPane.setColumnSpan(sepHor2,9);
ccRoot.getChildren().add(sepHor2);
// Create the currentconditions scene
currentConditions = new Scene(ccRoot, 615, 350);
// Add the stylesheet to this scene
currentConditions.getStylesheets().add("/Resources/Stylesheet.css");
// Set the scene to the stage
window.setScene(currentConditions);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment