背景
我是Java新手,今天我开始学习它(使用thenewboston.org)。我已经知道如何制作简单的windows / forms / gui,如何绘制线条等。
我的目标是在Java中创建这样的表:
这是我在.NET C#WPF中创建的标尺,现在我想将其重写为Java。
主要问题:
如何创建具有一定透明度的三角形或其他形状并旋转它?
我尝试使用这样的Graphics对象绘制一些东西:
public void paint(Graphics g){
g.drawLine(0, 0, 100, 100);
}
但我认为这是错误的方向,因为当我在图形上放置东西时 - 它只是停留在那里,我无法移动或旋转它。
我必须清除整个图形并再次绘制它以制作一种“动画”,还是有更简单的方法?
编辑: 我已经知道如何抗锯齿了(Hovercraft Full Of Eels已经帮助了我 - 谢谢)。
EDIT2:
我的代码实际上是这样的:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JPanel {
private Point p1 = new Point(100, 100);
private Point p2 = new Point(740, 450);
public MainWindow() {
this.setPreferredSize(new Dimension(800, 600));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawLines(g);
}
private void drawLines(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.DARK_GRAY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.drawLine(p1.x, p1.y, p2.x, p2.y);
}
private void display() {
JFrame f = new JFrame("Main Window");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
new MainWindow().display();
}
}
答案 0 :(得分:5)
你说:
我尝试使用这样的Graphics对象绘制一些东西:
public void paint(Graphics g){ g.drawLine(0, 0, 100, 100); }
但我认为这是错误的方向,因为当我在图形上放置东西时 - 它只是停留在那里,我无法移动或旋转它。
我必须清除整个图形并再次绘制它以制作一种“动画”,还是有更简单的方法?
建议:
paint(...)
方法。而是覆盖从JComponent或其子项之一(如JPanel)派生的对象的paintComponent(Graphics g)
方法。这将为您提供自动双缓冲的优势,使动画更流畅,并且还可以减少错误绘制组件的子项或边框的可能性。Graphics#drawImage(...)
方法将背景图像绘制为BufferedImage,然后在此基础上绘制运动图像,再次使用Graphics2D对象并再次根据对象的状态更改绘制的图像(值由其领域持有)。例如:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class DailAnimation extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 350;
private static final Point2D CENTER = new Point2D.Double(PREF_W / 2.0,
PREF_W / 2.0);
private static final double RADIUS = PREF_W / 2.0;
private static final Color LARGE_TICK_COLOR = Color.green;
private static final Color CENTER_HUB_COLOR = Color.LIGHT_GRAY;
private static final Stroke LARGE_TICK_STROKE = new BasicStroke(3f);
private static final int LRG_TICK_COUNT = 9;
private static final double TOTAL_LRG_TICKS = 12;
private static final double LRG_TICK_OUTER_RAD = 0.9;
private static final double LRG_TICK_INNER_RAD = 0.8;
private static final int START_TICK = 10;
private static final double CENTER_HUB_RADIUS = 10;
public static final int MAX_SPEED = 100;
private static final double INIT_SPEED = 0;
private static final double DIAL_INNER_RAD = 0.02;
private static final double DIAL_OUTER_RAD = 0.75;
private static final Color DIAL_COLOR = Color.DARK_GRAY;
private BufferedImage backgroundImg;
private double speed;
private double theta;
private double cosTheta;
private double sinTheta;
public DailAnimation() {
setBackground(Color.white);
backgroundImg = createBackgroundImg();
setSpeed(INIT_SPEED);
}
public void setSpeed(double speed) {
if (speed < 0) {
speed = 0;
} else if (speed > MAX_SPEED) {
speed = MAX_SPEED;
}
this.speed = speed;
this.theta = ((speed / MAX_SPEED) * LRG_TICK_COUNT * 2.0 + START_TICK)
* Math.PI / TOTAL_LRG_TICKS;
cosTheta = Math.cos(theta);
sinTheta = Math.sin(theta);
repaint();
}
private BufferedImage createBackgroundImg() {
BufferedImage img = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(LARGE_TICK_COLOR);
g2.setStroke(LARGE_TICK_STROKE);
for (int i = 0; i < LRG_TICK_COUNT; i++) {
double theta = (i * 2.0 + START_TICK) * Math.PI / TOTAL_LRG_TICKS;
double cosTheta = Math.cos(theta);
double sinTheta = Math.sin(theta);
int x1 = (int) (LRG_TICK_INNER_RAD * RADIUS * cosTheta + CENTER.getX());
int y1 = (int) (LRG_TICK_INNER_RAD * RADIUS * sinTheta + CENTER.getY());
int x2 = (int) (LRG_TICK_OUTER_RAD * RADIUS * cosTheta + CENTER.getX());
int y2 = (int) (LRG_TICK_OUTER_RAD * RADIUS * sinTheta + CENTER.getY());
g2.drawLine(x1, y1, x2, y2);
}
g2.setColor(CENTER_HUB_COLOR);
int x = (int) (CENTER.getX() - CENTER_HUB_RADIUS);
int y = (int) (CENTER.getY() - CENTER_HUB_RADIUS);
int width = (int) (2 * CENTER_HUB_RADIUS);
int height = width;
g2.fillOval(x, y, width, height);
// g2.draw(ellipse);
g2.dispose();
return img;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(DIAL_COLOR);
int x1 = (int) (DIAL_INNER_RAD * RADIUS * cosTheta + CENTER.getX());
int y1 = (int) (DIAL_INNER_RAD * RADIUS * sinTheta + CENTER.getY());
int x2 = (int) (DIAL_OUTER_RAD * RADIUS * cosTheta + CENTER.getX());
int y2 = (int) (DIAL_OUTER_RAD * RADIUS * sinTheta + CENTER.getY());
g.drawLine(x1, y1, x2, y2);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
final DailAnimation mainPanel = new DailAnimation();
JFrame frame = new JFrame("DailAnimation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
int delay = 100;
new Timer(delay, new ActionListener() {
int speed = 0;
@Override
public void actionPerformed(ActionEvent evt) {
speed ++;
if (speed > DailAnimation.MAX_SPEED) {
((Timer)evt.getSource()).stop();
}
mainPanel.setSpeed(speed);
}
}).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
答案 1 :(得分:0)
通过Graphics.drawLine()
绘制一条直接将像素写入支持Graphics实例的任何内容。如果要旋转线条,则必须计算旋转时其坐标应该是什么。这是在AWT和Swing中绘制东西的唯一方法。
您可以编写一个保持其角度的针类,然后让它每帧处理它的渲染。