代码用于绘制一个矩形,该矩形围绕画布中心移动一次。我目前的代码是
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.Timer;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Q3_Circular extends JComponent {
protected int degree = 0;
protected double xStart;
protected double yStart;
protected Timer timer;
public Q3_Circular() {
timer = new Timer(1000, new TimerCallback()); //creates new times that refreshes every 100 ms, and called the TimerCallback class
timer.start();
}
protected class TimerCallback implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (degree < (2 * Math.PI)){
xStart = getWidth()/2 * Math.cos(degree+1);
yStart = getHeight()/2 * Math.sin(degree+1);
degree+= 1;
repaint();
}
else {
degree += 0;
repaint();
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("AnimatedSquare");
Q3_Circular canvas = new Q3_Circular();
frame.add(canvas);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void paintComponent(Graphics g){
xStart = (double)(getWidth())/2.0 * Math.cos(degree);
yStart = (double)(getHeight())/2.0 * Math.sin(degree);
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Rectangle2D.Double(xStart,yStart, 25,25));
repaint();
}
}
此代码似乎在点(0,0)周围非常快速地绘制矩形。我不确定代码在哪里出错。
答案 0 :(得分:1)
您的代码令人困惑。这是我创建的GUI。
创建Swing GUI时,请使用模型/视图/控制器模式。创建GUI模型和GUI视图,以及一个或多个控制器来修改模型并重新绘制视图。
以下是我对您的代码所做的更改。
我创建了一个DrawingRectangle类来保存有关绘图矩形的信息。这个类是一个带有getter和setter的普通旧Java对象。这个类是GUI模型。
除了调用SwingUtilities invokeLater方法之外,我将所有内容都移出main方法。 invokeLater方法在Event Dispatch thread上创建和使用Swing组件。 Oracle和我坚持认为所有Swing应用程序都是从Event Dispatch线程开始的。
我在Q3_Circular类的构造函数中创建绘图矩形。通常,您创建GUI模型,然后创建GUI视图。
我将run方法中的JFrame代码重新排列为正确的顺序。我删除了setSize方法并将其替换为pack方法。我们不关心JFrame有多大。我们关心绘图板的大小。
我从JPanel创建了一个绘图面板。在这里,我们设置绘图面板的首选大小。我们扩展了一个JPanel,因此我们可以覆盖paintComponent方法。
paintComponent方法除了绘制绘图矩形外什么都不做。除了绘画之外,没有任何计算或任何东西在paintComponent方法中完成。我添加了对super paintComponent方法的调用,以在绘制绘图矩形之前维护Swing绘制链并清除绘图面板。我使用x和y坐标作为矩形的中心而不是左上角来绘制矩形。这是我在绘图代码中进行的一次转换。
我从Runnable创建了一个绘图动画。如果需要,您可以使用Swing Timer。我发现创建自己的动画代码更容易。这是GUI控制器。这是我们进行计算,更新模型和重绘绘图面板的地方。在重绘方法中,我使用SwingUtilities invokeLater方法在Event Dispatch线程上进行绘制。我这样做是因为动画线程是一个单独的线程。
这是代码。我将所有类放在一起,这样我就可以更轻松地粘贴代码了。您应该将类分成不同的文件。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Q3_Circular implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Q3_Circular());
}
private static final int DRAWING_WIDTH = 300;
private static final int DRAWING_HEIGHT = DRAWING_WIDTH;
private DrawingRectangle drawingRectangle;
public Q3_Circular() {
int center = DRAWING_WIDTH / 2;
Rectangle2D rectangle = new Rectangle2D.Double(center, center, 32D, 32D);
drawingRectangle = new DrawingRectangle(Color.RED, rectangle);
}
@Override
public void run() {
JFrame frame = new JFrame("Animated Square");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawingPanel drawingPanel = new DrawingPanel(DRAWING_WIDTH,
DRAWING_HEIGHT, drawingRectangle);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Thread(new DrawingAnimation(drawingPanel, drawingRectangle))
.start();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 8226587438110549806L;
private DrawingRectangle drawingRectangle;
public DrawingPanel(int width, int height,
DrawingRectangle drawingRectangle) {
this.setPreferredSize(new Dimension(width, height));
this.drawingRectangle = drawingRectangle;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(drawingRectangle.getColor());
Rectangle2D rectangle = drawingRectangle.getRectangle();
int x = (int) Math.round(rectangle.getX());
int y = (int) Math.round(rectangle.getY());
int width = (int) Math.round(rectangle.getWidth());
int height = (int) Math.round(rectangle.getHeight());
g.fillRect(x - width / 2, y - height / 2, width, height);
}
}
public class DrawingAnimation implements Runnable {
private DrawingPanel drawingPanel;
private DrawingRectangle drawingRectangle;
public DrawingAnimation(DrawingPanel drawingPanel,
DrawingRectangle drawingRectangle) {
this.drawingPanel = drawingPanel;
this.drawingRectangle = drawingRectangle;
}
@Override
public void run() {
int xCenter = drawingPanel.getWidth() / 2;
int yCenter = drawingPanel.getHeight() / 2;
double radius = drawingPanel.getWidth() / 3;
for (int degree = 0; degree < 360; degree++) {
double radians = Math.toRadians((double) degree);
double x = radius * Math.cos(radians) + xCenter;
double y = radius * Math.sin(radians) + yCenter;
drawingRectangle.setRectangleOrigin(x, y);
repaint();
sleep(100L);
}
}
private void sleep(long interval) {
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
}
}
private void repaint() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.repaint();
}
});
}
}
public class DrawingRectangle {
private final Color color;
private Rectangle2D rectangle;
public DrawingRectangle(Color color, Rectangle2D rectangle) {
this.color = color;
this.rectangle = rectangle;
}
public void setRectangleOrigin(double x, double y) {
rectangle
.setRect(x, y, rectangle.getWidth(), rectangle.getHeight());
}
public Color getColor() {
return color;
}
public Rectangle2D getRectangle() {
return rectangle;
}
}
}