├── README.md ├── Screenshot_15.png ├── WeatherAppGUI.iml ├── lib └── json-simple-1.1.1.jar ├── out └── production │ └── WeatherAppGUI │ ├── AppLauncher$1.class │ ├── AppLauncher.class │ ├── WeatherApp.class │ ├── WeatherAppGui$1.class │ ├── WeatherAppGui.class │ └── assets │ ├── clear.png │ ├── cloudy.png │ ├── humidity.png │ ├── rain.png │ ├── search.png │ ├── snow.png │ └── windspeed.png └── src ├── AppLauncher.java ├── WeatherApp.java ├── WeatherAppGui.java └── assets ├── clear.png ├── cloudy.png ├── humidity.png ├── rain.png ├── search.png ├── snow.png └── windspeed.png /README.md: -------------------------------------------------------------------------------- 1 |

Weather App GUI

2 |

Introduction

3 |

4 | The Weather App is a Java-based application that provides users with real-time weather information for a specified location. It fetches weather data from an external API and displays it in a graphical user interface (GUI). Users can enter a location, and the app retrieves and 5 | presents weather details, including temperature, weather condition, humidity, and wind speed. This documentation outlines the project's architecture, technologies used, and the functionality of each class within the application. 6 |

7 | 8 |

9 | You can check out the full tutorial where I will guide and you and explain the steps in this YouTube video: link 10 |

11 | 12 |

13 | 14 |

15 | 16 |

Technologies Used

17 |

18 | The Weather App utilizes the following technologies and libraries: 19 |

20 | 25 | 26 |

Class Summaries

27 | 28 |

3.1. AppLauncher

29 |

30 | Description: The AppLauncher class serves as the entry point for the Weather App. It initializes the GUI and displays the main application window. 31 |

32 | 33 |

3.2. WeatherAppGui

34 |

35 | Description: The WeatherAppGui class represents the graphical user interface (GUI) of the Weather App. It is responsible for displaying weather information for a specified location. 36 |

37 |

38 | Summary: This class handles the layout and display of GUI components, including text fields, labels, buttons, and images. It also implements the user interface for entering a location and updating the weather information based on user input. 39 |

40 | 41 |

3.3. WeatherApp

42 |

43 | Description: The WeatherApp class contains the backend logic for fetching weather data from an external API. It retrieves geographic coordinates for a location, fetches weather data for that location, and provides methods to convert weather codes. 44 |

45 |

46 | Summary: This class encapsulates the core functionality of the Weather App. It includes methods to fetch weather data and location coordinates, convert weather codes into readable weather conditions, and manage API requests. This class acts as the bridge between the GUI and the external weather data source, ensuring that weather information is retrieved and displayed accurately. 47 |

