【问题标题】:Dynamic Graphics Object Painting动态图形对象绘画
【发布时间】:2012-05-17 00:30:41
【问题描述】:

试图找出最好的方法来做到这一点(并且不跨越任何我不知道的细节)。

我正在用圆和线来直观地显示一个图形(各种节点,用边连接它们)来表示这种图形。每个节点都将在运行时添加,我无法对其进行硬编码。据我了解,所有绘画都需要在 paint(Graphics g) 方法中完成 - 这没什么帮助,因为我无法更改参数,而且似乎只在初始创建期间调用?

现在我正在考虑让它调用各种其他方法,传递 Graphics 对象,并取决于其他变量 - 我将决定这是否是我什至想要调用的(因为 paint() 方法是唯一的一个我可以打电话)。

我这样做完全错了吗?以前从来没有在意过这个。

为了让您更好地了解我想要最终得到什么:我希望能够传递我想为节点添加的形状的坐标,然后将其添加到图表上的任何内容中,这样远的。然后与边缘相同,我希望能够通过线的起点和终点以在当时存在的任何内容之上重新绘制。

不完全是我现在想要的 - 但你会从我到目前为止拼凑的内容中得到这个想法:

import java.awt.*;
import javax.swing.*;
public class MyCanvas extends Canvas
{
    public MyCanvas()
    {
    }
    public void paint(Graphics graphics)
    {
        // Keep this until I figured out if it's painted on load or not.
        graphics.drawLine(10, 20, 350, 380);
    }
    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(canvas);
        frame.setVisible(true);
    }
    public void drawNode(int x, int y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5 
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g.setColor(Color.white);
            g.fillOval(xLoc, yLoc, 8, 8);
            g.drawOval(xLoc, yLoc, 8, 8);
    }
    public void drawArc(int x, int y, int xx, int yy, Graphics g)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
            g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }

}

编辑:(对安德鲁的回应)

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MyCanvas extends JPanel
{

    public MyCanvas() {

    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }

    public static void main(String[] args)
    { 
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;

        JFrame frame = new JFrame();
        JLabel label = new JLabel();
        BufferedImage bImage = new BufferedImage(canvasSize, canvasSize, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bImage.createGraphics();
        g2d.drawLine(50, 50, 300, 300);
        ImageIcon iIcon = new ImageIcon(bImage); 
        label.setIcon(iIcon);
        frame.add(label);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        g2d = drawNode(1,1,g2d);
        label.repaint();
    }

    public static Graphics2D drawNode(int x, int y,Graphics2D g2d)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5 
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g2d.setColor(Color.white);
            g2d.fillOval(xLoc, yLoc, 8, 8);
            g2d.drawOval(xLoc, yLoc, 8, 8);
            return g2d;
    }
    public static void drawArc(int x, int y, int xx, int yy)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
           // g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }

}

【问题讨论】:

  • 不要混合使用 Swing(例如 JFrame)和 AWT(例如 Canvas)组件。代替Canvas,使用JPanel 并覆盖paintComponent(Graphics)

标签: java swing graphics paint


【解决方案1】:

您可以为此采取各种策略。

  1. 如果对象在完成后从未从绘图中删除,请使用BufferedImage,将其放入(ImageIcon in a)JLabel。到时候更新:
    1. 获取图像的图形实例并绘制新元素。
    2. 释放图形对象。
    3. 拨打标签上的repaint()
  2. 保留已绘制元素的列表。在paint方法中,将它们全部绘制。添加新元素时,在渲染组件上调用repaint()

这是第一种技术的示例:

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;

public class MyCanvas
{
    JLabel view;
    BufferedImage surface;
    Random random = new Random();

    public MyCanvas()
    {
        surface = new BufferedImage(600,400,BufferedImage.TYPE_INT_RGB);
        view = new JLabel(new ImageIcon(surface));
        Graphics g = surface.getGraphics();
        g.setColor(Color.ORANGE);
        g.fillRect(0,0,600,400);
        g.setColor(Color.BLACK);
        // Keep this until I figured out if it's painted on load or not.
        g.drawLine(10, 20, 350, 380);
        g.dispose();

        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addNewElement();
            }
        };
        Timer timer = new Timer(200, listener);
        timer.start();
    }

    public void addNewElement() {
        boolean drawArc = random.nextBoolean();
        int x = random.nextInt(60);
        int y = random.nextInt(40);
        Graphics g = surface.getGraphics();
        if (drawArc) {
            g.setColor(Color.BLUE);
            int xx = random.nextInt(60);
            int yy = random.nextInt(40);
            drawArc(x,y,xx,yy,g);
        } else {
            drawNode(x,y,g);
        }
        g.dispose();
        view.repaint();
    }

    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(canvas.view);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public void drawNode(int x, int y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g.setColor(Color.white);
            g.fillOval(xLoc, yLoc, 8, 8);
            g.drawOval(xLoc, yLoc, 8, 8);
    }

    public void drawArc(int x, int y, int xx, int yy, Graphics g)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
            g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }
}

进一步提示

您可能会注意到线条看起来很“锯齿状”且很难看。 BufferedImageJComponent 都可以访问更有用的Graphics2D 对象(对于JComponent,必须将其转换为paintComponent())。 Graphics2D 实例接受可用于平滑(抖动)绘制的元素的渲染提示。

【讨论】:

  • 哇 - 好吧,你确实在 12 秒前编辑了它,但只是想问一下这是不是你的意思:pastebin.com/tsgVeshn 不过我会很快读完你所说的。
  • 不会跟随 pastebin 链接。如果足够短,请将其添加为编辑。
  • 已编辑。出于好奇 - 有什么理由不关注 pastebin 链接?
  • @trashgod - 您是否对发布了 pastebin 链接发表评论?您也可以从 pastebin 复制原始代码(加上一些漂亮的语法突出显示:p)
  • 我通常会,虽然我今天感觉很懒。不过总的来说,人们觉得如果代码足够短,可以发布到 SO - 如果不是,他们会查看它。此外,a)有些人害怕“外部链接”(好吧 - 不是 pastebin 那么多)& b)如果pastebin 消失,我们将有代码以供将来参考。如果一个问题是“自包含”且“没有外部依赖关系”,那就更好了。 c) 另见垃圾神的观点。
猜你喜欢
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
相关资源
最近更新 更多