Java中的多个2D图形绘制函数

时间:2014-08-29 18:35:18

标签: java swing graphics2d

我正在处理的程序包含一个名为GameForm的类,它扩展了JFrame。此表单将包含地图(只是一系列矩形),以及地图上的某些对象。

但是,我无法使用单个paintComponent(Graphics g)函数绘制所有这些对象,因为并非游戏中的所有对象都必须同时绘制。例如,drawMap()函数仅在表单首次加载时调用,而所有其他绘图函数将在每次转弯后调用。

但是,根据我的阅读(如果我错了请纠正我),类中只允许一个paintComponent函数,其他函数不能使用它的Graphics2D对象。

是否有任何关于如何实施这一点的想法?

2 个答案:

答案 0 :(得分:1)

对Swing / GUI编程不熟悉的人通常认为JFrames就像绘图表面或纸张。但是,你必须习惯这种情况并非如此。

首先,GUI程序有某种EDT(Event Dispatch Thread)。此线程是所有GUI操作发生的位置。此处更新GUI并响应用户输入。这是必要的,因为用户交互和GUI的程序化更改需要很好地同步。

回到主题,JFrame基本上只是一个注册到系统的矩形,作为你的“绘图表面”。 要求绘制它,而不仅仅是在它上面绘画。

这就是paintComponent(Graphics)的好处。显然,你不想一直画画。它的工作原理如下:

  1. 用户打开您的窗口
  2. 系统告诉你的应用:“嘿,你想要这个表面,请画它”
  3. 来自paintComponent()的图片用于重绘您的框架(快速)
  4. 您的应用程序在用户进行下一次输入之前保持不活动状态
  5. 如果你想为你的框架设置动画,你必须像这样工作:

    1. 告诉系统:“嘿,我想重绘我的表面”(致电repaint()
    2. 系统调用paintComponent()并重新绘制您的内容
    3. 下次通话必须延迟
    4. 重新开始,画下一张图片
    5. 请注意延迟很重要,因为所有这些都发生在神圣的EDT上。 EDT处理所有事情并需要“呼吸”,以便用户在您制作动画时可以做一些事情。

      总而言之,您所学到的是:

      1. 保存变量绘制所需的所有状态
      2. 调用paintComponent()时,绘制到表面
      3. 如果您想制作动画,请致电repaint() - > paintComponent()将被称为
      4. 永远不会阻止EDT
      5. 最后要考虑的事项:不要使用JFrame直接绘制
        而不是那样,向框架添加JPanel并覆盖其paintComponent()方法。

答案 1 :(得分:0)

一般来说,您希望实现的目标可以通过几种方式完成。它与所谓的 sprites http://en.wikipedia.org/wiki/Sprite_%28computer_graphics%29)和图像缓冲(http://en.wikipedia.org/wiki/Multiple_buffering)严格相关。最简单的方法是:

a)paintComponent() JPanel JFrame添加到您的JFrame,通过处理所有输入数据/用户事件/机器状态生成生成的图像,

b)你可以准备&将 overlay 存储为例如BufferedImage,根据需要更新它,然后在单个调用期间将其绘制在JFrame上 - paint()的状态将仅在绘制事件(paintComponents()JFrame上更新等,如果地图发生变化而没有直接repaint()交互(调整窗口大小,用其他框架覆盖等),例如通过调用getGraphics()等,你必须手动强制失效。

c)您可以通过调用Graphics2Dhttp://docs.oracle.com/javase/7/docs/api/javax/swing/JFrame.html#getGraphics%28%29)获取绘图上下文,然后在需要时使用返回的对象(可能已转换为JPanel)作为您的画布。请注意,就效率而言,这实际上是最差解决方案。

他们是唯一可能的 - 我曾经一次使用OpenGL / JOGL来满足我的大部分2D渲染需求,因为它允许疯狂渲染速度以及3D的所有利润图形[插值,缩放,旋转,alpha混合,透视,几何变形,着色等],只需很少的功能开销。

另外,请注意,通常建议使用专用画布组件(例如JFrame)而不是全局JFrame - 它连接到 - 称轻量级与重量级组件差异以及其他OOP / Swing / AWT / EDT问题;它还允许隐藏地图,并通过一个简单的JPanel #setVisible(false)调用将{{1}}重新用于其他内容。

有关详细信息,请参阅java what is heavier: Canvas or paintComponent()?