我一直在使用Path2D.Double約一天左右, 我詢問了有關設置控制點以允許路徑通過指定點的幫助。我將一些代碼作爲一個快速測試平臺混合在一起,隨機生成點,然後根據上述文章中提到的信息將路徑曲線轉換爲這些點。Path2D繪製錯誤?
這裏是可運行的代碼,很抱歉它是鐵板一塊,我想這是過帳,所以你可以跟着:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class Curver {
public static ArrayList<Point2D> points = new ArrayList<Point2D>();
/**
* @param args
*/
public static void main(String[] args) {
final JFrame window = new JFrame();
window.setPreferredSize(new Dimension(500,500));
window.setLocationRelativeTo(null);
window.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
new Thread(new Runnable(){
@Override
public void run() {
Random random = new Random();
while(true){
points.add(new Point2D.Double(random.nextInt(window.getWidth()-1)+1,random.nextInt(window.getHeight()-1)+1));
System.out.println(points.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
});
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
int div = 7;
int d = 4;
Path2D.Double path = new Path2D.Double();
Point2D currentPoint;
double startX, startY;
double interiorX_In, interiorY_In;
double interiorX_Out, interiorY_Out;
double endX, endY;
Graphics2D g;
while(true){
g = (Graphics2D) window.getGraphics();
g.setColor(Color.blue);
for(int i = 0; i < points.size(); i++){
currentPoint = points.get(i);
g.fillRect((int)currentPoint.getX(), (int)currentPoint.getY(), d, d);
if (i == 0){
// Don't attempt any line drawing as we don't have enough points.
path.moveTo(currentPoint.getX(), currentPoint.getY());
} else if (i == 1 && points.size() > 2){
// draw first curve with knowledge of third point (third point is not end point)
startX = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-1).getX())/div; // from start
startY = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-1).getY())/div;
interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX())/div; // to interior
interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY())/div;
path.curveTo(startX, startY, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());
} else if (i == 1){ // Only 2 points in list so use a straight line until more points are available.
g.drawLine((int) points.get(i-1).getX(), (int) points.get(i-1).getY(), (int)currentPoint.getX(), (int)currentPoint.getY());
} else if (i >= 1 && i < points.size()-1){ // interior to interior edge.
interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX())/div; // from interior
interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY())/div;
interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX())/div; // to interior
interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY())/div;
path.curveTo(interiorX_Out, interiorY_Out, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());
} else { // from interior point to end point.
interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX())/div; // from interior
interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY())/div;
endX = currentPoint.getX() - (currentPoint.getX() - points.get(i-1).getX())/div; // to end
endY = currentPoint.getY() - (currentPoint.getY() - points.get(i-1).getY())/div;
path.curveTo(interiorX_Out, interiorY_Out, endX, endY, currentPoint.getX(), currentPoint.getY());
}
} // end for
g.clearRect(0, 0, window.getWidth(), window.getHeight());
g.draw(path);
path.reset();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 只需點擊JFrame中開始繪製隨機點 - 控制檯會報告繪製的點數。
我遇到的問題是,一旦我得到向上或60-65隨機點的路徑閃爍,似乎在屏幕上縮小,一般表現出奇怪的行爲? 正如我所說的代碼可能不完美,所以任何人都可以給我一些關於如何使它減少錯誤的指針。
我假設奇怪的行爲來自於構建JFrame重繪的更長和更長的路徑?或許我可以將路徑描繪爲一條連續的路線,因爲我認爲路徑被解釋爲一系列的路段?或者可能使路徑累積,而不是重構整個運行循環的每個迭代?
期待提出的任何建議 - 但請儘量解釋,因爲我是比較新的繪畫和路徑等提前
感謝。
感謝@camickr的發帖。 這裏是重新編寫代碼,完美的作品,3,500+隨機點,而不是一個單一的故障:
> import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Curver extends JFrame implements ActionListener, MouseListener{
public Timer animationTicker = new Timer(50, this);
public ArrayList<Point2D> points = new ArrayList<Point2D>();
private Canvas canvas;
public Curver(){
this.setPreferredSize(new Dimension(500,500));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
canvas = new Canvas(points);
this.add(canvas, BorderLayout.CENTER);
this.addMouseListener(this);
this.pack();
this.setVisible(true);
}
class Canvas extends JPanel{
int div = 7;
int d = 4;
Path2D.Double path = new Path2D.Double();
Point2D currentPoint;
double startX, startY;
double interiorX_In, interiorY_In;
double interiorX_Out, interiorY_Out;
double endX, endY;
Graphics2D g2;
ArrayList<Point2D> points;
public Canvas(ArrayList<Point2D> points){
this.setMinimumSize(new Dimension(100,100));
this.points = points;
}
@Override
public void paintComponent(Graphics g) {
g2 = (Graphics2D) g;
g.setColor(Color.blue);
synchronized(points){
for(int i = 0; i < points.size(); i++){
currentPoint = points.get(i);
g2.fillRect((int)currentPoint.getX(), (int)currentPoint.getY(), d, d);
if (i == 0){
// Don't attempt any line drawing as we don't have enough points.
path.moveTo(currentPoint.getX(), currentPoint.getY());
} else if (i == 1 && points.size() > 2){
// draw first curve with knowledge of third point (third point is not end point)
startX = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-1).getX())/div; // from start
startY = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-1).getY())/div;
interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX())/div; // to interior
interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY())/div;
path.curveTo(startX, startY, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());
} else if (i == 1){ // Only 2 points in list so use a straight line until more points are available.
g2.drawLine((int) points.get(i-1).getX(), (int) points.get(i-1).getY(), (int)currentPoint.getX(), (int)currentPoint.getY());
} else if (i >= 1 && i < points.size()-1){ // interior to interior edge.
interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX())/div; // from interior
interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY())/div;
interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX())/div; // to interior
interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY())/div;
path.curveTo(interiorX_Out, interiorY_Out, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());
} else { // from interior point to end point.
interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX())/div; // from interior
interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY())/div;
endX = currentPoint.getX() - (currentPoint.getX() - points.get(i-1).getX())/div; // to end
endY = currentPoint.getY() - (currentPoint.getY() - points.get(i-1).getY())/div;
path.curveTo(interiorX_Out, interiorY_Out, endX, endY, currentPoint.getX(), currentPoint.getY());
}
} // end for
g.clearRect(0, 0, this.getWidth(), this.getHeight());
g2.draw(path);
path.reset();
}
}
} // end of inner class
@Override
public void actionPerformed(ActionEvent e) {
this.canvas.repaint();
}
@Override
public void mouseClicked(MouseEvent e) {
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("Thread running");
Random random = new Random();
while(true){
synchronized(points){
points.add(new Point2D.Double(random.nextInt(getWidth()-1)+1,random.nextInt(getHeight()-1)+1));
System.out.println(points.size());
}
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
public static void main(String[] args) {
Curver curver = new Curver();
curver.animationTicker.start();
}
}
它可能不是主要問題,但它可能無助於從兩個線程訪問點列表而沒有任何同步。嘗試在繪製和添加點之前用'synchronized(points){...}'鎖定列表。 – Boann 2013-04-08 16:31:16
@Boann我明白你在說什麼,但是如果沒有鼠標點擊處理程序中的線程,這個問題是可重複的 - 我只把它放在那裏,因爲每次調試我都感到厭倦了50 - 70次鼠標點擊。你會看到如果你將隨機點邏輯移出線程,問題依然存在。 – 2013-04-08 16:35:37