Окрашенный контент невидим при изменении размера в Java
Обратите внимание, что я не проверял это на Windows-машине только на Mac-машине. Я не уверен, происходит ли это также на Windows-машине...
Когда я изменяю размеры моего Java-приложения, контент становится невидимым. Я уже нашел способ исправить это после изменения его размера, но не тогда, когда пользователь изменяет размер окна.
Я не использую Swing или что-то еще, потому что это делает мой бинарный файл настолько медленным (по моему мнению).
Структура выглядит так:
Frame
Мое главное окноContaine
r Содержание просмотраmain-window
Container
на основе подпредставлений, в том числеpaint(Graphics g)
-метод
Я добавил всех слушателей My main-window
и теперь я могу перерисовать Content-view после изменения размера окна.
public void componentResized(ComponentEvent e) {
this.contentView.paint(this.contentView.getGraphics());
}
Я остерегаюсь того факта, что использую paint(getGraphics())
-метод не очень хороший способ сделать это, но так как repaint()
-метод вообще ничего не делает, это единственная работающая возможность.
При изменении размера весь нарисованный контент становится невидимым. Тем не менее, когда я добавляю Button
-экземпляр к моему Content-view
и изменить размер моего Main-window
кнопка не становится невидимой.
Я могу отследить событие "live" -izeize:
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
}
- Когда я начинаю изменять размер, этот метод не вызывается.
- При изменении размера он генерирует "Live-resize" в моем журнале каждый пиксель, который я изменяю размер окна.
- Когда я прекращаю изменять размер, этот метод не вызывается, метод componentResized делает.
Когда я добавляю свой repaint-метод (или официальный repaint-метод) в событие live-resize, как это, я все равно получаю вывод, однако это не перерисовка или что-то в этом роде.
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
this.contentView.paint(this.contentView.getGraphics());
}
Или же
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
this.contentView.repaint();
}
Когда я минимизирую свое приложение до дока и снова максимизирую приложение, происходит то же самое, я предполагаю, что тот же код необходим, чтобы это исправить.
Я не пользуюсь Graphics2D
или что-то, просто Graphics
,
Не могли бы вы объяснить мне, как я могу перекрасить взгляды?
Заранее спасибо Тим
3 ответа
Хорошо, я наконец исправил это.
Вместо того, чтобы перерисовывать его каждый раз в paint(Graphics g)
-метод, вам нужно буферизовать вывод и перерисовать только это изображение (я надеялся, что Java уже будет делать это, точно так же, как Obj-C).
public BufferedImage buffer;
public void redraw() {
buffer = new BufferedImage(
200, // height
300, // width
BufferedImage.TYPE_4BYTE_ABGR); // ABGR = RGBA, 4-byte (r, g, b, a) per pixel
Graphics g = buffer.getGraphics();
// do your drawing here
if (this.getGraphics()) {
// 'this' is already shown, so it needs a redraw
this.paint(this.getGraphics()); // little hack
}
}
public void update(Graphics g) {
this.paint(g);
}
public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, this);
}
Теперь, когда вы свернете окно и снова развернете его, картины останутся. Только окно сейчас мигает в течение 0,1 секунды или около того, но меня это не особо волнует.
Для справки, здесь та же программа, использующая Swing. Так как JPanel
имеет двойную буферизацию, он не мерцает, когда мышь освобождается после изменения размера.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class SwingPaint {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new CirclePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static class CirclePanel extends JPanel {
private static final Random r = new Random();
public CirclePanel() {
this.setPreferredSize(new Dimension(320, 240));
this.setForeground(new Color(r.nextInt()));
this.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
CirclePanel.this.update();
}
});
}
public void update() {
this.setForeground(new Color(r.nextInt()));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}
Я больше знаком с Swing, но в статье " Живопись в AWT" и "Swing" проводится различие между системной и прикладной живописью. Пример ниже показывает, как система вызывает paint()
при изменении размера окна, в то время как приложение вызывает repaint()
, который вызывает update()
, в ответ на событие мыши. Поведение кроссплатформенное.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class AWTPaint {
public static void main(String[] args) {
Frame frame = new Frame();
frame.add(new CirclePanel());
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
private static class CirclePanel extends Panel {
private static final Random r = new Random();
public CirclePanel() {
this.setPreferredSize(new Dimension(320, 240));
this.setForeground(new Color(r.nextInt()));
this.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
CirclePanel.this.repaint();
}
});
}
@Override
public void update(Graphics g) {
this.setForeground(new Color(r.nextInt()));
}
@Override
public void paint(Graphics g) {
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}