├── 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 |
21 | - Java 18
22 | - JSON Simple - Used to parse and read through JSON data
23 | - HTTPURLConnection: Java's built-in library for making HTTP requests to fetch data from external APIs.
24 |
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
--------------------------------------------------------------------------------