
Практическое задание №2
Составить программу вывода на экран дисплея треугольника. При нажатии клавиши курсор вправо треугольник вращается по часовой стрелке, клавиши курсор влево − против часовой стрелки.
RotateViewFrame.java:
package trianglerotate.view;
import java.awt.Point;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import trianglerotate.logic.Triangle;
import trianglerotate.logic.TriangleRotator;
public class RotateViewFrame extends javax.swing.JFrame {
/** Creates new form RotateViewFrame */
public RotateViewFrame() {
initComponents();
triangleRotator = new TriangleRotator(jCanvas.getGraphics(),
Triangle.getInstance(new Point(100, 100),
new Point(210, 190),
new Point(310, 100)),
(short ) 5);
rotateExecutor = Executors.newSingleThreadExecutor();
}
private TriangleRotator triangleRotator;
private Executor rotateExecutor;
@SuppressWarnings("unchecked")
private void initComponents() {
jCanvas = new javax.swing.JPanel();
jLeftBtn = new javax.swing.JButton();
jRightBtn = new javax.swing.JButton();
jStopBtn = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setName("jRotateFrame"); // NOI18N
setResizable(false);
jCanvas.setBackground(new java.awt.Color(255, 255, 255));
javax.swing.GroupLayout jCanvasLayout = new javax.swing.GroupLayout(jCanvas);
jCanvas.setLayout(jCanvasLayout);
jCanvasLayout.setHorizontalGroup(
jCanvasLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
jCanvasLayout.setVerticalGroup(
jCanvasLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 246, Short.MAX_VALUE)
);
jLeftBtn.setText("<---");
jLeftBtn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jLeftBtnActionPerformed(evt);
}
});
jRightBtn.setText("--->");
jRightBtn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jRightBtnActionPerformed(evt);
}
});
jStopBtn.setText("Stop");
jStopBtn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jStopBtnActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jCanvas, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(34, 34, 34)
.addComponent(jLeftBtn)
.addGap(77, 77, 77)
.addComponent(jStopBtn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 84, Short.MAX_VALUE)
.addComponent(jRightBtn)
.addGap(44, 44, 44))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jCanvas, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jRightBtn)
.addComponent(jLeftBtn)
.addComponent(jStopBtn))
.addContainerGap(13, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void jRightBtnActionPerformed(java.awt.event.ActionEvent evt) {
this.triangleRotator.stop();
this.triangleRotator.setClockwise(true);
rotateExecutor.execute(triangleRotator);
}
private void jStopBtnActionPerformed(java.awt.event.ActionEvent evt) {
this.triangleRotator.stop();
}
private void jLeftBtnActionPerformed(java.awt.event.ActionEvent evt) {
this.triangleRotator.stop();
this.triangleRotator.setClockwise(false);
rotateExecutor.execute(triangleRotator);
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(RotateViewFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(RotateViewFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(RotateViewFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(RotateViewFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new RotateViewFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel jCanvas;
private javax.swing.JButton jLeftBtn;
private javax.swing.JButton jRightBtn;
private javax.swing.JButton jStopBtn;
// End of variables declaration
}
Trialngle.java:
package trianglerotate.logic;
import java.awt.Point;
public class Triangle {
private Point p0;
private Point p1;
private Point p2;
private Point p3;
public static Triangle getInstance(Point p1, Point p2, Point p3) {
return new Triangle(p1, p2, p3);
}
private Triangle(Point p1, Point p2, Point p3) {
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.p0 = new Point();
this.p0.x = (p1.x + p2.x + p3.x) / 3;
this.p0.y = (p1.y + p2.y + p3.y) / 3;
}
public Point getP0() {
return p0;
}
public Point getP1() {
return p1;
}
public Point getP2() {
return p2;
}
public Point getP3() {
return p3;
}
@Override
public String toString() {
return p1.toString() + " | " +
p2.toString() + " | " +
p3.toString();
}
}
TriangleRotator.java:
package trianglerotate.logic;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TriangleRotator implements Runnable {
private final short angle;
private Graphics canvas;
private final CycledIterator triangles;
private volatile boolean stop = false;
public TriangleRotator(Graphics graphics, Triangle movable, short angle)
{
this.canvas = graphics;
this.angle = angle;
List<Triangle> traces = new LinkedList<Triangle>();
traces = new LinkedList<Triangle>();
traces.add(Triangle.getInstance(movable.getP1(), movable.getP2(), movable.getP3()));
int fullAngle = angle;
Triangle triangle = movable;
while (fullAngle < 360)
{
triangle = move(triangle);
traces.add(triangle);
fullAngle += angle;
}
this.triangles = new CycledIterator(traces);
}
private Triangle move(Triangle tr)
{
assert (tr != null);
Point sP0 = tr.getP0();
Point sP1_ = rotatePoint(tr.getP1(), sP0);
Point sP2_ = rotatePoint(tr.getP2(), sP0);
Point sP3_ = rotatePoint(tr.getP3(), sP0);
return Triangle.getInstance(sP1_, sP2_, sP3_);
}
private Point rotatePoint(Point pX, Point p0)
{
assert (pX != null);
assert (p0 != null);
assert (angle > 0 && angle <= 360);
int rX = (int)Math.round(p0.getX() + (pX.getX() - p0.getX()) * Math.cos(Math.toRadians(angle)) +
(p0.getY() - pX.getY()) * Math.sin(Math.toRadians(angle)));
int rY = (int)Math.round(p0.getY() + (pX.getX() - p0.getX()) * Math.sin(Math.toRadians(angle)) +
(pX.getY() - p0.getY()) * Math.cos(Math.toRadians(angle)));
return new Point(rX, rY);
}
@Override
public void run() {
stop = false;
while (!stop)
{
try {
drawTriangle(triangles.next());
Thread.sleep(40);
} catch (InterruptedException ex) {
Logger.getLogger(TriangleRotator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void stop()
{
this.stop = true;
}
public void setClockwise(boolean clockwise)
{
this.triangles.setClockwise(clockwise);
}
private void drawTriangle(Triangle tr)
{
assert (canvas != null);
assert (tr != null);
canvas.setColor(Color.WHITE);
canvas.fillRect(0, 0, 400, 400);
canvas.setColor(Color.BLACK);
canvas.drawLine(tr.getP1().x, tr.getP1().y, tr.getP2().x, tr.getP2().y);
canvas.drawLine(tr.getP2().x, tr.getP2().y, tr.getP3().x, tr.getP3().y);
canvas.drawLine(tr.getP3().x, tr.getP3().y, tr.getP1().x, tr.getP1().y);
}
private class CycledIterator implements Iterator<Triangle> {
private final List<Triangle> traces;
private ListIterator<Triangle> iterator;
private volatile boolean clockwise;
public CycledIterator(List<Triangle> traces)
{
this.traces = Collections.unmodifiableList(traces);
this.iterator = traces.listIterator();
this.clockwise = true;
}
public void setClockwise(boolean clockwise) {
this.clockwise = clockwise;
}
@Override
public boolean hasNext() {
return true;
}
@Override
public Triangle next() {
if (clockwise)
{
if (!iterator.hasNext())
iterator = traces.listIterator();
return iterator.next();
}
else
{
if (!iterator.hasPrevious())
iterator = traces.listIterator(traces.size());
return iterator.previous();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}