JPanel перекрасить не очистить - PullRequest
       14

JPanel перекрасить не очистить

3 голосов
/ 12 сентября 2011

У меня есть собственный абстрактный класс Panel, который расширяет JPanel.Существует не так много различий между двумя при рисовании.У меня есть панель, и я имитирую анимацию, обновляя значение x изображения.У меня сейчас две анимации: одна перерисовывает правильно, а другая нет.Это для того, кто этого не делает.Тот, который работает, будет помечен A, а тот, который не будет B.

A и B, следуют одному и тому же формату.Обновите некоторую переменную в Panel, вызовите update (метод в Panel, который вызывает PaintComponent), а затем вызовет repaint.Он вызывает repaint after, потому что эта проблема была с A раньше и была решена таким образом.

A: Обновляет переменную изображения.B: Обновляет переменную x изображения.

Проблема: Перекрашивание не очищает прежнее местоположение изображения, и поэтому на экране появляется беспорядочный беспорядок.

То, что я пробовал:

  • Я видел супер.PaintComponent (g) много упомянул, но это не решило проблему.
  • Я пытался изменить порядок, когдаВызываются методы перерисовки / обновления.
  • Перекрашивание вообще не обновляет Panel.(Возможно, потому что рисование выполняется в PaintComponent)

Любая помощь будет оценена.

Код:

Панель:

public Panel (boolean visible){
    super();
    this.setLayout(new BorderLayout(640, 416));//sets the Layout type of the panel
    this.setOpaque(false);//Makes it so that the panel underneath can be seen where images aren't drawn
    this.setVisible(visible);
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    gs = ge.getDefaultScreenDevice();
    gc = gs.getDefaultConfiguration();
}

public void paintComponent (Graphics g){
    setUp();
    drawOff();
    setDown(g);
}

private void setUp(){
    off_screen = gc.createCompatibleImage(getSize().width, getSize().height, Transparency.TRANSLUCENT);
    buffer = off_screen.createGraphics();
}

protected abstract void drawOff();

private void setDown(Graphics g){
    g.drawImage(off_screen,0,0,this);
    off_screen.flush(); 
}

public void update(){
    paintComponent(this.getGraphics());
}

Методы анимации (мг - рассматриваемая панель):

private void battleStart(User user) {
    for (int i = 0; i < user.battle.length; i++) {
        mg.battleStart(user.battleStart(i));
        mg.update();
        try {
            Thread.sleep(150);
        } catch (Exception e) {

        }
        mg.repaint();
    }
}

private void animateStart(User user){
    for (int i = 0; i < 10; i++){
        mg.x = mg.x + 10;
        mg.update();
        try {
            Thread.sleep(100);
        } catch (Exception e) {

        }
        mg.repaint();
    }
}

1 Ответ

3 голосов
/ 12 сентября 2011

Я думаю, что ваш дизайн далек от этого, и поэтому все не работает.Я не совсем уверен, как работают ваши неабстрактные JPanels, но рассмотрите возможность сделать вашу родительскую JPanel чем-то более похожим на это:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class MyPanel extends JPanel {
   private GraphicsEnvironment ge;
   private GraphicsDevice gs;
   private GraphicsConfiguration gc;
   private BufferedImage offScreen;

   public MyPanel(boolean visible) {
      super();
      this.setLayout(new BorderLayout(640, 416)); // strange constants for this layout.
      this.setOpaque(false);
      this.setVisible(visible);
      ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      gs = ge.getDefaultScreenDevice();
      gc = gs.getDefaultConfiguration();

      addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
            setUp();
         }
      });
   }

   @Override
   // don't make this public. Keep it protected like the super's
   // just draw in this method. Don't call other methods that create buffers
   // or draw to buffers.
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (offScreen != null) {
         g.drawImage(offScreen, 0, 0, null);
      }
   }

   private void setUp() {
      offScreen = gc.createCompatibleImage(getSize().width, getSize().height,
            Transparency.TRANSLUCENT);
   }

   // draw to the buffer outside of the paintComponent
   // and then call repaint() when done
   public void upDateOffScreen() {
      // ?? offScreen.flush(); // I've never used this before, 
                  // so am not sure if you need this here
      Graphics2D osGraphics = offScreen.createGraphics();
      // TODO: do drawing with osGraphics object here
      osGraphics.dispose();
      repaint();
   }
}

Также и снова,

  • Сделайте вседлинные методы обработки вне EDT (Thread Dispatch Thread).
  • Никогда не вызывайте Thread.sleep (...) в EDT.
  • Рассмотрите возможность использования таймеров Swing вместо использования Thread.sleep дляанимации.
  • Можно вызывать перерисовку на вашем JPanel вне EDT, но по большей части это все.
  • Все остальные методы Swing должны вызываться в EDT.
  • Читать, перечитывать и изучать учебники по 2D и Swing графике.
...