Java,如何绘制不断变化的图形

2024-02-13

以前没有这样做过,所以显然我很糟糕。这里,当前鼠标位置周围的 64 像素在表单上绘制得稍大一些。问题是,它“有点”慢,而且我不知道从哪里开始修复。

除此之外,我创建了一个线程,在完成后不断调用更新图形和一些类似文本的 fps,以真正显示绘制事物的速度。

图像示例:(图像来自 Eclipse 中的字母“a”)

代码示例:

@SuppressWarnings("serial")
public static class AwtZoom extends Frame {
    private BufferedImage image;
    private long timeRef = new Date().getTime();
    Robot robot = null;

    public AwtZoom() {
        super("Image zoom");
        setLocation(new Point(640, 0));
        setSize(400, 400);
        setVisible(true);
        final Ticker t = new Ticker();

        this.image = (BufferedImage) (this.createImage(320, 330));
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                t.done();
                dispose();
            }
        });
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
        t.start();
    }

    private class Ticker extends Thread {
        public boolean update = true;
        public void done() {
            update = false;
        }
        public void run() {
            try {

                while (update == true) {
                    update(getGraphics());
                    // try {
                    // Thread.sleep(200);
                    // } catch (InterruptedException e) {
                    // e.printStackTrace();
                    // return;
                    // }
                }
            } catch (Exception e) {

                update=false;
            }
        }
    }

    public void update(Graphics g) {
        paint(g);
    }

    boolean isdone = true;
    public void paint(Graphics g) {
        if (isdone) {
            isdone=false;
            int step = 40;
            Point p = MouseInfo.getPointerInfo().getLocation();

            Graphics2D gc = this.image.createGraphics();

            try {

                for (int x = 0; x < 8; x++) {
                    for (int y = 0; y < 8; y++) {
                        gc.setColor(robot.getPixelColor(p.x - 4 + x, p.y
                                - 4 + y));
                        gc.fillOval(x * step, y * step, step - 3, step - 3);
                        gc.setColor(Color.GRAY);
                        gc.drawOval(x * step, y * step, step - 3, step - 3);
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            gc.dispose();
            isdone = true;
            iter++;
        }
        g.drawImage(image, 40, 45, this);
        g.setColor(Color.black);
        StringBuilder sb = new StringBuilder();
        sb.append(iter)
                .append(" frames in ")
                .append((double) (new Date().getTime() - this.timeRef) / 1000)
                .append("s.");
        g.drawString(sb.toString(), 50, 375);
    }

    int iter = 0;
}

所做的更改:
* 添加了“gc.dispose();”
* 添加了“isdone”,因此重绘不能更快地调用,那么它应该。
* 添加这个链接 http://pastebin.com/huD9s6bqthrashgod 源码重写
* 添加这个链接 http://pastebin.com/V8mDfUiVthrashgod 源码重写 2


这是我的主要重写,其中包含以下值得注意的更改:

  • 我将检测像素颜色的任务与绘图任务分开
  • 我已将 robots.getPixelColor(...) 替换为 robots.createScreenCapture(...) 以一次获取所有 64 个像素,而不是一次获取一个像素
  • 我引入了智能裁剪 - 仅重绘需要重绘的内容。
  • 我已经修复了线程,因此模型和视图的所有更新都发生在事件调度线程上

股票行情持续运行。当它检测到像素颜色发生变化(由于鼠标移动到不同区域或鼠标下的像素发生变化)时,它会准确检测发生的变化,更新模型,然后请求视图重新绘制。这种方法对于人眼来说是即时更新的。 289次屏幕更新累计耗时1秒。

对于一个安静的周六晚上来说,这是一次令人愉快的挑战。

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;

public class ZoomPanel extends JPanel {

    private static final int STEP = 40;
    private int iter = 0;
    private long cumulativeTimeTaken = 0;


    public static void main(String[] args) {
        final JFrame frame = new JFrame("Image zoom");

        final ZoomPanel zoomPanel = new ZoomPanel();
        frame.getContentPane().add(zoomPanel);
        final Ticker t = new Ticker(zoomPanel);

        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                t.done();
                frame.dispose();
            }
        });
        t.start();

        frame.setLocation(new Point(640, 0));
        frame.pack();
        frame.setVisible(true);
    }

    private final Color[][] model = new Color[8][8];

    public ZoomPanel() {
        setSize(new Dimension(400, 400));
        setMinimumSize(new Dimension(400, 400));
        setPreferredSize(new Dimension(400, 400));
        setOpaque(true);
    }

    private void setColorAt(int x, int y, Color pixelColor) {
        model[x][y] = pixelColor;
        repaint(40 + x * STEP, 45 + y * STEP, 40 + (x * STEP) - 3, 45 + (y * STEP) - 3);
    }

    private Color getColorAt(int x, int y) {
        return model[x][y];
    }

    public void paintComponent(Graphics g) {
        long start = System.currentTimeMillis();
        if (!SwingUtilities.isEventDispatchThread()) {
            throw new RuntimeException("Repaint attempt is not on event dispatch thread");
        }
        final Graphics2D g2 = (Graphics2D) g;
        g2.setColor(getBackground());
        try {

            for (int x = 0; x < 8; x++) {
                for (int y = 0; y < 8; y++) {
                    g2.setColor(model[x][y]);
                    Ellipse2D e = new Ellipse2D.Double(40 + x * STEP, 45 + y * STEP, STEP - 3, STEP - 3);
                    g2.fill(e);
                    g2.setColor(Color.GRAY);
                    g2.draw(e);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        iter++;
        g2.setColor(Color.black);
        long stop = System.currentTimeMillis();
        cumulativeTimeTaken += stop - start;
        StringBuilder sb = new StringBuilder();
        sb.append(iter)
                .append(" frames in ")
                .append((double) (cumulativeTimeTaken) / 1000)
                .append("s.");

        System.out.println(sb);
    }

    private static class Ticker extends Thread {

        private final Robot robot;

        public boolean update = true;
        private final ZoomPanel view;

        public Ticker(ZoomPanel zoomPanel) {
            view = zoomPanel;
            try {
                robot = new Robot();
            } catch (AWTException e) {
                throw new RuntimeException(e);
            }
        }

        public void done() {
            update = false;
        }

        public void run() {
            int runCount = 0;
            while (update) {
                runCount++;
                if (runCount % 100 == 0) {
                    System.out.println("Ran ticker " + runCount + " times");
                }
                final Point p = MouseInfo.getPointerInfo().getLocation();

                Rectangle rect = new Rectangle(p.x - 4, p.y - 4, 8, 8);
                final BufferedImage capture = robot.createScreenCapture(rect);

                for (int x = 0; x < 8; x++) {
                    for (int y = 0; y < 8; y++) {
                        final Color pixelColor = new Color(capture.getRGB(x, y));

                        if (!pixelColor.equals(view.getColorAt(x, y))) {
                            final int finalX = x;
                            final int finalY = y;
                            SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    view.setColorAt(finalX, finalY, pixelColor);
                                }
                            });
                        }
                    }
                }

            }
        }

    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java,如何绘制不断变化的图形 的相关文章

  • 如何在 JFace 的 TableViewer 中创建复选框?

    我创建了一个包含两列的 tableViewer 我想将其中一列设为复选框 为此 我创建了一个 CheckBoxCellEditor 但我不知道为什么它不起作用 名为 tableName 的列显示其值正常 色谱柱规格如下 String COL
  • 我需要在 Spring 中检查每个控制器中的有效会话吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设在 Spring Mvc 的 Web 应用程序中 我们是否需要检查每个控制器或 jsps 中的有效会话 我该如何解决 MVC 中的
  • manifest.mf 文件的附加内容的约定?

    Java JAR 中的 MANIFEST MF 文件是否有任何超出 MANIFEST MF 约定的约定 JAR规范 http download oracle com javase 1 4 2 docs guide jar jar html
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • 如何在 Java 中禁用 System.out 以提高速度

    我正在用 Java 编写一个模拟重力的程序 其中有一堆日志语句 到 System out 我的程序运行速度非常慢 我认为日志记录可能是部分原因 有什么方法可以禁用 System out 以便我的程序在打印时不会变慢 或者我是否必须手动检查并
  • 如何在jsp代码中导入java库?

    我有以下jsp代码 我想添加 java io 等库 我怎样才能做到这一点
  • 为什么这个 R ggplot2 代码会显示一个空白的显示设备?

    虽然 SO 通常不用于帮助解决错误 但这个显示了特别简单且特别烦人的行为 如果你是一个ggplot2用户 您可以在 10 秒或更短的时间内重现它 正如这个 GitHub 问题 ggplot gtable 创建空白显示 https githu
  • Microsoft Graph 身份验证 - 委派权限

    我可以使用 Microsoft Graph 访问资源无需用户即可访问 https developer microsoft com en us graph docs concepts auth v2 service 但是 此方法不允许我访问需
  • Prim 的迷宫生成算法:获取相邻单元格

    我基于 Prim 算法编写了一个迷宫生成器程序 该算法是 Prim 算法的随机版本 从充满墙壁的网格开始 选择一个单元格 将其标记为迷宫的一部分 将单元格的墙壁添加到墙壁列表中 While there are walls in the li
  • 请求位置更新参数

    这就是 requestLocationUpdates 的样子 我使用它的方式 requestLocationUpdates String provider long minTime float minDistance LocationLis
  • Clip 在 Java 中播放 WAV 文件时出现严重延迟

    我编写了一段代码来读取 WAV 文件 大小约为 80 mb 并播放该文件 问题是声音播放效果很差 极度滞后 你能告诉我有什么问题吗 这是我的代码 我称之为doPlayJframe 构造函数内的函数 private void doPlay f
  • Java中接口作为方法参数

    前几天去面试 被问到了这样的问题 问 反转链表 给出以下代码 public class ReverseList interface NodeList int getItem NodeList nextNode void reverse No
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 使用 Flyway 和 Hibernate 的 hbm2ddl 在应用程序的生命周期中管理数据库模式

    我正在开发 Spring Hibernate MySql 应用程序 该应用程序尚未投入生产 我目前使用 Hibernatehbm2ddl该功能对于管理域上的更改非常方便 我也打算用Flyway用于数据库迁移 在未来的某个时候 该应用程序将首
  • 应用程序关闭时的倒计时问题

    我制作了一个 CountDownTimer 代码 我希望 CountDownTimer 在完成时重新启动 即使应用程序已关闭 但它仅在应用程序正在运行或重新启动应用程序时重新启动 因此 如果我在倒计时为 00 10 分钟 秒 时关闭应用程序
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • Windows 上的 Nifi 命令

    在我当前的项目中 我一直在Windows操作系统上使用apache nifi 我已经提取了nifi 0 7 0 bin zip文件输入C 现在 当我跑步时 bin run nifi bat as 管理员我在命令行上看到以下消息 但无法运行
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour
  • 休眠以持久保存日期

    有没有办法告诉 Hibernate java util Date 应该持久保存 我需要这个来解决 MySQL 中缺少的毫秒分辨率问题 您能想到这种方法有什么缺点吗 您可以自己创建字段long 或者使用自定义的UserType 实施后User

随机推荐