Прежде чем вы прочитаете, это будет информативным: Java JFrame не появится после использования.setVisible(true) после невидимости
Здравствуйте, я работаю над библиотечным 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, не входит в приложение, просто используется для использования в качестве примера).
Процесс захвата изображения.
Шаг 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
(abstract)
@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
Пользователь выбирает область, и слушатели мыши и мыши прислушиваются к ней (см. Движение мыши):
@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, width, height от камеры выбора и передает его классу захватчика, который использует Robot для получения снимка экрана с этим прямоугольником, и до этого он удаляет ВСЕ компоненты из содержимого панели, и перерисовывает все, а затем устанавливает видимость в 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
Заранее спасибо.
Основываясь на этом примере...
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();
}
Я не буду сосредотачиваться на начальной стадии первого раунда, я сосредоточусь на инициализации второго раунда, поскольку именно здесь проблема...
b.beginCapture
вызовите this.capturer.beginSelection();
, который вызывает super.getCamera().startSelection();
который вызывает setVisible(true)
(CaptureCamera
был JFrame
).
Это немедленно покажет, что когда-либо было показано на CaptureCamera
. Здесь важно отметить, что никаких новых экземпляров объектов в процессе не было создано...
Теперь я сделал много изменений в базовом тестировании, но, похоже, проблема заключается в восстановлении кадра, когда он стал видимым во второй раз. Это, похоже, проблема с поддержкой прозрачности окна, поскольку, похоже, оно восстанавливает последнее "известное" состояние, а не сразу перерисовывает окно...
Теперь я попробовал очистить selector
прежде чем сделать CaptureCamera
невидимым без eval, поскольку окно кажется невидимым перед тем, как selector
будет нарисован.
Окончательное решение, которое я придумал было назвать dispose
на CaptureCamera
, который выпускает его родной сверстников и, следовательно, разрушает старые графический контекст, заставляя кадр, чтобы восстановить себя, когда он становится видимым снова.
"Проблема" с этим может заключаться в том, что когда все окна расположены (и только бегущие потоки - потоки демона), JVM выйдет из...
Это было проблемой во время моего тестирования, поскольку я использовал javax.swing.Timer
для задержки между первым и вторым процессом захвата, чтобы я мог видеть, где возникла проблема, и это вызвало выход моей JVM (поскольку таймер использует демона, и у меня не было других открытых окон).
Я обошел это, создав крошечное (1x1) прозрачное окно в классе Capturer
, помните об этом, если JVM существует изящно без причины;)
Теперь есть проблема с SelectionCamera
(которая расширяет JPanel
), она непрозрачна, но использует прозрачный фон, это невероятно опасно, поскольку Swing знает, как бороться с непрозрачными или полностью прозрачными компонентами.
public SelectionCamera() {
super.setBackground(new Color(0, 0, 0, 0));
super.setVisible(false);
}
Должно быть обновлено до чего-то вроде...
public SelectionCamera() {
setOpaque(false);
//super.setBackground(new Color(0, 0, 0, 0));
super.setVisible(false);
}
Я также запутался в использовании super.xxx
, единственной причиной, по которой вы это сделаете, является то, что вы переопределили эти методы и не хотели называть их в это время... В ходе тестирования я удалил все вызовы для super
где метод не был переопределен в текущем классе (и я еще не был в методе overriden)
Кроме того, метод paintComponent
должен быть super.paintComponent
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0, 0, 0, 0.5f));
g.fillRect(this.x, this.y, this.width, this.height);
}
Сделайте Frame оставшимся для -10, 000, затем установите видимое значение true, добавьте таймер 2 секунды (попробуйте уменьшить значение до 25 -10 0 миллисекунд, чтобы дать ему sligth pause для аннулирования содержимого), по таймеру: слева до 0. Я думаю, что это работает из-за кеширования и двойного буферизации. Кадр показывает, что у него было в буфере, буфер указывает на старое изображение из-за кэширования/ленивой перерисовки.
Альтернатива: Возможно, перерисовка или недействительность до того, как ваше шоу тоже будет работать, и не нужно делать левые -10, 000. Я не очень много работаю с ui-swing, всего лишь несколько лет назад и помню некоторые странные вещи, подобные этому.
selector
должен быть сброшен ... может быть ... Вы также можете выделить ваш код и код из библиотеки захвата ...