I’m new to Java, and I was assigned in my class to develop a code for the following question, I was only able to do the design, after that I didn’t know how to continue adding the actions to every button.
This is the question:
If anyone has ever solved it, please share it. Thanks for help in advance!
Advertisement
Answer
Since this is homework, I’m not providing the entire code. I will provide snippets.
Here’s the GUI I created. I wish I could show it as an animated GIF.
I added a stop button to stop the word rotation.
I wrote the code by breaking the problem down into smaller and smaller steps, then coding each of the steps. I ran many tests of the GUI before I finished it. Some of the tests failed, and I had to revise the code.
I wrote 6 classes. The main class created the JFrame
, the letter panel group, and the control panel on the bottom. I wrote a LetterPanel
class to create one letter panel. I wrote 3 actionListener
classes, one for the JComboBox
, one for the rotate button, and one for the stop button. I wrote an Animation
class that rotates the letters every second.
Here are the colors I used to get the 4 shades of green.
Color[] colors = { new Color(50, 117, 1), new Color(65, 159, 0), new Color(88, 201, 5), new Color(107, 242, 2) };
Setting up the main JPanel
to hold the 4 LetterPanel
objects was a bit tricky. Here’s how I did it.
JPanel panel = new JPanel(); panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
The LetterPanel
class extended a JPanel
and overrode the paintComponent
method. First, I called the super.paintComponent
method. Always call the super.paintComponent
method first. Then, I painted the background color. Then, I painted the letter.
To paint the letter in each LetterPanel
, I used the following code.
/** * Draw a String centered in the middle of the panel. * * @param g2d The Graphics2D instance. * @param text The String to draw. * @param font The Font to draw with. */ public void drawCenteredString(Graphics2D g2d, String text, Font font) { FontMetrics metrics = g2d.getFontMetrics(font); int x = (getWidth() - metrics.stringWidth(text)) / 2; int y = ((getHeight() - metrics.getHeight()) / 2) + metrics.getAscent(); g2d.setFont(font); g2d.drawString(text, x, y); }
The JComboBox actionListener gets the selected word from the JComboBox. The Oracle tutorial, How to Use Combo Boxes, tells you exactly how I set up the word JComboBox.
The rotate button actionListener
checks if both JCheckBox
fields are checked. Then it checks if neither JCheckBox
field is checked. Finally, it starts an Animation
thread.
The stop button stops the Animation
thread.
The Animation
thread rotates the word and pauses 1 second to allow you to see the rotation.
Here is the run loop.
@Override public void run() { while (running) { updatePanel(); sleep(1000L); if (leftSelected) { word = rotateLeft(word); } else { word = rotateRight(word); } } }
Here are my rotation methods.
private String rotateLeft(String word) { return word.substring(1) + word.substring(0, 1); } private String rotateRight(String word) { return word.substring(word.length() - 1) + word.substring(0, word.length() - 1); }
Edited to add;
I’d forgotten I’d answered this question. Enough time has passed so I’ll post the entire application. I made the additional classes inner classes so I can post this code as one block.
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class RotateWord implements Runnable { public static void main(String[] args) { SwingUtilities.invokeLater(new RotateWord()); } private Animation animation; private JCheckBox leftBox; private JCheckBox rightBox; private JComboBox<String> wordComboBox; private JFrame frame; private LetterPanel[] letterPanel; private String word; public RotateWord() { this.word = "WORD"; } @Override public void run() { frame = new JFrame("Rotate Word"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(createWordPanel(word), BorderLayout.CENTER); frame.add(createControlPanel(word), BorderLayout.AFTER_LAST_LINE); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private JPanel createWordPanel(String word) { JPanel panel = new JPanel(); panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); Color[] colors = { new Color(50, 117, 1), new Color(65, 159, 0), new Color(88, 201, 5), new Color(107, 242, 2) }; letterPanel = new LetterPanel[word.length()]; for (int i = 0; i < word.length(); i++) { letterPanel[i] = new LetterPanel(colors[i], word.charAt(i)); panel.add(letterPanel[i]); } return panel; } public void updateWordPanel(String word) { for (int i = 0; i < word.length(); i++) { letterPanel[i].setLetter(word.charAt(i)); letterPanel[i].repaint(); } } private JPanel createControlPanel(String word) { JPanel panel = new JPanel(); String[] words = { "ABLE", "BATH", "EXIT", "WORD" }; wordComboBox = new JComboBox<>(words); wordComboBox.setSelectedItem(word); wordComboBox.addActionListener(new WordListener()); panel.add(wordComboBox); leftBox = new JCheckBox("Left"); panel.add(leftBox); rightBox = new JCheckBox("Right"); panel.add(rightBox); JButton rotateButton = new JButton("Rotate"); rotateButton.addActionListener(new RotateListener()); panel.add(rotateButton); JButton stopButton = new JButton("Stop"); stopButton.addActionListener(new StopListener()); panel.add(stopButton); return panel; } public class LetterPanel extends JPanel { private static final long serialVersionUID = 1L; private char letter; private Color backgroundColor; private Font font; public LetterPanel(Color backgroundColor, char letter) { this.backgroundColor = backgroundColor; this.letter = letter; this.font = getFont().deriveFont(96f) .deriveFont(Font.BOLD); this.setPreferredSize(new Dimension(120, 200)); } public void setLetter(char letter) { this.letter = letter; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setColor(backgroundColor); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.setColor(Color.BLACK); drawCenteredString(g2d, Character.toString(letter), font); } /** * Draw a String centered in the middle of the panel. * * @param g2d The Graphics2D instance. * @param text The String to draw. * @param font The Font to draw with. */ public void drawCenteredString(Graphics2D g2d, String text, Font font) { FontMetrics metrics = g2d.getFontMetrics(font); int x = (getWidth() - metrics.stringWidth(text)) / 2; int y = ((getHeight() - metrics.getHeight()) / 2) + metrics.getAscent(); g2d.setFont(font); g2d.drawString(text, x, y); } } public class WordListener implements ActionListener { @Override public void actionPerformed(ActionEvent event) { word = (String) wordComboBox.getSelectedItem(); updateWordPanel(word); } } public class RotateListener implements ActionListener { @Override public void actionPerformed(ActionEvent event) { boolean leftSelected = leftBox.isSelected(); boolean rightSelected = rightBox.isSelected(); if (leftSelected && rightSelected) { word = "OOPS"; updateWordPanel(word); return; } if (!leftSelected && !rightSelected) { return; } word = (String) wordComboBox.getSelectedItem(); updateWordPanel(word); animation = new Animation(leftSelected); new Thread(animation).start(); } } public class StopListener implements ActionListener { @Override public void actionPerformed(ActionEvent event) { if (animation != null) { animation.setRunning(false); animation = null; } } } public class Animation implements Runnable { private boolean leftSelected; private volatile boolean running; public Animation(boolean leftSelected) { this.leftSelected = leftSelected; this.running = true; } @Override public void run() { while (running) { updatePanel(); sleep(1000L); if (leftSelected) { word = rotateLeft(word); } else { word = rotateRight(word); } } } public synchronized void setRunning(boolean running) { this.running = running; } private String rotateLeft(String word) { return word.substring(1) + word.substring(0, 1); } private String rotateRight(String word) { return word.substring(word.length() - 1) + word.substring(0, word.length() - 1); } private void updatePanel() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { updateWordPanel(word); } }); } private void sleep(long duration) { try { Thread.sleep(duration); } catch (InterruptedException e) { // Deliberately left blank } } } }