Создание многопоточного приложения с элементами вывода графической информации - 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();
        }
        }

Оцени полезность:

9   голосов , оценка 4.111 из 5
Похожие ответы