这是我的主要重写,其中包含以下值得注意的更改:
- 我将检测像素颜色的任务与绘图任务分开了
- 我已将robot.getPixelColor(…)替换为robot.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); } }); } } } } } }}


