之前没有这样做过,所以显然我很沮丧.这里,当前鼠标位置周围的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",因此无法更快地调用重绘,那么应该.
*添加此链接到thrashgod source rewrite
*添加此链接到thrashgod source rewrite 2
这是我的主要改写,具有以下值得注意的变化:
我将检测像素颜色的任务与绘图任务分开了
我用robot.createScreenCapture(...)替换了robot.getPixelColor(...)来一次获取所有64个像素,而不是一次获取一个
我已经介绍了智能剪辑 - 只重绘了需要重绘的内容.
我修复了线程,因此模型和视图的所有更新都发生在Event Dispatch Thread上
股票代码不断运行.当它检测到像素颜色的变化时(由于鼠标移动到不同的区域或鼠标变化下的像素),它会准确检测到更改的内容,更新模型,然后请求重新绘制视图.这种方法立即更新到人眼.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); } }); } } } } } } }
如果你不介意使用Swing,这个例子展示了如何快速放大BufferedImage
从a 获得的Icon
.在你的情况下,你需要一个8x8 BufferedImage
,mouseMoved()
用机器人看到的像素填充.
附录:这是您示例左上角的快照.
附录:
缩放本身并不重要......
缓慢的部分是从桌面获取像素; 缩放是次要的.如果您只是想看各种动画技术,请看一下这个例子.
附录:由于获得单个像素的速度很慢而且createScreenCapture()
@Steve McLeod提出的方法很快,这就是我开车的想法.您可以看到它也更顺畅地更新.请注意,释放鼠标按钮可以查看捕获的颜色.
import java.awt.AWTException; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; /** @see /sf/ask/17360801/ */ public class Zoom extends JPanel implements MouseMotionListener { private static final int SIZE = 16; private static final int S2 = SIZE / 2; private static final int SCALE = 48; private BufferedImage img; private Robot robot; public Zoom() { super(true); this.setPreferredSize(new Dimension(SIZE * SCALE, SIZE * SCALE)); img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_RGB); try { robot = new Robot(); } catch (AWTException e) { e.printStackTrace(System.err); } } @Override protected void paintComponent(Graphics g) { g.drawImage(img, 0, 0, getWidth(), getHeight(), null); } @Override public void mouseMoved(MouseEvent e) { Point p = e.getPoint(); int x = p.x * SIZE / getWidth(); int y = p.y * SIZE / getHeight(); int c = img.getRGB(x, y); this.setToolTipText(x + "," + y + ": " + String.format("%08X", c)); } @Override public void mouseDragged(MouseEvent e) { int x = e.getXOnScreen(); int y = e.getYOnScreen(); Rectangle rect = new Rectangle(x - S2, y - S2, SIZE, SIZE); img = robot.createScreenCapture(rect); repaint(); } private static void create() { JFrame f = new JFrame("Click & drag to zoom."); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Zoom zoom = new Zoom(); f.add(zoom); f.pack(); f.setVisible(true); zoom.addMouseMotionListener(zoom); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { create(); } }); } }