import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Comparator; public class CarAnimation extends JFrame { public CarAnimation() { setTitle("Анимация с машинкой"); setSize(300, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); // панель анимации AnimationPanel panel = new AnimationPanel(); JMenuBar menuBar = new JMenuBar(); // меню файл JMenu fileMenu = new JMenu("Файл"); JMenuItem useFolderItem = new JMenuItem("Использовать картинки из папки"); JMenuItem exitItem = new JMenuItem("Выход"); useFolderItem.addActionListener(e -> { JFileChooser chooser = new JFileChooser(); // только папки chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setDialogTitle("Выберите папку с изображениями машинок"); int returnVal = chooser.showOpenDialog(CarAnimation.this); if (returnVal == JFileChooser.APPROVE_OPTION) { // выбранная папка в панель panel.loadImagesFromFolder(chooser.getSelectedFile()); } }); exitItem.addActionListener(e -> System.exit(0)); fileMenu.add(useFolderItem); fileMenu.add(exitItem); // меню скорость JMenu speedMenu = new JMenu("Скорость машинки"); JMenuItem slowSpeed = new JMenuItem("Медленно"); JMenuItem normalSpeed = new JMenuItem("Нормально"); JMenuItem fastSpeed = new JMenuItem("Быстро"); slowSpeed.addActionListener(e -> panel.setSpeed(300)); normalSpeed.addActionListener(e -> panel.setSpeed(100)); fastSpeed.addActionListener(e -> panel.setSpeed(30)); speedMenu.add(slowSpeed); speedMenu.add(normalSpeed); speedMenu.add(fastSpeed); // меню справка JMenu helpMenu = new JMenu("Справка"); JMenuItem aboutItem = new JMenuItem("О программе"); aboutItem.addActionListener(e -> JOptionPane.showMessageDialog(this, "Анимация машинки\nУправление: наведите мышь на окно.")); helpMenu.add(aboutItem); // сборка менюбара menuBar.add(fileMenu); menuBar.add(speedMenu); menuBar.add(helpMenu); setJMenuBar(menuBar); add(panel); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { CarAnimation app = new CarAnimation(); app.setVisible(true); }); } } class AnimationPanel extends JPanel implements MouseListener, java.awt.event.MouseMotionListener { private final BufferedImage[] frames; private int currentFrameIndex = 0; private volatile boolean isMouseInside = false; // флаг для управления потоком private final Thread animationThread; private volatile int speedDelay = 100; // переменная для скорости private BufferedImage[] currentFrames; // чтобы можно было менять массив картинок private volatile boolean isFolderMode = false; // true, если загружены файлы из папки // метод для изменения скорости public void setSpeed(int newSpeed) { this.speedDelay = newSpeed; } // метод для загрузки картинок из папки public void loadImagesFromFolder(File folder) { // список всех файлов в папке File[] files = folder.listFiles(); if (files == null || files.length == 0) { JOptionPane.showMessageDialog(this, "Папка пуста!"); return; } // только картинки (png, jpg, gif) File[] imageFiles = Arrays.stream(files) .filter(f -> f.getName().toLowerCase().endsWith(".png") || f.getName().toLowerCase().endsWith(".jpg") || f.getName().toLowerCase().endsWith(".jpeg") || f.getName().toLowerCase().endsWith(".gif")) .sorted(Comparator.comparing(File::getName)) // сортировка по имени .toArray(File[]::new); if (imageFiles.length == 0) { JOptionPane.showMessageDialog(this, "В выбранной папке нет подходящих изображений!"); return; } // найденные файлы в массив BufferedImage BufferedImage[] newFrames = new BufferedImage[imageFiles.length]; try { for (int i = 0; i < imageFiles.length; i++) { newFrames[i] = ImageIO.read(imageFiles[i]); } // обновляем массив в панели this.currentFrames = newFrames; this.isFolderMode = true; this.currentFrameIndex = 0; // Сбрасываем кадр на первый this.repaint(); JOptionPane.showMessageDialog(this, "Загружено кадров: " + newFrames.length); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Ошибка при чтении файлов: " + e.getMessage()); e.printStackTrace(); } } // private BufferedImage[] createDummyCarArray(Color color) { // BufferedImage[] newFrames = new BufferedImage[5]; // for (int i = 0; i < 5; i++) { // newFrames[i] = createDummyCar(i, 5, color); // цвет в метод отрисовки // } // return newFrames; // } private BufferedImage createDummyCar(int frame, int total, Color color) { BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); int offset = frame * 10; g.setColor(color); // Используем переданный цвет g.fillRect(20 + offset, 40, 100, 40); g.setColor(Color.BLACK); g.fillOval(30 + offset, 70, 20, 20); g.fillOval(90 + offset, 70, 20, 20); g.dispose(); return img; } public AnimationPanel() { // подготовка изображений frames = prepareImages(); this.currentFrames = prepareImages(); // создание и запуск потока анимации animationThread = new Thread(new Runnable() { @Override public void run() { while (true) { try { // условие только если мышь внутри окна if (isMouseInside) { currentFrameIndex = (currentFrameIndex + 1) % frames.length; repaint(); Thread.sleep(speedDelay); } else { Thread.sleep(50); } } catch (InterruptedException e) { break; // выход } } } }); animationThread.start(); addMouseListener(this); addMouseMotionListener(this); } private BufferedImage[] prepareImages() { int frameCount = 5; // количество кадров this.isFolderMode = false; BufferedImage[] imgArray = new BufferedImage[frameCount]; // создание болванок for (int i = 0; i < frameCount; i++) { imgArray[i] = createDummyCar(i, frameCount); } return imgArray; } // рисование на BufferedImage private BufferedImage createDummyCar(int frame, int total) { BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); // корпус int offset = frame * 10; g.setColor(Color.RED); g.fillRect(20 + offset, 40, 100, 40); // крыша g.setColor(Color.RED); g.fillRect(40 + offset, 20, 50, 25); // колеса g.setColor(Color.BLACK); g.fillOval(30 + offset, 70, 20, 20); g.fillOval(90 + offset, 70, 20, 20); g.dispose(); return img; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // очистка фона g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); // отрисовка в центре экрана if (frames.length > 0) { int x = (getWidth() - frames[0].getWidth()) / 2; int y = (getHeight() - frames[0].getHeight()) / 2; g.drawImage(currentFrames[currentFrameIndex], x, y, this); } if (isFolderMode) { g.setColor(Color.BLUE); g.drawString("Кадров в папке: " + currentFrames.length, 10, 40); } // подсказка g.setColor(Color.GRAY); g.drawString(isMouseInside ? "Статус: Анимация работает" : "Статус: Пауза (мышь снаружи)", 10, 20); } // Реализация методов MouseListener @Override public void mouseEntered(MouseEvent e) { isMouseInside = true; // запуск } @Override public void mouseExited(MouseEvent e) { isMouseInside = false; // остановка } @Override public void mouseClicked(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseMoved(MouseEvent e) {} @Override public void mouseDragged(MouseEvent e) {} }