gpt4 book ai didi

Java JFrame 在不可见后使用 .setVisible(true) 后不会显示

转载 作者:行者123 更新时间:2023-11-30 09:04:48 25 4
gpt4 key购买 nike

我会从下到上开始解释,这样你就会真正理解我想做什么,并更好地理解我的代码。

我正在创建一个库,让您捕获一个区域,无论捕获的是 gif 动画还是图像。捕获完成后,该库将返回一个对象,该对象包含 ByteArrayInputStreamcreateImage 等实用方法。

阅读本文时,您可以在此处访问图书馆:https://github.com/BenBeri/WiseCapturer/

现在这是一个关于我的库如何工作的虚拟示例:

您的应用程序使用捕获器类创建引导实例,并开始捕获:

public static void main(String[] args) throws AWTException {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}

监听器将返回 CapturedImage,您可以使用它来做任何您想做的事情。现在有了这个例子,这应该让你捕获两次,一次又一次在你完成后,一旦完成,它将在 JFrame 窗口中显示第二次捕获。

现在我不是在谈论这个 JFrame。

这个问题只出现在 ScreeenshotCapturer 上,它会在 GifCapturer 实例上正常工作。

问题

完成第一次捕获后,第二次捕获 JFrame 透明窗口不会出现,我在窗口工具栏中没有看到它,也没有在任何地方看到它,但应用程序仍在运行。

但是,正如我所说,如果我使用 GifCapturer 实例,它确实有效。

现在让我们调试我的库是如何工作的:

引导构造函数:

/**
* Bootstrap consturctor, let it bootstrap!
* @param c
* Capturer instance
* @throws AWTException
*/
public Bootstrap(Capturer c) throws AWTException {
this.capturer = c;
}

现在 Capturer 类初始化,它是抽象类,所有捕获器都有相同的构造函数:

public Capturer() throws AWTException {
this.camera = new CaptureCamera(this);
}

这会创建一个新的捕捉相机,这是我遇到问题的地方。CaptureCamera 的目的是让整个 JFrame,透明大小与我的屏幕相同,并在其中包含负责绘制选择矩形的 JPanel。

它的构造函数:

public CaptureCamera(Capturer c) throws AWTException {
this.c = c;
this.toolkit = Toolkit.getDefaultToolkit();
this.screen = this.toolkit.getScreenSize();
this.robot = new Robot();
this.selector = new SelectionCamera();

super.setSize(this.screen);
super.setUndecorated(true);
super.setBackground(new Color(255, 255, 255, 1));

// Listeners for area selection
super.addMouseListener(new SelectionAdapter(this, this.selector));
super.addMouseMotionListener(new SelectionMotion(this, this.selector));

super.add(this.selector);
}

好了,现在让我们来看看捕获是如何开始的。

bootstrap 中的 beginCapture 方法:

/**
* Starts capturing the screen, sends back a callback event with the
* captured file.
*
* The system saves a temporary file to send the file.
* @param c
* Callback instance
*/
public void beginCapture(ScreenCaptureCallback c) {
this.capturer.setCallback(c);
this.capturer.beginSelection();
}

setCallback 对于这个问题并不是很重要,所以 beginSelection 方法:

所有捕获器都一样

@Override
public void beginSelection() {
super.init();
this.setHotkeys();
super.getCamera().startSelection();
}

startSelection 方法(抱歉,重复的名称具有相同的含义,稍后会更改):

/**
* Starts area selection event
* @param c Capturer instance
*/
public void startSelection() {
super.setVisible(true);
}

好的,这是应该让 JFrame 可见的地方,我之前尝试过打印并且它显示为 true,但是 JFrame 在第二次尝试时没有显示。

现在框架可见,用户可以选择一个区域。选择后,鼠标适配器将执行 startCapturing 方法。

GifCapturer 中的

startCapturing:

@Override
public void startCapturing(final int x, final int y, final int width, final int height) {
this.border = new GifCaptureBorder(x, y, width, height);
this.process = new TimerCaptureProcess(this, x, y, width, height);
Timer timer = new Timer();
timer.schedule(this.process, 0, 600);
}

`在 ScreenshotCapturer 中开始捕获:

@Override
public void startCapturing(int x, int y, int width, int height) {
Robot robot = super.getCamera().getRobot();
BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height));
super.disableSelectionFrame();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(image, "png", stream);
super.setCaptureResult(stream);
super.finish();
} catch (IOException e) {
e.printStackTrace();
}
}

现在在 GifCapturer 中这个过程更长了,因为它实际上启动了一个 Timer 每隔 60ms 对每一帧进行截图。

要完成捕获 gif,请单击“输入”,我使用了 JKeyMaster检测热键。点击“ENTER”后,该方法将在GifCapturer

中执行
public void createGif() {
super.disableSelectionFrame();

AnimatedGifEncoder gif = new AnimatedGifEncoder();

ByteArrayOutputStream stream = new ByteArrayOutputStream();
gif.start(stream);
gif.setDelay(1000);

this.border.updateProgress(10);

for(int i = 0; i < this.frames.size(); i++) {
gif.addFrame(this.frames.get(i));
}

this.border.updateProgress(50);

gif.finish();

super.setCaptureResult(stream);

this.border.updateProgress(100);

super.finish();
this.border.setVisible(false);
this.border = null;
}

差不多就是这样,如果我将使用 GifCapturer 两次,一切正常,但如果我将使用 ScreenshotCapturer 两次,JFrame 将不会出现在第二次时间!

我不太确定为什么,这可能是 Swing 中的错误吗?可能是因为 GifCapturer 需要更长的时间才能使框架可见?

我做错了什么?

最佳答案

好的,据我了解,您遇到的问题是这段代码...

基本上,当您调用 beginCapture 时,WiseCapturer API 允许您在屏幕上“拖动”透明矩形...

public static void main(String[] args) throws AWTException {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}

您遇到的问题是当调用 captureEnded 时(对于外部捕获),内部捕获过程没有说明(并且您不能“拖动”透明选择矩形)。 ..

这似乎是因为每当线程/事件队列 WiseCapturer 正在使用并且 captureEnded 事件不允许完成时您正在阻塞...

如果我做类似...

try {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
System.out.println("...");
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
t.start();
}
});
System.out.println("Hello");
} catch (AWTException exp) {
exp.printStackTrace();
}

在外部 captureEnded 调用中启动一个新的 Thread,我可以让它工作...

另外,不知道这个 API 的线程安全规则,我还使用了 SwingUtilities.invokeLater

try {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
b.beginCapture(new ScreenCaptureCallback() {
@Override
public void captureEnded(CapturedImage img) {
System.out.println("...");
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}
});
System.out.println("Hello");
} catch (AWTException exp) {
exp.printStackTrace();
}

成功了......我也有点奇怪你为什么要这样做,但我就是这样

关于Java JFrame 在不可见后使用 .setVisible(true) 后不会显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25067871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com