Files
java-kursach/CarAnimation.java
2026-04-24 00:53:11 +09:00

269 lines
10 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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) {}
}