I want to make a panel that, when the mouse enters it, its height increases smoothly and when the mouse leaves it, its height decreases smoothly.
public class Main {
private static final int INITIAL_HEIGHT = 150;
private static final int TARGET_HEIGHT = 200;
private static final int ANIMATION_DELAY = 10;
private static final int INCREMENT = 2;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, INITIAL_HEIGHT));
panel.setBackground(Color.BLUE);
frame.add(panel);
frame.pack();
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Timer(ANIMATION_DELAY, new ActionListener() {
private int currentHeight = INITIAL_HEIGHT;
@Override
public void actionPerformed(ActionEvent e) {
if (currentHeight < TARGET_HEIGHT) {
currentHeight += INCREMENT;
panel.setPreferredSize(new Dimension(200, currentHeight));
panel.revalidate();
frame.pack();
} else {
((Timer) e.getSource()).stop();
}
}
}).start();
}
@Override
public void mouseExited(MouseEvent e) {
new Timer(ANIMATION_DELAY, new ActionListener() {
private int currentHeight = TARGET_HEIGHT;
@Override
public void actionPerformed(ActionEvent e) {
if (currentHeight > INITIAL_HEIGHT) {
currentHeight -= INCREMENT;
panel.setPreferredSize(new Dimension(200, currentHeight));
panel.revalidate();
frame.pack();
} else {
((Timer) e.getSource()).stop();
}
}
}).start();
}
});
});
}
}
The problem is that if I move the mouse out of the panel while changing the size of the panel, it does not work properly.
Try to use only one timer and add a boolean to track the direction and make sure that the animation is happening in one direction
public class Main {
private static final int INITIAL_HEIGHT = 150;
private static final int TARGET_HEIGHT = 200;
private static final int ANIMATION_DELAY = 10;
private static final int INCREMENT = 2;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(300, 300); // Adjust frame size to better see the effect
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, INITIAL_HEIGHT));
panel.setBackground(Color.BLUE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
Timer timer = new Timer(ANIMATION_DELAY, null);
boolean growing = false;
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
if (!growing) {
growing = true;
timer.removeActionListener(timer.getActionListeners()[0]);
timer.addActionListener(new ActionListener() {
private int currentHeight = panel.getPreferredSize().height;
@Override
public void actionPerformed(ActionEvent e) {
if (currentHeight < TARGET_HEIGHT) {
currentHeight += INCREMENT;
panel.setPreferredSize(new Dimension(200, currentHeight));
panel.revalidate();
frame.pack();
} else {
timer.stop();
}
}
});
timer.start();
}
}
@Override
public void mouseExited(MouseEvent e) {
if (growing) {
growing = false;
timer.removeActionListener(timer.getActionListeners()[0]);
timer.addActionListener(new ActionListener() {
private int currentHeight = panel.getPreferredSize().height;
@Override
public void actionPerformed(ActionEvent e) {
if (currentHeight > INITIAL_HEIGHT) {
currentHeight -= INCREMENT;
panel.setPreferredSize(new Dimension(200, currentHeight));
panel.revalidate();
frame.pack();
} else {
timer.stop();
}
}
});
timer.start();
}
}
});
});
}}