之前没有这样做,显然我很沮丧。这里,当前鼠标位置周围的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”,因此无法更快地调用重绘,那么它应该
*将this link添加到thrashgod源重写
*将this link添加到thrashgod source rewrite 2
答案 0 :(得分:14)
这是我的主要改写,有以下值得注意的变化:
自动收报机不断运行。当它检测到像素颜色的变化时(由于鼠标移动到不同的区域或鼠标变化下的像素),它会准确检测到更改的内容,更新模型,然后请求重新绘制视图。这种方法立即更新到人眼。 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);
}
});
}
}
}
}
}
}
}
答案 1 :(得分:6)
如果您不介意使用Swing,则此example会显示如何快速放大从BufferedImage
获得的Icon
。在您的情况下,您需要使用机器人看到的像素填充BufferedImage
的8x8 mouseMoved()
。
附录:这是您示例左上角的快照。
附录:
缩放本身并不重要......
缓慢的部分是从桌面获取像素;缩放是次要的。如果您只想查看各种动画技术,请查看此example。
附录:由于获得单个像素的速度很慢而且@Steve McLeod提出的createScreenCapture()
方法很快,这就是我开车的想法。您可以看到它也更顺畅地更新。请注意,释放鼠标按钮可以查看捕获的颜色。
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 https://stackoverflow.com/questions/3742731 */
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();
}
});
}
}
答案 2 :(得分:0)
将此方法添加到Paint方法:
public void clear(Graphics g, Color currentColor) {
g.setColor(backgroundColor);
g.fillRect(0, 0, width, height);
g.setColor(currentColor);
int delay = 5; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) { } };
new Timer(delay, taskPerformer).start();
} //run this right before you draw something
好的,所以使用计时器来减慢延迟,而不是线程,这很糟糕。
答案 3 :(得分:-1)
只需使用时间延迟循环。然后您可以通过调整i的限制来微调延迟。它还可以让您通过某些命中和试验来调整转换速度。
for(long i = 0; i&lt; = 100000000000; i ++);
canvas.repaint();
它对我来说非常好,也不需要使用缓冲图像。