我一直在努力使这个程序工作,即使我似乎无法找到问题所在。这个程序由以下2个类组成,不多也不少。基本上应该在绘图区域中的每次点击上绘制一个点,并在第3次点击时连接所有点。我仍然需要努力使它更漂亮,更准确,但这一部分有效。什么不起作用应该遵循:在第四次点击线程应该开始(并开始),三角形本身应该旋转给定一个任意刷新率,恰好80重绘。在动画完成之前,下一次单击不应该起作用,只有在动画停止后(线程消失)有一次点击时,才会显示一个新点并重新开始。
是否有可能所有的绘制调用都被堆叠到我的线程结束之前?我知道可能会发生所有事件都堆叠在事件队列中并视为一个事件。使用带有时间参数的重绘无济于事。我添加了评论以帮助澄清,因为所有变量都是法语单词(它们已被解释)。我很难弄清楚是否在我的代码中找到问题,如果它与线程相关甚至类型相关。我只是在调试模式下无处可去(使用 Eclipse )。我完全忽略了一些明显的东西吗?
虽然我的方法可能不是最有效的方法,但旋转是我的主要问题。我可以处理编写代码中未写入的剩余部分。 谢谢你的帮助!这是两个类:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Application extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JButton btnTerminer;
private Triangle triangle;
private int totalClics = 0;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Application frame = new Application();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Application() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 453, 692);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
btnTerminer = new JButton("Terminer");
btnTerminer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
btnTerminer.setBounds(138, 622, 132, 23);
contentPane.add(btnTerminer);
triangle = new Triangle();
//Adds points for every mouse click
triangle.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(totalClics < 3){
triangle.ajouterPoint(e.getX(), e.getY());
totalClics++;
} else {
triangle.getAnim().start();
totalClics = 0;
}
}
});
triangle.setBounds(10, 11, 400, 600);
contentPane.add(triangle);
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JPanel;
public class Triangle extends JPanel implements Runnable,Serializable{
private static final long serialVersionUID = 1L;
private ArrayList<Point> points = null;
//Animation thread
private Thread anim;
private Color couleurPrin;
private Color couleurBoite;
//A point's diameter
private int diametre = 8;
//The rectangle's width
private int largeur;
//The rectangle's height
private int hauteur;
//The rectangle's top-left corner
private int minX;
private int minY;
//Angle incrementation multiplier
private int nbAng = 0 ;
//Thread stopping variable
private boolean continuer = true;
public Triangle() {
setPreferredSize(new Dimension(400, 600));
setBackground(Color.BLACK);
couleurPrin = Color.GREEN;
couleurBoite = Color.RED;
setAnim(new Thread(this));
points = new ArrayList<Point>();
}
/**
* Repaints this component
*/
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int i = 0;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int[] coorX = new int[points.size()+1];
int[] coorY = new int[points.size()+1];
Iterator<Point> iter = points.iterator();
while(iter.hasNext()){
Point p = iter.next();
coorX[i] = p.getX();
coorY[i]= p.getY();
i++;
}
coorX[points.size()] = coorX[0];
coorY[points.size()] = coorY[0];
if(points.size() != 0){
g2d.setColor(Color.white);
g2d.fillOval(minX+largeur/2, minY+hauteur/2, 6, 6);
g2d.setColor(couleurPrin);
for(i =0; i<points.size(); i++){
g2d.drawLine(coorX[i], coorY[i], coorX[i+1], coorY[i+1]);
}
for(i = 0; i<points.size(); i++){
g2d.fillOval(coorX[i]-diametre/2, coorY[i]-diametre/2, diametre, diametre);
}
g2d.setColor(couleurBoite);
g2d.drawRect(minX, minY, largeur, hauteur);
g2d.rotate(15.0*nbAng, (largeur+getWidth())/2, (hauteur+getWidth())/2);
}
}
/**
* Adds a point. Stops at 3.
* @param x
* @param y
*
*
*/
public void ajouterPoint(int x, int y){
Point p = new Point(x,y);
System.out.println(p.toString());
if(points.size()>=0 && points.size()<3){
points.add(p);
minX = p.getX()-3;
minY = p.getY()-3;
}
if(points.size() == 3){
rectanguler(points);
}
repaint();
}
public Color getCouleurPrin() {
return couleurPrin;
}
public void setCouleurPrin(Color c) {
this.couleurPrin = c;
repaint();
}
public int getDiametre() {
return diametre;
}
public void setDiametre(int d) {
this.diametre = d;
repaint();
}
/**
* Sets rectangle's values to the largest bounds possible
* @param points
*/
private void rectanguler(ArrayList<Point> points){
Iterator<Point> iter = points.iterator();
Point p1, p2, p3;
p1 = iter.next();
p2 = iter.next();
p3 = iter.next();
int dLarg;
int dLong;
if(p2 != null && p3 != null){
minX = Math.min(p1.getX(), p2.getX());
minY = Math.min(p1.getY(), p2.getY());
largeur = Math.abs(p1.getX()-p2.getX());
hauteur = Math.abs(p1.getY()-p2.getY());
if(p3 != null){
minX = Math.min(minX, p3.getX());
minY = Math.min(minY, p3.getY());
dLarg = Math.max(Math.abs(p3.getX()-p2.getX()), Math.abs(p3.getX()-p1.getX()));
dLong = Math.max(Math.abs(p3.getY()-p2.getY()), Math.abs(p3.getY()-p1.getY()));
largeur = Math.max(dLarg, largeur);
hauteur = Math.max(dLong, hauteur);
}
}
}
/**
* Custom point class
* Stores an x and y value
*
*/
private class Point{
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
private int x,y;
public Point(){
setX(0);
setY(0);
}
public Point(int x,int y){
setX(x);
setY(y);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
/**
* Starts the rotation
*
*/
@Override
public void run() {
int i =1;
while(continuer){
nbAng = i;
repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
System.out.println("Erreur dans le thread");
e.printStackTrace();
}
i++;
if(i== 80){
continuer = false;
}
}
anim = new Thread(this);
}
public Thread getAnim() {
return anim;
}
public void setAnim(Thread anim) {
this.anim = anim;
repaint();
}
}
答案 0 :(得分:3)
第一个问题是你永远不会在动画线程上调用start()
。
第二个问题是你应该从不在EDT之外做gui事情。正如@AndrewThompson在评论中提到的那样,你应该使用摆动Timer而不是线程。
答案 1 :(得分:3)
Thread
对于您想要达到的目标而言过于苛刻。 javax.swing.Timer
更简单易用,与Thread
不同,它也可以重复使用。
Graphics2D#rotate
将翻译应用于所有后续渲染,这意味着您需要在绘制任何内容之前应用它。
您的鼠标点击逻辑也有点偏离,它不会在允许点击继续之前检查线程的状态。
我稍微修改了你的代码作为一个例子(对不起,我将鼠标单击处理移动到Triangle
类,但你应该能够删除它;)
public class TestRotation01 {
public static void main(String[] args) {
new TestRotation01();
}
public TestRotation01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Triangle());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Triangle extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Point> points = null;
//Animation thread
// private Thread anim;
private Color couleurPrin;
private Color couleurBoite;
//A point's diameter
private int diametre = 8;
//The rectangle's width
private int largeur;
//The rectangle's height
private int hauteur;
//The rectangle's top-left corner
private int minX;
private int minY;
//Angle incrementation multiplier
private int nbAng = 0;
//Thread stopping variable
private boolean continuer = true;
private int totalClics = 0;
private Timer timer;
private int cycle;
public Triangle() {
setPreferredSize(new Dimension(400, 600));
setBackground(Color.BLACK);
couleurPrin = Color.GREEN;
couleurBoite = Color.RED;
points = new ArrayList<Point>();
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (!timer.isRunning()) {
if (totalClics < 3) {
nbAng = 0;
ajouterPoint(e.getX(), e.getY());
totalClics++;
} else {
cycle = 0;
totalClics = 0;
timer.restart();
}
}
}
});
timer = new Timer(200, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
nbAng += 5;
repaint();
cycle++;
if (cycle == 80) {
timer.stop();
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
}
/**
* Repaints this component
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (timer.isRunning()) {
g2d.rotate(15.0 * nbAng, (largeur + getWidth()) / 2, (hauteur + getWidth()) / 2);
}
int i = 0;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int[] coorX = new int[points.size() + 1];
int[] coorY = new int[points.size() + 1];
Iterator<Point> iter = points.iterator();
while (iter.hasNext()) {
Point p = iter.next();
coorX[i] = p.getX();
coorY[i] = p.getY();
i++;
}
coorX[points.size()] = coorX[0];
coorY[points.size()] = coorY[0];
if (points.size() != 0) {
g2d.setColor(Color.white);
g2d.fillOval(minX + largeur / 2, minY + hauteur / 2, 6, 6);
g2d.setColor(couleurPrin);
for (i = 0; i < points.size(); i++) {
g2d.drawLine(coorX[i], coorY[i], coorX[i + 1], coorY[i + 1]);
}
for (i = 0; i < points.size(); i++) {
g2d.fillOval(coorX[i] - diametre / 2, coorY[i] - diametre / 2, diametre, diametre);
}
g2d.setColor(couleurBoite);
g2d.drawRect(minX, minY, largeur, hauteur);
}
g2d.dispose();
}
/**
* Adds a point. Stops at 3.
*
* @param x
* @param y
*
*
*/
public void ajouterPoint(int x, int y) {
Point p = new Point(x, y);
System.out.println(p.toString());
if (points.size() >= 0 && points.size() < 3) {
points.add(p);
minX = p.getX() - 3;
minY = p.getY() - 3;
}
if (points.size() == 3) {
rectanguler(points);
}
repaint();
}
public Color getCouleurPrin() {
return couleurPrin;
}
public void setCouleurPrin(Color c) {
this.couleurPrin = c;
repaint();
}
public int getDiametre() {
return diametre;
}
public void setDiametre(int d) {
this.diametre = d;
repaint();
}
/**
* Sets rectangle's values to the largest bounds possible
*
* @param points
*/
private void rectanguler(ArrayList<Point> points) {
Iterator<Point> iter = points.iterator();
Point p1, p2, p3;
p1 = iter.next();
p2 = iter.next();
p3 = iter.next();
int dLarg;
int dLong;
if (p2 != null && p3 != null) {
minX = Math.min(p1.getX(), p2.getX());
minY = Math.min(p1.getY(), p2.getY());
largeur = Math.abs(p1.getX() - p2.getX());
hauteur = Math.abs(p1.getY() - p2.getY());
if (p3 != null) {
minX = Math.min(minX, p3.getX());
minY = Math.min(minY, p3.getY());
dLarg = Math.max(Math.abs(p3.getX() - p2.getX()), Math.abs(p3.getX() - p1.getX()));
dLong = Math.max(Math.abs(p3.getY() - p2.getY()), Math.abs(p3.getY() - p1.getY()));
largeur = Math.max(dLarg, largeur);
hauteur = Math.max(dLong, hauteur);
}
}
}
/**
* Custom point class Stores an x and y value
*
*/
private class Point {
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
private int x, y;
public Point() {
setX(0);
setY(0);
}
public Point(int x, int y) {
setX(x);
setY(y);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
}
}