Java Applet

时间:2015-05-25 17:57:42

标签: java applet curve

所以我被赋予了一个选择图片并使用java代码(主要是drawLine和drawArc方法)绘制它的任务,我决定在下面的截图链接中显示的flamel。

enter image description here

问题1:drawArc方法是否正确(x,y,x width,y height,startAngle,arcAngle)?我将图片放入油漆并打开网格,这样我就可以得到(x,y)坐标并计算高度和宽度。然而,当我运行程序时,弧永远不会从(x,y)坐标开始,我总是必须调整所有数字以将弧移动到它应该的位置。有没有什么办法解决这一问题?我做错了吗?

enter image description here

问题2:上面的截图是我到目前为止编码的结果。请注意,正如红色箭头所指出的那样,弧线的末端向内移动,而不是以倾斜结束。将该弧度与第一个屏幕截图(原始flamel)的相应区域进行比较,以更好地了解我的意思。基本上我想要一条流过的曲线。我四处寻找并发现了Cardinal Spline(Catmull-Rom),这正是我正在寻找的,但我没有找到 easy 解释它是如何工作的或者为它编写代码。代码越短越好(更容易理解)。我使用jGrasp进行编码,我发现的所有“演示”和“源代码”都有大量编译错误,我不理解,也不知道如何修复。我是一个Java新手,所以如果有人可以让我了解如何创建一个通过Java Applet中的多个点的曲线的基础知识,我将非常感激。

以下代码

import java.applet.*;
import java.awt.*;

public class Flamel extends Applet
{
public void paint (Graphics flamel)
{
  //crown

  flamel.drawLine(217,75,217,105);
  flamel.drawLine(283,75,283,105);
  flamel.drawLine(217,105,283,105);
  flamel.drawArc(217,62,33,20,180,180);
  flamel.drawArc(250,62,33,20,180,180);

  //left wing

  flamel.drawLine(203,98,147,98);
  flamel.drawLine(233,133,216,133);
  flamel.drawLine(204,127,181,127);
  flamel.drawLine(181,127,172,118);
  flamel.drawArc(204,113,22,20,199,67);
  flamel.drawArc(158,93,25,25,190,90);
  flamel.drawArc(145,95,20,14,154,140);
  flamel.drawArc(203,65,60,67,180,90);


  //right wing

  flamel.drawLine(297,98,353,98);
  flamel.drawLine(267,133,284,133);
  flamel.drawLine(296,127,319,127);
  flamel.drawLine(319,127,328,118);
  flamel.drawArc(274,113,22,20,270,67);
  flamel.drawArc(318,93,25,25,260,80);
  flamel.drawArc(334,95,20,14,255,140);
  flamel.drawArc(236,65,60,67,270,90);

  //cross heads (top/bottom/left/right)

  flamel.drawLine(250,128,237,151);
  flamel.drawLine(250,128,263,151);
  flamel.drawLine(237,151,244,159);
  flamel.drawLine(263,151,257,159);

  flamel.drawLine(250,421,238,398);
  flamel.drawLine(250,421,263,398);
  flamel.drawLine(238,398,244,393);
  flamel.drawLine(263,398,257,393);

  flamel.drawLine(170,220,146,233);
  flamel.drawLine(170,246,146,233);
  flamel.drawLine(170,220,177,227);
  flamel.drawLine(170,246,177,240);

  flamel.drawLine(330,220,354,233);
  flamel.drawLine(330,246,354,233);
  flamel.drawLine(330,220,323,227);
  flamel.drawLine(330,246,323,240);


  //cross body

  flamel.drawLine(244,159,244,393);
  flamel.drawLine(257,159,257,393);
  flamel.drawLine(177,227,323,227);
  flamel.drawLine(177,240,323,240);


  //snake (starting upward from tail)

  flamel.drawArc(252,342,10,45,270,180);
  flamel.drawArc(240,296,6,33,90,180);
  flamel.drawArc(225,270,35,85,90,180);
  flamel.drawArc(235,218,45,45,270,90);

  }
  }

1 个答案:

答案 0 :(得分:0)

不可否认,当目标是连接几十个或几百个drawLinedrawArc个电话时,我认为这不是一个编程练习。而且我不完全确定它是否适合作为一个问题。但我会尝试以更广泛的规范方式回答它,希望它仍然可以接受,即使我提出的解决方案不再包含drawLine或{的任何调用{1}} ...

通常,您应该考虑绘制“复杂”几何对象的替代方法。 Graphics类的drawArcdrawLine方法可能会被使用,并且可能会有应用案例,但我个人认为它们主要是作为遗留特征源于Java 1.0。

在Java中有更多现代的表示几何形状的方法。特别是,通过Shape接口(因此名称......)。

drawArc界面的优势在于其灵活性的提高。这个接口有很多实现。例如,Line2DArc2D,或者 - 最重要的是 - Path2D。后者允许通过指定线端点的坐标来手动“构建”形状。它还支持三次曲线部分(样条曲线 - 不是Catmull-Rom,但是Bezier),使用Path2D#curveTo方法(以及稍微简单的Shape方法)。 quadTo类还允许您使用Path2D#append方法任意组合多个形状。

考虑到您的应用案例,还可以使用Stroke#createStrokedShape方法创建描边形状。简单地说:如果你有Path2D代表一条细线,那么你可以使用这种方法创建一个代表Shape。 (请注意,这与绘图具有粗笔划的细线不同!)。

这是一个绘制类似于原始绘画部分的内容的示例(红色和绿色部分仅用于指出实际绘制的内容......):

Path

使用以下代码创建:

Shape

实际上,最难的部分是制作这些箭形末端。但是如果结果只是看起来像原始的,并且你不需要一个代表绘制元素的整个轮廓的实际形状,你可以简单地将这些头部涂在其余的部分上......

脚注:

  • 手动摆弄坐标仍然不是我认为是一个很好的编程练习。但也许你(或正在阅读这个答案的其他人)有机会学习Java2D中的import java.applet.Applet; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Arc2D; import java.awt.geom.Path2D; public class Flamel extends Applet { public void paint (Graphics gr) { Graphics2D g = (Graphics2D)gr; g.setColor(Color.WHITE); g.fillRect(0,0,getWidth(),getHeight()); g.setColor(Color.BLACK); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Path2D path = new Path2D.Double(); // Create the lower, snail-like part path.moveTo(100, 300); path.quadTo(115, 275, 100, 260); path.quadTo( 60, 225, 100, 200); path.quadTo(150, 180, 150, 150); // Append the upper part, which is a "perfect arc" Arc2D a = new Arc2D.Double(50, 100, 100, 100, 0, 180, Arc2D.OPEN); path.append(a, true); BasicStroke s = new BasicStroke(14); // Fill a stroked version of the path g.setColor(Color.BLACK); g.fill(s.createStrokedShape(path)); // Draw the path g.setColor(Color.GREEN); g.draw(path); // Draw a stroked version of the path: g.setColor(Color.RED); g.draw(s.createStrokedShape(path)); } } 类......

  • 对于某些应用案例,通过Shape对象表示“所有内容”可能有缺点 - 例如,盲目创建许多 Line2D对象作为插入替换Shape调用,这可能会产生一些开销,影响性能和内存(导致GC)。但这肯定不适用于此。