This commit is contained in:
2026-04-24 00:53:11 +09:00
parent 6be7659130
commit d64329b910
8 changed files with 273 additions and 0 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"java.debug.settings.onBuildFailureProceed": true
}

269
CarAnimation.java Normal file
View File

@@ -0,0 +1,269 @@
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) {}
}

BIN
example/frame_001.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
example/frame_002.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
example/frame_003.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
example/frame_004.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
example/frame_005.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

1
manifest.txt Normal file
View File

@@ -0,0 +1 @@
Main-Class: CarAnimation