Как исчезнуть в вызове graphics.fill

Я делаю следующее с объектом Canvas.

graphics.setColor(BLUE);
graphics.fill(new Rectangle2D.Double(x, y, width, height));

Я хочу сделать цвет заливки плавным, чтобы создать плавный переход от цвета фона холста к новому цвету (и, возможно, сделать так, чтобы исходный цвет исчез).

Я играл с такими вещами (настройка состав графического объекта в AlphaComposite, который Timer обновляет значение alpha каждые n миллисекунд), но я мерцаю.

Мне интересно, какую общую концепцию мне не хватает.

Спасибо за любые указатели.


person Toby    schedule 30.07.2013    source источник
comment
Мерцание будет происходить, в основном, из источника без двойной буферизации, такого как JFrame или JApplet. Вместо этого вы должны убедиться, что 1- вы рисуете поверхность с двойной буферизацией (как и все, что простирается от JComponent) и 2- вы переопределяете метод paintComponent и вызываете super.paintComponent. Взгляните на этот пример который использует AlphaComposite и не страдает мерцанием...   -  person MadProgrammer    schedule 30.07.2013
comment
Или этот пример с различной насыщенностью.   -  person trashgod    schedule 30.07.2013
comment
I'd like to fade in the fill colour to create a smooth transition from the canvas background colour to the new colour — класс Fader делает это тогда, когда компонент получает/теряет фокус.   -  person camickr    schedule 30.07.2013
comment
Хороший совет по Fader классу, большое спасибо   -  person Toby    schedule 31.07.2013


Ответы (2)


Прежде всего, как вы могли бы использовать AWT? Это довольно устарело. Я рекомендую вам переключиться на свинг, в основном потому, что у свинг есть двойная буферизация, которая уберет ваше мерцание.

person tbodt    schedule 30.07.2013
comment
Что такое Swing-эквивалент Canvas? - person Toby; 30.07.2013
comment
В AWT нет специализированного класса рисования, поэтому вы должны использовать JPanel. И последнее замечание: НЕ ЗАМЕНЯЙТЕ paint. Если вы это сделаете, многие вещи будут работать неправильно. Вместо этого вы должны переопределить paintComponent, что вы и должны делать, и это работает. - person tbodt; 30.07.2013
comment
+1 за использование Swing, so you are supposed to use JPanel — вы бы использовали JPanel, если вам нужно пользовательское рисование и компонент, действующий как контейнер. Более общим компонентом для пользовательского рисования будет JComponent, поскольку он не имеет функциональности по умолчанию. - person camickr; 30.07.2013
comment
Помечено как правильное, как вы указали, я не использовал Swing. При переключении на JPanel автоматически применялась двойная буферизация, так что я снова счастлив. Спасибо - person Toby; 31.07.2013

Ваше приложение делает именно то, что вы ему говорите. Если вы хотите создать эффект плавного появления, вы должны определить, какие изменения цвета вы хотите произвести, создать функцию, которая это делает, и реализовать само исчезновение.

Я бы подошел к этому так:

class FadeEffect{

  int totalDurationMs;

  int elapsedDurationMs;

  Color initialColor;

  Color finalColor;

  Color getColor(int durationDelta) {
    elapsedDurationMs += durationDelta;
    if (elapsedDurationMs > totalDurationMs) {
      return finalColor;
    }
    double progress = 1.0d*elapsedDurationMs/totalDurationMs;
    return new Color( (int)(finalColor.getRed()-initialColor.getRed())*progress,
                      (int)(finalColor.getGreen()-initialColor.getGreen())*progress,
                      (int)(finalColor.getBlue()-initialColor.getBlue())*progress);
  }

  //getters, setters, etc
}

Что касается проблемы мерцания: убедитесь, что вы используете двойную буферизацию - либо в своем компоненте, либо вручную рисуя внеэкранный буфер (изображение) и выводя изображение на экран только после завершения рисования.

Вот пример кода из моего приложения Graphic2D, выполняющего двойную буферизацию:

private VolatileImage vImg;

@Override
public void paint(Graphics g) {
    if (gc==null) gc = this.getGraphicsConfiguration();
    do {
        boolean sizeChanged = false;
        sizeChanged = (vImg!=null&&(vImg.getWidth()!=getWidth()|| vImg.getHeight()!=getHeight()));
        if (vImg == null || vImg.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE
                || sizeChanged) {
            vImg = gc.createCompatibleVolatileImage(getWidth(), getHeight());
            vImg.setAccelerationPriority(1);
        }
        final Graphics gimg =  vImg.getGraphics();
        if (gimg instanceof Graphics2D) {
            renderContents((Graphics2D) gimg);
            gimg.dispose();
            g.drawImage(vImg, 0, 0, null);
        } else {
            throw new UnsupportedOperationException("Rendering impossible, graphics are not of Graphics2D class");
        }
    } while (vImg.contentsLost());
    updateAnimationNo();
}
person Dariusz    schedule 30.07.2013