Consider the following classes:
public class ControlPanel {
	
	/**
	 * Initializes and adds components to the panel and sets layouts.
	 * Includes start, stop, save and load buttons for users to use.
	 * @param panel The panel where all the components are added.
	 */
	public static void Components(JPanel panel) {
		
		panel.setLayout(null);
		
		//Temperature components.
		JLabel InitialTempLabel = new JLabel("Initial Temperature (integer):");
		InitialTempLabel.setBounds(20, 20, 190, 25);
		panel.add(InitialTempLabel);
		
		JTextField InitialTempText = new JTextField(20);
		InitialTempText.setBounds(210, 20, 100, 25);
		panel.add(InitialTempText);
		
		JLabel IdealTempLabel = new JLabel("Ideal Temperature:");
		IdealTempLabel.setBounds(20, 60, 190, 25);
		panel.add(IdealTempLabel);
		
		JTextField IdealTempText = new JTextField(20);
		IdealTempText.setBounds(210, 60, 100, 25);
		panel.add(IdealTempText);
		
		JLabel FurnaceRateLabel = new JLabel("Furnace Rate:");
		FurnaceRateLabel.setBounds(20, 100, 190, 25);
		panel.add(FurnaceRateLabel);
		
		JTextField FurnaceRateText = new JTextField(20);
		FurnaceRateText.setBounds(210, 100, 100, 25);
		panel.add(FurnaceRateText);
		
		JLabel ACRateLabel = new JLabel("Air-Conditioner Rate:");
		ACRateLabel.setBounds(20, 140, 190, 25);
		panel.add(ACRateLabel);
		
		JTextField ACRateText = new JTextField(20);
		ACRateText.setBounds(210, 140, 100, 25);
		panel.add(ACRateText);
		
		JLabel NoneRateLabel = new JLabel("Ambient Temperature Rate:");
		NoneRateLabel.setBounds(20, 180, 190, 25);
		panel.add(NoneRateLabel);
		
		JTextField NoneRateText = new JTextField(20);
		NoneRateText.setBounds(210, 180, 100, 25);
		panel.add(NoneRateText);
		
		JLabel CurrentTempLabel = new JLabel("Current Temperature");
		CurrentTempLabel.setBounds(20, 220, 320, 25);
		panel.add(CurrentTempLabel);
		
		JLabel FurnaceIndicatorLabel = new JLabel("Furnace:");
		FurnaceIndicatorLabel.setBounds(20, 260, 80, 25);
		panel.add(FurnaceIndicatorLabel);
		
		JLabel ACIndicatorLabel = new JLabel("Air Conditioner:");
		ACIndicatorLabel.setBounds(20, 300, 110, 25);
		panel.add(ACIndicatorLabel);
		
		JPanel FurnaceIndicator = new JPanel();
		FurnaceIndicator.setBounds(210, 260, 25, 25);
		FurnaceIndicator.setBackground(Color.RED);
		panel.add(FurnaceIndicator);
		
		JPanel ACIndicator = new JPanel();
		ACIndicator.setBounds(210, 300, 25, 25);
		ACIndicator.setBackground(Color.RED);
		panel.add(ACIndicator);
		
		//Moisture components.
		JLabel InitialMoistureLabel = new JLabel("Initial Moisture(integer):");
		InitialMoistureLabel.setBounds(330, 20, 190, 25);
		panel.add(InitialMoistureLabel);
		
		JTextField InitialMoistureText = new JTextField(20);
		InitialMoistureText.setBounds(520, 20, 100, 25);
		panel.add(InitialMoistureText);
		
		JLabel IdealMoistureLabel = new JLabel("Ideal Moisture:");
		IdealMoistureLabel.setBounds(330, 60, 190, 25);
		panel.add(IdealMoistureLabel);
		
		JTextField IdealMoistureText = new JTextField(20);
		IdealMoistureText.setBounds(520, 60, 100, 25);
		panel.add(IdealMoistureText);
		
		JLabel IdealMoistureRangeLabel = new JLabel("Moisture Comfort Range:");
		IdealMoistureRangeLabel.setBounds(330, 100, 190, 25);
		panel.add(IdealMoistureRangeLabel);
		
		JTextField IdealMoistureRangeText = new JTextField(20);
		IdealMoistureRangeText.setBounds(520, 100, 100, 25);
		panel.add(IdealMoistureRangeText);
		
		JLabel SprinklerOnRateLabel = new JLabel("Sprinkler On Rate:");
		SprinklerOnRateLabel.setBounds(330, 140, 190, 25);
		panel.add(SprinklerOnRateLabel);
		
		JTextField SprinklerOnRateText = new JTextField(20);
		SprinklerOnRateText.setBounds(520, 140, 100, 25);
		panel.add(SprinklerOnRateText);
		
		JLabel SprinklerOffRateLabel = new JLabel("Ambient Moisture Rate:");
		SprinklerOffRateLabel.setBounds(330, 180, 190, 25);
		panel.add(SprinklerOffRateLabel);
		
		JTextField SprinklerOffRateText = new JTextField(20);
		SprinklerOffRateText.setBounds(520, 180, 100, 25);
		panel.add(SprinklerOffRateText);
		
		JLabel CurrentMoistureLabel = new JLabel("Current Moisture:");
		CurrentMoistureLabel.setBounds(330, 220, 190, 25);
		panel.add(CurrentMoistureLabel);
		
		JLabel SprinklerIndicatorLabel = new JLabel("Sprinkler:");
		SprinklerIndicatorLabel.setBounds(330, 260, 190, 25);
		panel.add(SprinklerIndicatorLabel);
		
		JPanel SprinklerIndicator = new JPanel();
		SprinklerIndicator.setBounds(520, 260, 25, 25);
		SprinklerIndicator.setBackground(Color.RED);
		panel.add(SprinklerIndicator);
		
		//Humidity components.
		JLabel InitialHumidityLabel = new JLabel("Initial Humidity(integer):");
		InitialHumidityLabel.setBounds(660, 20, 190, 25);
		panel.add(InitialHumidityLabel);
		
		JTextField InitialHumidityText = new JTextField(20);
		InitialHumidityText.setBounds(850, 20, 100, 25);
		panel.add(InitialHumidityText);
		
		JLabel IdealHumidityLabel = new JLabel("Ideal Moisture:");
		IdealHumidityLabel.setBounds(660, 60, 190, 25);
		panel.add(IdealHumidityLabel);
		
		JTextField IdealHumidityText = new JTextField(20);
		IdealHumidityText.setBounds(850, 60, 100, 25);
		panel.add(IdealHumidityText);
		
		JLabel IdealHumidityRangeLabel = new JLabel("Humidity Comfort Range:");
		IdealHumidityRangeLabel.setBounds(660, 100, 190, 25);
		panel.add(IdealHumidityRangeLabel);
		
		JTextField IdealHumidityRangeText = new JTextField(20);
		IdealHumidityRangeText.setBounds(850, 100, 100, 25);
		panel.add(IdealHumidityRangeText);
		
		JLabel HumidifierOnRateLabel = new JLabel("Humidifier On Rate:");
		HumidifierOnRateLabel.setBounds(660, 140, 190, 25);
		panel.add(HumidifierOnRateLabel);
		
		JTextField HumidifierOnRateText = new JTextField(20);
		HumidifierOnRateText.setBounds(850, 140, 100, 25);
		panel.add(HumidifierOnRateText);
		
		JLabel HumidifierOffRateLabel = new JLabel("Ambient Humidity Rate:");
		HumidifierOffRateLabel.setBounds(660, 180, 190, 25);
		panel.add(HumidifierOffRateLabel);
		
		JTextField HumidifierOffRateText = new JTextField(20);
		HumidifierOffRateText.setBounds(850, 180, 100, 25);
		panel.add(HumidifierOffRateText);
		
		JLabel CurrentHumidityLabel = new JLabel("Current Humidity:");
		CurrentHumidityLabel.setBounds(660, 220, 190, 25);
		panel.add(CurrentHumidityLabel);
		
		JLabel HumidifierIndicatorLabel = new JLabel("Humidifier:");
		HumidifierIndicatorLabel.setBounds(660, 260, 190, 25);
		panel.add(HumidifierIndicatorLabel);
		
		JPanel HumidifierIndicator = new JPanel();
		HumidifierIndicator.setBounds(850, 260, 25, 25);
		HumidifierIndicator.setBackground(Color.RED);
		panel.add(HumidifierIndicator);
		
		//Control buttons
		
		//Start and stop buttons.
		JButton StartButton = new JButton("Start");
		StartButton.setBounds(20, 360, 130, 30);
		panel.add(StartButton);
		
		JButton StopButton = new JButton("Stop");
		StopButton.setBounds(160, 360, 130, 30);
		StopButton.setEnabled(false);
		panel.add(StopButton);
		
		//Save button for save simulation
		JButton SaveButton = new JButton("Save");
		SaveButton.setBounds(500, 360, 130, 30);
		panel.add(SaveButton);

		//Load button for load simulation.
		JButton LoadButton = new JButton("Load");
		LoadButton.setBounds(640, 360, 130, 30);
		panel.add(LoadButton);
		
		
		//Pass necessary variables and instantiate required classes and objects.
		TemperatureControl tempControl = new TemperatureControl(IdealTempText, FurnaceRateText, 
				ACRateText, NoneRateText, CurrentTempLabel, FurnaceIndicator, ACIndicator);
		MoistureControl moistureControl = new MoistureControl(IdealMoistureText, IdealMoistureRangeText, 
				SprinklerOnRateText, SprinklerOffRateText, CurrentMoistureLabel, SprinklerIndicator);
		HumidityControl humidityControl = new HumidityControl(IdealHumidityText, IdealHumidityRangeText, 
				HumidifierOnRateText, HumidifierOffRateText, CurrentHumidityLabel, HumidifierIndicator);
		
		//Action listener for the start button.
		StartButton.addActionListener(e -> {
			if(!tempControl.isAlive() && !moistureControl.isAlive() && !humidityControl.isAlive()) {
				try {
					int InitialTemp = Integer.parseInt(InitialTempText.getText());
					int InitialMoisture = Integer.parseInt(InitialMoistureText.getText());
					int InitialHumidity = Integer.parseInt(InitialHumidityText.getText());
					
					
					tempControl.setCurrentTemp(InitialTemp);
					moistureControl.setCurrentMoisture(InitialMoisture);
					humidityControl.setCurrentHumidity(InitialHumidity);
					
					tempControl.start();
                    moistureControl.start();
                    humidityControl.start();
					
					StartButton.setEnabled(false);
					StopButton.setEnabled(true);
				} catch (NumberFormatException ex) {
					JOptionPane.showMessageDialog(panel, "Invalid input format (enter integers).");
				}
			} else {
				tempControl.pauseSimulation(false);
				moistureControl.pauseSimulation(false);
				humidityControl.pauseSimulation(false);
				
				StartButton.setEnabled(false);
				StopButton.setEnabled(true);
			}
		});
		
		//Action listener for save button.
		SaveButton.addActionListener(e -> {
			FileDialog fileDialog = new FileDialog((Frame) null, "Save Simulation Data", FileDialog.SAVE);
			fileDialog.setFilenameFilter((dir, name) -> name.endsWith(".txt"));
			fileDialog.setVisible(true);
			
			String FileName = fileDialog.getFile();
			String Directory = fileDialog.getDirectory();
			
			
			if (FileName != null && Directory != null) {
				
				String SimulationData = getSimulationData(tempControl, moistureControl, humidityControl);
				String FilePath = Directory + FileName;
				
				try (FileWriter fileWriter = new FileWriter(FilePath, false)){
					fileWriter.write(SimulationData);
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(panel, "Saving error.");
				}
			}
		});
		
		//Action listener for load button.
		LoadButton.addActionListener(e -> {
			FileDialog fileDialog = new FileDialog((Frame) null, "Load Simulation Data", FileDialog.LOAD);
			fileDialog.setFilenameFilter((dir, name) -> name.endsWith(".txt"));
			fileDialog.setVisible(true);
			
			
			String FileName = fileDialog.getFile();
			String Directory = fileDialog.getDirectory();
			
			if (FileName != null && Directory != null) {
				StringBuilder SimulationData = new StringBuilder();
				String FilePath = Directory + FileName;
				
				try (BufferedReader bufferedReader = new BufferedReader(new FileReader(FilePath))) {
					String line;
					while ((line = bufferedReader.readLine()) != null) {
						SimulationData.append(line);
					}
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(panel, "Loading error.");
				}
				
				if (SimulationData.length() > 0) {
					JOptionPane.showMessageDialog(panel, SimulationData.toString(), "Loaded Simulation", 
							JOptionPane.INFORMATION_MESSAGE);
				}
			}
		});
		
		//Action listener for stop button.
		StopButton.addActionListener(e -> {
            tempControl.pauseSimulation(true);
            moistureControl.pauseSimulation(true);
            humidityControl.pauseSimulation(true);

            StartButton.setEnabled(true);
            StopButton.setEnabled(false);
        });
	}
	/**
	 * Combines the simulation data from TemperatureControl, MoistureControl, HumidityControl objects
	 * into a single string.
	 * @param tempControl The TemperatureControl object providing temperature data.
	 * @param moistureControl The MoistureControl object providing moisture data.
	 * @param humidityControl The HumidityControl object providing humidity data.
	 * @return A formatted string with the combined simulation data.
	 */
	public static String getSimulationData(TemperatureControl tempControl, 
			MoistureControl moistureControl, HumidityControl humidityControl) {
		
		StringBuilder SimulationData = new StringBuilder();
		List<String> TempDataList = Arrays.asList(tempControl.SimulationData.toString().split("\n"));
		List<String> MoistureDataList = Arrays.asList(moistureControl.SimulationData.toString().split("\n"));
		List<String> HumidityDataList = Arrays.asList(humidityControl.SimulationData.toString().split("\n"));
		
		int MaxData = Math.max(TempDataList.size(), Math.max(MoistureDataList.size(), HumidityDataList.size()));
		
		
		for (int i = 0; i < MaxData; i++) {
			if (i < TempDataList.size()) {
				SimulationData.append(TempDataList.get(i)).append(", ");
			}
			if (i < MoistureDataList.size()) {
				SimulationData.append(MoistureDataList.get(i)).append(", ");
			}
			if (i < HumidityDataList.size()) {
				SimulationData.append(HumidityDataList.get(i)).append(", ");
			}
			SimulationData.append("\n");
		}
		
		return SimulationData.toString();
	}
}