java - 运行线程时,旋转变换无法在重新绘制中正常工作

标签 java multithreading swing awt graphics2d

我一直在努力使这个程序运行,尽管我似乎找不到问题所在。该程序由以下2个类组成,不多不少。基本上应该在绘图区中每次单击时绘制一个点,并在第 3 次单击时连接所有点。我仍然需要努力让它更漂亮、更准确,但这部分是有效的。不起作用的是应该遵循的:在第四次单击时,线程应该启动(并且它启动了),并且三角形本身应该在给定任意刷新率的情况下旋转,正好 80 次重绘。在动画完成之前,下一次点击应该不会起作用,只有在动画停止(线程死亡)后点击一次,才会显示一个新点并重新开始。

是否有可能所有的绘画调用都堆叠起来直到我的线程结束?我知道可能会发生所有事件都堆叠在事件队列中并被视为一个事件的情况。使用带有时间参数的重绘没有帮助。我添加了评论以帮助澄清,因为所有变量都是法语单词(它们已被解释)。我很难弄清楚它是否在我的代码中以找到问题,它是与线程相关还是与类型相关。我只是在 Debug模式下无处可去(使用 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();
}

}

最佳答案

第一个问题是您永远不会在动画线程上调用 start()

第二个问题是你不应该永远在 EDT 之外做 gui 的事情。正如@AndrewThompson 在他的评论中提到的,你应该使用 Swing Timer而不是线程。

关于java - 运行线程时,旋转变换无法在重新绘制中正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13964419/

相关文章:

java - jsp中分离javascript和java的最佳方法

java - 避免单实例变量在android中被混淆

java - if 语句的复杂性

java - 限制生成的线程数量

c - 如何找到哪个线程被卡住了

java - 如何检测大写锁定是否在 Swing 中切换?

java - 如何在 Android 上以编程方式使用 View

c# - 由于线程原因,实例化不起作用

java - JFileChooser 和复制文件

java - ImageIO.read(URL) 需要很长时间