Создание многопоточного приложения с элементами вывода графической информации - Java
Формулировка задачи:
В общем кодил тут програмку
Суть заключается в том, что по экрану летают ромбы
В меню управления есть три пункта
1. Приостановка выборочных фигур
2. Приостановка всех фигур
3. И возобновление движения
суть вопроса заключается в том
никак не могу понять как прописать что при нажатии кнопки приостановка выборочных фигур остонавливаются только те фигуры которые находят в диапазоне (угол скорости фигуры находится между 180 и 270 градусов (3-я четверть))
Прикрепил архив с кодом
программирую в Eclipse
Помогите разобраться)
Решение задачи: «Создание многопоточного приложения с элементами вывода графической информации»
textual
Листинг программы
- MainFrame
- package mainPackage;
- import java.awt.BorderLayout;
- import java.awt.Toolkit;
- import java.awt.event.ActionEvent;
- import javax.swing.AbstractAction;
- import javax.swing.Action;
- import javax.swing.JFrame;
- import javax.swing.JMenu;
- import javax.swing.JMenuBar;
- import javax.swing.JMenuItem;
- @SuppressWarnings("serial")
- public class MainFrame extends JFrame {
- // Константы, задающие размер окна приложения, если оно
- // не распахнуто на весь экран
- private static final int WIDTH = 700;
- private static final int HEIGHT = 500;
- private JMenuItem pauseMenuItem;
- private JMenuItem resumeMenuItem;
- // Поле, по которому движутся фигуры
- private Field field = new Field();
- // Конструктор главного окна приложения
- public MainFrame() {
- super("Программирование и синхронизация потоков");
- setSize(WIDTH, HEIGHT);
- Toolkit kit = Toolkit.getDefaultToolkit();
- // Отцентрировать окно приложения на экране
- setLocation((kit.getScreenSize().width - WIDTH)/2,
- (kit.getScreenSize().height - HEIGHT)/2);
- // Установить начальное состояние окна развернутым на весь экран
- setExtendedState(MAXIMIZED_BOTH);
- // Создать меню
- JMenuBar menuBar = new JMenuBar();
- setJMenuBar(menuBar);
- JMenu figuresMenu = new JMenu("Фигуры");
- Action addFigureAction = new AbstractAction("Добавить фигуру") {
- public void actionPerformed(ActionEvent event) {
- field.addFigure();
- if (!pauseMenuItem.isEnabled() &&
- !resumeMenuItem.isEnabled()) {
- // Ни один из пунктов меню не является
- // доступным - сделать доступным "Паузу"
- pauseMenuItem.setEnabled(true);
- }
- }
- };
- menuBar.add(figuresMenu);
- figuresMenu.add(addFigureAction);
- JMenu controlMenu = new JMenu("Управление");
- menuBar.add(controlMenu);
- pauseMenuItem = controlMenu.add(pauseAction);
- pauseMenuItem.setEnabled(false);
- Action resumeAction2 = new AbstractAction("Остановка рандомных фигурок"){
- public void actionPerformed(ActionEvent event) {
- field.paused2();
- pauseMenuItem.setEnabled(true);
- resumeMenuItem.setEnabled(true);
- pauseSelect.setEnabled(false);
- }
- };
- Action pauseAction = new AbstractAction("Приостановить движение"){
- public void actionPerformed(ActionEvent event) {
- field.pause();
- pauseMenuItem.setEnabled(false);
- resumeMenuItem.setEnabled(true);
- }
- };
- pauseMenuItem = controlMenu.add(pauseAction);
- pauseMenuItem.setEnabled(false);
- Action resumeAction = new AbstractAction("Возобновить движение") {
- public void actionPerformed(ActionEvent event) {
- field.resume();
- pauseMenuItem.setEnabled(true);
- resumeMenuItem.setEnabled(false);
- }
- };
- resumeMenuItem = controlMenu.add(resumeAction);
- resumeMenuItem.setEnabled(false);
- // Добавить в центр граничной компоновки поле Field
- getContentPane().add(field, BorderLayout.CENTER);
- }
- // Главный метод приложения
- public static void main(String[] args) {
- // Создать и сделать видимым главное окно приложения
- MainFrame frame = new MainFrame();
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setVisible(true);
- }
- }
- MovingFigure
- package mainPackage;
- import java.awt.BasicStroke;
- import java.awt.Color;
- import java.awt.Graphics2D;
- import java.awt.Stroke;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Area;
- import java.awt.geom.Rectangle2D;
- public class MovingFigure implements Runnable {
- // Максимальный размер половины стороны квадрата, описывающего фигуру
- private static final int maxFramingSquareHalfSize = 60;
- // Минимальный размер половины стороны квадрата, описывающего фигуру
- private static final int minFramingSquareHalfSize = 10;
- // Минимальное время, на которое может засыпать поток после каждого смещения
- private static final int minSleepTime = 1;
- private Field field;
- // Характеристики фигуры
- // Половина стороны квадрата, описывающего фигуру
- private int framingSquareHalfSize;
- // Цвет для заливки внутреннего простанства фигуры
- private Color color;
- // Штриховка для рисования границы фигуры
- float [] dash = {8,2,8,2,2,2,2,2,4,2,4,2};
- private Stroke stroke = new BasicStroke(2.0f, BasicStroke.CAP_BUTT,
- BasicStroke.JOIN_ROUND, 10.0f, dash, 0.0f);
- // Текущие координаты центра фигуры
- private double x;
- private double y;
- // Время сна потока между двумя пересчетами координат
- private int sleepTime;
- // Вертикальная и горизонтальная компоненты смещения
- private double shiftX;
- private double shiftY;
- //Конструктор класса MovingFigure
- public MovingFigure(Field field) {
- //Необходимо иметь ссылку на поле, по которому передвигается фигура,
- //чтобы отслеживать выход за его пределы через getWidth(), getHeight()
- this.field = field;
- //Случайно выбираем размер половины стороны квадрата, описывающего фигуру
- framingSquareHalfSize = minFramingSquareHalfSize + new Double(
- Math.random()*(maxFramingSquareHalfSize - minFramingSquareHalfSize)).intValue();
- //Абсолютное значение времени сна потока зависит от размера фигуры,
- //чем он больше, тем больше
- sleepTime = 16 -
- new Double(Math.round(210 / framingSquareHalfSize)).intValue();
- if (sleepTime < minSleepTime)
- sleepTime = minSleepTime;
- //Начальное направление движения случайно, угол в пределах от 0 до 2PI
- double angle = Math.random()*2*Math.PI;
- //Вычисляются горизонтальная и вертикальная компоненты смещения
- shiftX = 3*Math.cos(angle);
- shiftY = 3*Math.sin(angle);
- //Цвет фигуры выбирается случайно
- color = new Color((float)Math.random(), (float)Math.random(),
- (float)Math.random());
- //Начальное положение фигуры случайно
- x = framingSquareHalfSize + Math.random()*
- (field.getSize().getWidth()-2*framingSquareHalfSize);
- y = framingSquareHalfSize + Math.random()*
- (field.getSize().getHeight()-2*framingSquareHalfSize);
- //Создаем новый экземпляр потока, передавая аргументом
- //ссылку на объект класса, реализующего Runnable (т.е. на себя)
- Thread thisThread = new Thread(this);
- //Запускаем поток
- thisThread.start();
- }
- //Метод run() исполняется внутри потока. Когда он завершает работу,
- //то завершается и поток
- public void run() {
- try {
- //Крутим бесконечный цикл, т.е. пока нас не прервут,
- //мы не намерены завершаться
- while(true) {
- //Синхронизация потоков выполняется на объекте field.
- //Если движение разрешено - управление будет возвращено в метод.
- //В противном случае - активный поток заснет
- field.canMove(this);
- if (x + shiftX <= framingSquareHalfSize) {
- //Достигли левой стенки, отскакиваем право
- shiftX = -shiftX;
- x = framingSquareHalfSize;
- } else if (x + shiftX >= field.getWidth()-
- framingSquareHalfSize) {
- // Достигли правой стенки, отскок влево
- shiftX = -shiftX;
- x=new Double(field.getWidth()-
- framingSquareHalfSize).intValue();
- } else if (y + shiftY <= framingSquareHalfSize) {
- // Достигли верхней стенки
- shiftY = -shiftY;
- y = framingSquareHalfSize;
- } else if (y + shiftY >= field.getHeight()-
- framingSquareHalfSize) {
- // Достигли нижней стенки
- shiftY = -shiftY;
- y=new Double(field.getHeight()-
- framingSquareHalfSize).intValue();
- } else {
- // Просто смещаемся
- x += shiftX;
- y += shiftY;
- }
- // Засыпаем на sleepTime миллисекунд
- Thread.sleep(sleepTime);
- }
- } catch (InterruptedException ex) {
- // Если нас прервали, то ничего не делаем
- // и просто выходим (завершаемся)
- }
- }
- // Метод прорисовки самой себя
- public void paint (Graphics2D canvas) {
- Rectangle2D.Double rect1 = new Rectangle2D.Double(x-framingSquareHalfSize, y-framingSquareHalfSize,
- 2*framingSquareHalfSize, 2*framingSquareHalfSize);
- Rectangle2D.Double rect2 = new Rectangle2D.Double(x-framingSquareHalfSize, y-framingSquareHalfSize,
- 2*framingSquareHalfSize, 2*framingSquareHalfSize);
- Area figure = new Area(rect1);
- AffineTransform at = AffineTransform.getRotateInstance(
- Math.PI/3, rect1.getCenterX(), rect2.getCenterY());
- figure.transform(at);
- //figure.add(new Area(rect2));
- canvas.setPaint(color);
- canvas.fill(figure);
- canvas.setStroke(stroke);
- canvas.setPaint(Color.black);
- canvas.draw(figure);
- //canvas.draw(line);
- }
- }
- Field
- package mainPackage;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.ArrayList;
- import javax.swing.JPanel;
- import javax.swing.Timer;
- @SuppressWarnings("serial")
- public class Field extends JPanel {
- // Флаг приостановки движения
- private boolean paused;
- // Динамический список движущихся фигур
- private ArrayList<MovingFigure> figures = new ArrayList<MovingFigure>(10);
- // Класс таймер отвечает за регулярную генерацию событий ActionEvent
- // При создании его экземпляра используется анонимный класс,
- // реализующий интерфейс ActionListener
- private Timer repaintTimer = new Timer(10, new ActionListener() {
- public void actionPerformed(ActionEvent ev) {
- // Задача обработчика события ActionEvent - перерисовка окна
- repaint();
- }
- });
- // Конструктор класса Field
- public Field() {
- // Установить цвет заднего фона белым
- setBackground(Color.WHITE);
- // Запустить таймер
- repaintTimer.start();
- }
- // Унаследованный от JPanel метод перерисовки компонента
- public void paintComponent(Graphics g) {
- // Вызвать версию метода, унаследованную от предка
- super.paintComponent(g);
- Graphics2D canvas = (Graphics2D) g;
- // Последовательно запросить прорисовку от всех фигур из списка
- for (MovingFigure figure: figures)
- figure.paint(canvas);
- }
- // Метод добавления новой фигуры в список
- public void addFigure() {
- // Заключается в добавлении в список нового экземпляра MovingFigure
- // Всю инициализацию положения, скорости, размера, цвета
- // MovingFigure выполняет в своем конструкторе
- figures.add(new MovingFigure(this));
- }
- // Cинхронизированный метод приостановки движения фигур
- // (только один поток может одновременно быть внутри)
- public synchronized void pause() {
- // Включить режим паузы
- paused = true;
- }
- // Cинхронизированный метод возобновления движения фигур
- // (только один поток может одновременно быть внутри)
- public synchronized void resume() {
- // Выключить режим паузы
- paused = false;
- // Будим все ожидающие продолжения потоки
- notifyAll();
- }
- // Синхронизированный метод проверки, может ли фигура двигаться
- // (не включен ли режим паузы?)
- public synchronized void canMove(MovingFigure figure) throws InterruptedException {
- // Если режим паузы включен, то поток, зашедший
- // внутрь данного метода, засыпает
- if (paused)
- wait();
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д