/** * A GUI class to run the Virtual Pet Lab * Requires javax.swing and java.awt * @author Kim Hermans * Image Credit: J.P. O'Hara & Jamie O'Hara * @November 2024 */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; public class VirtualPetGUIRunner { // CHANGE THIS VARIABLE VALUE TO TEST AT A DIFFERENT SPEED private final int INTERVAL_IN_SECONDS = 10; private String info; private int timerSeconds, animationTimerSeconds; private boolean isEating, isPlaying; private VirtualPet pet3; private ImageIcon imageHappy, imageSad, imageEat, imagePlay; private JFrame frame; private JPanel petPanel, menuPanel, mainPanel, statsPanel, timerPanel; private JLabel petLabel,statsLabel, messageLabel, timerLabel; private JButton foodButton, playButton; private JMenu newPetMenu; private JMenuItem petRunner3, petRunner4; private JMenuBar menuBar; public VirtualPetGUIRunner(String name) { pet3 = new VirtualPet(name); isPlaying = isEating = false; // Automatically calls update after INTERVAL_IN_SECONDS time ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(() -> { pet3.updateStatus(); }, INTERVAL_IN_SECONDS, INTERVAL_IN_SECONDS, TimeUnit.SECONDS); // Calls helper methods to initialize components of GUI initPetDisplayPanel(); initTimerPanel(); initStatsPanel(); initButtons(); fillLayout(); initMenuBar(); // Initializes the frame frame = new JFrame(); frame.setPreferredSize(new Dimension(350, 500)); frame.setTitle("Virtual Pet"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Adds all components to the frame and makes visible frame.add(mainPanel); frame.setJMenuBar(menuBar); frame.pack(); frame.setVisible(true); } // Initializes the Feed and Play buttons and the panel that contains them public void initButtons() { GridBagConstraints c = new GridBagConstraints(); foodButton = new JButton("Feed"); foodButton.addActionListener(new FoodButtonListener()); foodButton.setPreferredSize(new Dimension(80, 30)); foodButton.setMaximumSize(new Dimension(80, 30)); playButton = new JButton("Play"); playButton.addActionListener(new PlayButtonListener()); playButton.setPreferredSize(new Dimension(80, 30)); playButton.setMaximumSize(new Dimension(80, 30)); menuPanel = new JPanel(); menuPanel.setLayout(new BoxLayout(menuPanel, BoxLayout.Y_AXIS)); menuPanel.add(Box.createVerticalStrut(50)); menuPanel.add(foodButton, c); menuPanel.add(Box.createVerticalStrut(10)); menuPanel.add(playButton, c); menuPanel.add(Box.createVerticalStrut(10)); } // Initializes the panel that contains the information text public void initStatsPanel() { info = "" + pet3.toString().replaceAll("\n", "") + ""; statsLabel = new JLabel(info); statsLabel.setBorder(BorderFactory.createEmptyBorder(0, 15, 15, 0)); messageLabel = new JLabel("Happy Birthday, " + pet3.getName() + "!"); messageLabel.setForeground(Color.blue); messageLabel.setBorder(BorderFactory.createEmptyBorder(0, 15, 15, 0)); statsPanel = new JPanel(new GridLayout(2,1)); statsPanel.add(messageLabel); statsPanel.add(statsLabel); } // Initializes the panel that displays the VirtualPet public void initPetDisplayPanel() { imageHappy = new ImageIcon("petHappy.gif"); imageSad = new ImageIcon("petSad.gif"); imageEat = new ImageIcon("petEat.gif"); imagePlay = new ImageIcon("petPlay.gif"); petLabel = new JLabel(imageHappy); petPanel = new JPanel(new BorderLayout()); petPanel.add(petLabel); } // Initializes the timer that is displayed public void initTimerPanel() { timerSeconds = 0; timerLabel = new JLabel("00:00"); Timer timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timerSeconds++; int minutes = timerSeconds / 60; int remainingSeconds = timerSeconds % 60; timerLabel.setText(String.format("%02d:%02d", minutes, remainingSeconds)); info = "" + pet3.toString().replaceAll("\n", "") + ""; statsLabel.setText(info); if(!isPlaying && !isEating) { if((ImageIcon)petLabel.getIcon() != imageSad && (pet3.getEnergyLevel() < 5 || pet3.getHappinessLevel() < 5)) petLabel.setIcon(imageSad); else if((ImageIcon)petLabel.getIcon() != imageHappy && (pet3.getEnergyLevel() >= 5 && pet3.getHappinessLevel() >= 5)) petLabel.setIcon(imageHappy); } } }); timer.start(); timerPanel = new JPanel(); timerPanel.add(timerLabel); timerPanel.setLayout(new GridBagLayout()); } // Initializes the Menu Bar that allows you to create a new Virtual Pet public void initMenuBar() { petRunner3 = new JMenuItem("Activity 3"); petRunner3.addActionListener(new NewPet3Listener()); petRunner4 = new JMenuItem("Activity 4"); petRunner4.addActionListener(new NewPet4Listener()); newPetMenu = new JMenu("New Pet"); newPetMenu.add(petRunner3); newPetMenu.add(petRunner4); menuBar = new JMenuBar(); menuBar.add(newPetMenu); } // Organizes the layout for the main panel public void fillLayout() { mainPanel = new JPanel(); mainPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 60; c.weighty = 70; c.gridx = 0; c.gridy = 0; mainPanel.add(petPanel, c); c.weightx = 40; c.gridx = 1; mainPanel.add(menuPanel, c); c.weightx = 60; c.weighty = 30; c.gridx = 0; c.gridy = 1; mainPanel.add(statsPanel, c); c.weightx = 40; c.gridx = 1; mainPanel.add(timerPanel, c); } // Defines the action when the Feed button is clicked class FoodButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { pet3.feed(); messageLabel.setText("You have fed " + pet3.getName()); info = "" + pet3.toString().replaceAll("\n", "") + ""; statsLabel.setText(info); animationTimerSeconds = 0; animationTimerSeconds = 0; isEating = true; petLabel.setIcon(imageEat); // Timer to show eating image for 2 seconds Timer animationTimer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { animationTimerSeconds++; if(animationTimerSeconds >= 2) { if(pet3.getEnergyLevel() < 5 || pet3.getHappinessLevel() < 5) petLabel.setIcon(imageSad); else petLabel.setIcon(imageHappy); isEating = false; ((Timer) e.getSource()).stop(); } } }); animationTimer.start(); } } // Defines the action when the Play button is clicked class PlayButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { pet3.play(); messageLabel.setText("You have played with " + pet3.getName()); info = "" + pet3.toString().replaceAll("\n", "") + ""; statsLabel.setText(info); animationTimerSeconds = 0; isPlaying = true; petLabel.setIcon(imagePlay); // Timer to show playing image for 2 seconds Timer animationTimer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { animationTimerSeconds++; if(animationTimerSeconds >= 2) { if(pet3.getEnergyLevel() < 5 || pet3.getHappinessLevel() < 5) petLabel.setIcon(imageSad); else petLabel.setIcon(imageHappy); isPlaying = false; ((Timer) e.getSource()).stop(); } } }); animationTimer.start(); } } // Defines the action when a New Pet from Activity 3 is clicked class NewPet3Listener implements ActionListener { public void actionPerformed(ActionEvent e) { try { String input = JOptionPane.showInputDialog("Enter your virtual pet's name:"); VirtualPetGUIRunner init = new VirtualPetGUIRunner(input); frame.dispose(); } catch(Exception err) { System.out.println(err); } } } // Defines the action when a New Pet from Activity 4 is clicked class NewPet4Listener implements ActionListener { public void actionPerformed(ActionEvent e) { // "Uncomment" code when you complete Activity 4 and include // VirtualPetGUIRunner4 in your project /* try { String input = JOptionPane.showInputDialog("Enter your virtual pet's name:"); VirtualPetGUIRunner4 init = new VirtualPetGUIRunner4(input); frame.dispose(); } catch(Exception err) { System.out.println(err); } */ } } public static void main(String [] args) throws IOException { String input = JOptionPane.showInputDialog("Enter your virtual pet's name:"); VirtualPetGUIRunner init = new VirtualPetGUIRunner(input); } }