48 | -------------------------------------------------------------------------------- /Screenshot_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/Screenshot_15.png -------------------------------------------------------------------------------- /WeatherAppGUI.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /lib/json-simple-1.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/lib/json-simple-1.1.1.jar -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/AppLauncher$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/AppLauncher$1.class -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/AppLauncher.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/AppLauncher.class -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/WeatherApp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/WeatherApp.class -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/WeatherAppGui$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/WeatherAppGui$1.class -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/WeatherAppGui.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/WeatherAppGui.class -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/clear.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/cloudy.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/humidity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/humidity.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/rain.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/search.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/snow.png -------------------------------------------------------------------------------- /out/production/WeatherAppGUI/assets/windspeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/out/production/WeatherAppGUI/assets/windspeed.png -------------------------------------------------------------------------------- /src/AppLauncher.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | 3 | public class AppLauncher { 4 | public static void main(String[] args) { 5 | SwingUtilities.invokeLater(new Runnable(){ 6 | @Override 7 | public void run(){ 8 | // display our weather app gui 9 | new WeatherAppGui().setVisible(true); 10 | 11 | // System.out.println(WeatherApp.getLocationData("Tokyo")); 12 | 13 | // System.out.println(WeatherApp.getCurrentTime()); 14 | 15 | } 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/WeatherApp.java: -------------------------------------------------------------------------------- 1 | import org.json.simple.JSONArray; 2 | import org.json.simple.JSONObject; 3 | import org.json.simple.parser.JSONParser; 4 | 5 | import java.io.IOException; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | import java.time.LocalDateTime; 9 | import java.time.format.DateTimeFormatter; 10 | import java.util.Scanner; 11 | 12 | // retreive weather data from API - this backend logic will fetch the latest weather 13 | // data from the external API and return it. The GUI will 14 | // display this data to the user 15 | public class WeatherApp { 16 | // fetch weather data for given location 17 | public static JSONObject getWeatherData(String locationName){ 18 | // get location coordinates using the geolocation API 19 | JSONArray locationData = getLocationData(locationName); 20 | 21 | // extract latitude and longitude data 22 | JSONObject location = (JSONObject) locationData.get(0); 23 | double latitude = (double) location.get("latitude"); 24 | double longitude = (double) location.get("longitude"); 25 | 26 | // build API request URL with location coordinates 27 | String urlString = "https://api.open-meteo.com/v1/forecast?" + 28 | "latitude=" + latitude + "&longitude=" + longitude + 29 | "&hourly=temperature_2m,relativehumidity_2m,weathercode,windspeed_10m&timezone=America%2FLos_Angeles"; 30 | 31 | try{ 32 | // call api and get response 33 | HttpURLConnection conn = fetchApiResponse(urlString); 34 | 35 | // check for response status 36 | // 200 - means that the connection was a success 37 | if(conn.getResponseCode() != 200){ 38 | System.out.println("Error: Could not connect to API"); 39 | return null; 40 | } 41 | 42 | // store resulting json data 43 | StringBuilder resultJson = new StringBuilder(); 44 | Scanner scanner = new Scanner(conn.getInputStream()); 45 | while(scanner.hasNext()){ 46 | // read and store into the string builder 47 | resultJson.append(scanner.nextLine()); 48 | } 49 | 50 | // close scanner 51 | scanner.close(); 52 | 53 | // close url connection 54 | conn.disconnect(); 55 | 56 | // parse through our data 57 | JSONParser parser = new JSONParser(); 58 | JSONObject resultJsonObj = (JSONObject) parser.parse(String.valueOf(resultJson)); 59 | 60 | // retrieve hourly data 61 | JSONObject hourly = (JSONObject) resultJsonObj.get("hourly"); 62 | 63 | // we want to get the current hour's data 64 | // so we need to get the index of our current hour 65 | JSONArray time = (JSONArray) hourly.get("time"); 66 | int index = findIndexOfCurrentTime(time); 67 | 68 | // get temperature 69 | JSONArray temperatureData = (JSONArray) hourly.get("temperature_2m"); 70 | double temperature = (double) temperatureData.get(index); 71 | 72 | // get weather code 73 | JSONArray weathercode = (JSONArray) hourly.get("weathercode"); 74 | String weatherCondition = convertWeatherCode((long) weathercode.get(index)); 75 | 76 | // get humidity 77 | JSONArray relativeHumidity = (JSONArray) hourly.get("relativehumidity_2m"); 78 | long humidity = (long) relativeHumidity.get(index); 79 | 80 | // get windspeed 81 | JSONArray windspeedData = (JSONArray) hourly.get("windspeed_10m"); 82 | double windspeed = (double) windspeedData.get(index); 83 | 84 | // build the weather json data object that we are going to access in our frontend 85 | JSONObject weatherData = new JSONObject(); 86 | weatherData.put("temperature", temperature); 87 | weatherData.put("weather_condition", weatherCondition); 88 | weatherData.put("humidity", humidity); 89 | weatherData.put("windspeed", windspeed); 90 | 91 | return weatherData; 92 | }catch(Exception e){ 93 | e.printStackTrace(); 94 | } 95 | 96 | return null; 97 | } 98 | 99 | // retrieves geographic coordinates for given location name 100 | public static JSONArray getLocationData(String locationName){ 101 | // replace any whitespace in location name to + to adhere to API's request format 102 | locationName = locationName.replaceAll(" ", "+"); 103 | 104 | // build API url with location parameter 105 | String urlString = "https://geocoding-api.open-meteo.com/v1/search?name=" + 106 | locationName + "&count=10&language=en&format=json"; 107 | 108 | try{ 109 | // call api and get a response 110 | HttpURLConnection conn = fetchApiResponse(urlString); 111 | 112 | // check response status 113 | // 200 means successful connection 114 | if(conn.getResponseCode() != 200){ 115 | System.out.println("Error: Could not connect to API"); 116 | return null; 117 | }else{ 118 | // store the API results 119 | StringBuilder resultJson = new StringBuilder(); 120 | Scanner scanner = new Scanner(conn.getInputStream()); 121 | 122 | // read and store the resulting json data into our string builder 123 | while(scanner.hasNext()){ 124 | resultJson.append(scanner.nextLine()); 125 | } 126 | 127 | // close scanner 128 | scanner.close(); 129 | 130 | // close url connection 131 | conn.disconnect(); 132 | 133 | // parse the JSON string into a JSON obj 134 | JSONParser parser = new JSONParser(); 135 | JSONObject resultsJsonObj = (JSONObject) parser.parse(String.valueOf(resultJson)); 136 | 137 | // get the list of location data the API gtenerated from the lcoation name 138 | JSONArray locationData = (JSONArray) resultsJsonObj.get("results"); 139 | return locationData; 140 | } 141 | 142 | }catch(Exception e){ 143 | e.printStackTrace(); 144 | } 145 | 146 | // couldn't find location 147 | return null; 148 | } 149 | 150 | private static HttpURLConnection fetchApiResponse(String urlString){ 151 | try{ 152 | // attempt to create connection 153 | URL url = new URL(urlString); 154 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 155 | 156 | // set request method to get 157 | conn.setRequestMethod("GET"); 158 | 159 | // connect to our API 160 | conn.connect(); 161 | return conn; 162 | }catch(IOException e){ 163 | e.printStackTrace(); 164 | } 165 | 166 | // could not make connection 167 | return null; 168 | } 169 | 170 | private static int findIndexOfCurrentTime(JSONArray timeList){ 171 | String currentTime = getCurrentTime(); 172 | 173 | // iterate through the time list and see which one matches our current time 174 | for(int i = 0; i < timeList.size(); i++){ 175 | String time = (String) timeList.get(i); 176 | if(time.equalsIgnoreCase(currentTime)){ 177 | // return the index 178 | return i; 179 | } 180 | } 181 | 182 | return 0; 183 | } 184 | 185 | private static String getCurrentTime(){ 186 | // get current date and time 187 | LocalDateTime currentDateTime = LocalDateTime.now(); 188 | 189 | // format date to be 2023-09-02T00:00 (this is how is is read in the API) 190 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH':00'"); 191 | 192 | // format and print the current date and time 193 | String formattedDateTime = currentDateTime.format(formatter); 194 | 195 | return formattedDateTime; 196 | } 197 | 198 | // convert the weather code to something more readable 199 | private static String convertWeatherCode(long weathercode){ 200 | String weatherCondition = ""; 201 | if(weathercode == 0L){ 202 | // clear 203 | weatherCondition = "Clear"; 204 | }else if(weathercode > 0L && weathercode <= 3L){ 205 | // cloudy 206 | weatherCondition = "Cloudy"; 207 | }else if((weathercode >= 51L && weathercode <= 67L) 208 | || (weathercode >= 80L && weathercode <= 99L)){ 209 | // rain 210 | weatherCondition = "Rain"; 211 | }else if(weathercode >= 71L && weathercode <= 77L){ 212 | // snow 213 | weatherCondition = "Snow"; 214 | } 215 | 216 | return weatherCondition; 217 | } 218 | } 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /src/WeatherAppGui.java: -------------------------------------------------------------------------------- 1 | import org.json.simple.JSONObject; 2 | 3 | import javax.imageio.ImageIO; 4 | import javax.swing.*; 5 | import java.awt.*; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.awt.image.BufferedImage; 9 | import java.io.File; 10 | import java.io.IOException; 11 | 12 | public class WeatherAppGui extends JFrame { 13 | private JSONObject weatherData; 14 | 15 | public WeatherAppGui(){ 16 | // setup our gui and add a title 17 | super("Weather App"); 18 | 19 | // configure gui to end the program's process once it has been closed 20 | setDefaultCloseOperation(EXIT_ON_CLOSE); 21 | 22 | // set the size of our gui (in pixels) 23 | setSize(450, 650); 24 | 25 | // load our gui at the center of the screen 26 | setLocationRelativeTo(null); 27 | 28 | // make our layout manager null to manually position our components within the gui 29 | setLayout(null); 30 | 31 | // prevent any resize of our gui 32 | setResizable(false); 33 | 34 | addGuiComponents(); 35 | } 36 | 37 | private void addGuiComponents(){ 38 | // search field 39 | JTextField searchTextField = new JTextField(); 40 | 41 | // set the location and size of our component 42 | searchTextField.setBounds(15, 15, 351, 45); 43 | 44 | // change the font style and size 45 | searchTextField.setFont(new Font("Dialog", Font.PLAIN, 24)); 46 | 47 | add(searchTextField); 48 | 49 | // weather image 50 | JLabel weatherConditionImage = new JLabel(loadImage("src/assets/cloudy.png")); 51 | weatherConditionImage.setBounds(0, 125, 450, 217); 52 | add(weatherConditionImage); 53 | 54 | // temperature text 55 | JLabel temperatureText = new JLabel("10 C"); 56 | temperatureText.setBounds(0, 350, 450, 54); 57 | temperatureText.setFont(new Font("Dialog", Font.BOLD, 48)); 58 | 59 | // center the text 60 | temperatureText.setHorizontalAlignment(SwingConstants.CENTER); 61 | add(temperatureText); 62 | 63 | // weather condition description 64 | JLabel weatherConditionDesc = new JLabel("Cloudy"); 65 | weatherConditionDesc.setBounds(0, 405, 450, 36); 66 | weatherConditionDesc.setFont(new Font("Dialog", Font.PLAIN, 32)); 67 | weatherConditionDesc.setHorizontalAlignment(SwingConstants.CENTER); 68 | add(weatherConditionDesc); 69 | 70 | // humidity image 71 | JLabel humidityImage = new JLabel(loadImage("src/assets/humidity.png")); 72 | humidityImage.setBounds(15, 500, 74, 66); 73 | add(humidityImage); 74 | 75 | // humidity text 76 | JLabel humidityText = new JLabel("Humidity 100%"); 77 | humidityText.setBounds(90, 500, 85, 55); 78 | humidityText.setFont(new Font("Dialog", Font.PLAIN, 16)); 79 | add(humidityText); 80 | 81 | // windspeed image 82 | JLabel windspeedImage = new JLabel(loadImage("src/assets/windspeed.png")); 83 | windspeedImage.setBounds(220, 500, 74, 66); 84 | add(windspeedImage); 85 | 86 | // windspeed text 87 | JLabel windspeedText = new JLabel("Windspeed 15km/h"); 88 | windspeedText.setBounds(310, 500, 85, 55); 89 | windspeedText.setFont(new Font("Dialog", Font.PLAIN, 16)); 90 | add(windspeedText); 91 | 92 | // search button 93 | JButton searchButton = new JButton(loadImage("src/assets/search.png")); 94 | 95 | // change the cursor to a hand cursor when hovering over this button 96 | searchButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 97 | searchButton.setBounds(375, 13, 47, 45); 98 | searchButton.addActionListener(new ActionListener() { 99 | @Override 100 | public void actionPerformed(ActionEvent e) { 101 | // get location from user 102 | String userInput = searchTextField.getText(); 103 | 104 | // validate input - remove whitespace to ensure non-empty text 105 | if(userInput.replaceAll("\\s", "").length() <= 0){ 106 | return; 107 | } 108 | 109 | // retrieve weather data 110 | weatherData = WeatherApp.getWeatherData(userInput); 111 | 112 | // update gui 113 | 114 | // update weather image 115 | String weatherCondition = (String) weatherData.get("weather_condition"); 116 | 117 | // depending on the condition, we will update the weather image that corresponds with the condition 118 | switch(weatherCondition){ 119 | case "Clear": 120 | weatherConditionImage.setIcon(loadImage("src/assets/clear.png")); 121 | break; 122 | case "Cloudy": 123 | weatherConditionImage.setIcon(loadImage("src/assets/cloudy.png")); 124 | break; 125 | case "Rain": 126 | weatherConditionImage.setIcon(loadImage("src/assets/rain.png")); 127 | break; 128 | case "Snow": 129 | weatherConditionImage.setIcon(loadImage("src/assets/snow.pngImage")); 130 | break; 131 | } 132 | 133 | // update temperature text 134 | double temperature = (double) weatherData.get("temperature"); 135 | temperatureText.setText(temperature + " C"); 136 | 137 | // update weather condition text 138 | weatherConditionDesc.setText(weatherCondition); 139 | 140 | // update humidity text 141 | long humidity = (long) weatherData.get("humidity"); 142 | humidityText.setText("Humidity " + humidity + "%"); 143 | 144 | // update windspeed text 145 | double windspeed = (double) weatherData.get("windspeed"); 146 | windspeedText.setText("Windspeed " + windspeed + "km/h"); 147 | } 148 | }); 149 | add(searchButton); 150 | } 151 | 152 | // used to create images in our gui components 153 | private ImageIcon loadImage(String resourcePath){ 154 | try{ 155 | // read the image file from the path given 156 | BufferedImage image = ImageIO.read(new File(resourcePath)); 157 | 158 | // returns an image icon so that our component can render it 159 | return new ImageIcon(image); 160 | }catch(IOException e){ 161 | e.printStackTrace(); 162 | } 163 | 164 | System.out.println("Could not find resource"); 165 | return null; 166 | } 167 | } 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/assets/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/clear.png -------------------------------------------------------------------------------- /src/assets/cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/cloudy.png -------------------------------------------------------------------------------- /src/assets/humidity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/humidity.png -------------------------------------------------------------------------------- /src/assets/rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/rain.png -------------------------------------------------------------------------------- /src/assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/search.png -------------------------------------------------------------------------------- /src/assets/snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/snow.png -------------------------------------------------------------------------------- /src/assets/windspeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/curadProgrammer/WeatherAppGUI-Java/85b1ca30d921775c3a0f2cbf04ffa4b5883fd072/src/assets/windspeed.png --------------------------------------------------------------------------------