【发布时间】:2014-09-25 20:17:54
【问题描述】:
在您阅读之前,这将是一个信息:Java JFrame won't show up after using .setVisible(true) after being invisible
您好,我正在开发一个库 API,它可以让您捕获屏幕的某个区域,它会返回一个包含 ByteArrayInputStream 和实用方法(如 createBufferedImage、createFile 等)的类。
基本上,您创建一个 Bootstrap 实例,并将您想要的捕获器类型作为依赖项(ScreenshotCapturer 或 GifCapturer)传递:
Bootstrap b = new Bootstrap(new ScreenshotCapturer());
而beginCapture 方法接收一个实现ScreenCaptureCallback 的对象,这是将捕获的结果传递给的回调事件。
这是一个简短的背景。
现在,当您使用beginCapture 方法时,基本上它所做的就是创建SelectionCamera 的新实例,这基本上是绘制您在拖动鼠标时选择的选择区域并更新侦听器的组件。
一旦创建实例,它就会调用super.setVisible(true);
调用该方法后,框架会显示出来,并且还会显示旧的绘制屏幕大约 600-500 毫秒,我不确定,但它消失得如此之快。
看看这个活生生的例子:
请注意使用视频选项,否则您将看不到我所看到的,因为 gif 太慢而无法显示!
http://gyazo.com/d2f0432ada37842966b42dfd87be4240
你可以看到我再次点击屏幕截图后,它显示了旧的选定区域并迅速消失。 (顺便说一下,您在 gif 中看到的框架不是应用程序的一部分,只是虚拟的 hello world 示例用法)。
图像捕获的过程。
第 1 步
beginCapture 被调用:
public void beginCapture(final ScreenCaptureCallback c) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
capturer.setCallback(c);
capturer.beginSelection();
}
});
}
第 2 步
beginSelection 在 Capturer 类中被调用(ScreenshotCapturer 扩展 Capturer(摘要)
@Override
public void beginSelection() {
super.init();
this.setHotkeys();
super.getCamera().startSelection();
}
第 3 步
CaptureCamera#startSelection() 被调用
public void startSelection() {
super.getContentPane().removeAll();
super.getContentPane().repaint();
super.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
this.selector = new SelectionCamera();
this.selectionMosueAdapter.updateCamera(this.selector);
this.selectionMouseMotion.updateCamera(this.selector);
super.add(this.selector);
super.setVisible(true);
super.repaint();
super.getContentPane().repaint();
}
第 4 步
用户选择一个区域,鼠标监听器和鼠标移动都监听它(Take a look at mouse motion):
@Override
public void mouseDragged(MouseEvent e) {
Point dragPoint = e.getPoint();
Point startPoint = this.selector.getStartPoint();
int x = Math.min(startPoint.x, dragPoint.x);
int y = Math.min(startPoint.y, dragPoint.y);
int width = Math.max(startPoint.x - dragPoint.x, dragPoint.x - startPoint.x);
int height = Math.max(startPoint.y - dragPoint.y, dragPoint.y - startPoint.y);
this.selector.setCameraDimension(width, height);
this.selector.setCoordinates(x, y);
this.camera.repaint(); // important
}
顺便说一下,this.selector 是 SelectorCamera,它是绘制选择区域的组件。
第 5 步
CaptureCamera#endSelection() 被调用,此方法从选择相机中获取 x、y、宽度、高度,并将其传递给捕获器类,该捕获器类使用机器人获取该矩形的屏幕截图,并在此之前删除所有组件从内容窗格中,重新绘制所有内容,然后将可见性设置为 false。
public void endSelection() {
super.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
int x = this.selector.getCameraX();
int y = this.selector.getCameraY();
int w = this.selector.getCameraWidth();
int h = this.selector.getCameraHeight();
super.getContentPane().removeAll();
super.getContentPane().repaint();
//super.repaint();
super.setVisible(false);
this.c.startCapturing(x, y, w, h);
}
基本上这是最后一步,其余步骤对于调试来说是不必要的,因为它只发回回调。
我真的尽力解释了我的申请过程,我已经尝试了 5 个半小时,但完全没有运气。如您所见,通过创建新的 SelectionCamera 对象尝试了不同的方法,但不起作用。
为什么要这样做?是不是跟摆动核心有关系?
SelectionCamera 代码:https://github.com/BenBeri/WiseCapturer/blob/master/src/il/ben/wise/SelectionCamera.java
提前致谢。
【问题讨论】:
-
它“lloks”就像
selector可能需要重置......也许......您可能还想突出显示您的代码和捕获库中的代码.. . -
一切都在图书馆里,一切都是我的代码
-
@MadProgrammer 您说选择器需要重置,但是即使我从 JFrame 中删除该组件,如果它这样做,这怎么可能,这意味着它不会再被重新绘制或显示?
-
使 Frame left 为 -10,000 然后设置可见 true,添加一个计时器 2 秒,在计时器上:left to 0
-
@tgkprog 这行得通,但是你有什么核心解释为什么会发生这种情况吗?
标签: java swing api user-interface