После дня отсутствия предлагаемых решений я начал думать, что Java Graphics не может стереть отдельные элементы обратно в прозрачный цвет.Но оказывается, что улучшенная Graphics2D, вместе с BufferedImage и AlphaComposite, обеспечивают в значительной степени именно ту функциональность, которую я искал, позволяя мне как рисовать фигуры, так и стирать фигуры (обратно до полной прозрачности) в различных слоях.
Теперь я делаю в start () следующее:
screenBuffer = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
screenBufferGraphics = screenBuffer.createGraphics();
overlayBuffer = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
overlayBufferGraphics = overlayBuffer.createGraphics();
Я должен использовать new BufferedImage()
вместо createImage()
, потому что мне нужно запросить альфа.(Даже для screenBuffer, хотя это фон - иди на фигуру!) Я использую createGraphics()
вместо getGraphics()
только потому, что моя переменная screenBufferGraphics теперь является объектом Graphics2D, а не просто объектом Graphics.(Хотя приведение вперед и назад тоже работает нормально.)
Код в paint () почти не отличается:
g.drawImage(screenBuffer, 0, 0, null);
g.drawImage(overlayBuffer, 0, 0, null);
И объекты отображаются (или стираются) следующим образом:
// render to background
screenBufferGraphics.setColor(Color.red);
screenBufferGraphics.fillOval(80,80, 40,40);
// render to overlay
overlayBufferGraphics.setComposite(AlphaComposite.SrcOver);
overlayBufferGraphics.setColor(Color.green);
overlayBufferGraphics.fillOval(90,70, 20,60);
// render invisibility onto overlay
overlayBufferGraphics.setComposite(AlphaComposite.DstOut);
overlayBufferGraphics.setColor(Color.blue);
overlayBufferGraphics.fillOval(70,90, 30,20);
// and flush just this locally changed region
repaint(60,60, 80,80);
Конечный Color.blue дает прозрачность, а не синеву - это может быть любой цвет, который не имеет прозрачности.
В качестве заключительного замечания, если вы выполняете рендеринг в потоке, отличном от AWT- Поток EventQueue (которым вы, вероятно, являетесь, если вы тратите много времени на рендеринг, но также должны иметь адаптивный интерфейс), тогда вы захотите синхронизировать приведенный выше код в paint () с вашей процедурой рендеринга;в противном случае дисплей может оказаться в полусрисованном состоянии.
Если вы выполняете рендеринг в более чем одном потоке, вам все равно нужно будет синхронизировать процедуру рендеринга, чтобы изменения состояния Graphics2D не мешали друг другу.,(Или, может быть, каждый поток может иметь свой собственный объект Graphics2D, рисующий на одном и том же BufferedImage - я этого не пробовал.)
Это выглядит так просто, что трудно поверить, сколько времени понадобилось, чтобы понять, каксделай это!