Как я могу исчезнуть или исчезнуть с помощью команды JPanel, ее компонентов и ее цвета

Я хотел создать стеклянную панель, содержащую JPanel с белым фоном, рамкой и сообщением «пожалуйста, подождите».

Вот пример кода:

JLabel glassLabel = new JLabel("Please wait");
FadingPanel msg = new FadingPanel();
glassLabel.setFont(new Font("Dialog", Font.BOLD, 26));
msg.setLayout(new BorderLayout());
msg.add(glassLabel,BorderLayout.NORTH);
msg.setBackground(Color.white);
msg.setFont(UIManager.getFont("Table.font").deriveFont(24f));   
msg.setBorder(new CompoundBorder(new TitledBorder(""),
  new EmptyBorder(20,20,20,20)));

Он будет появляться и исчезать в ожидании запроса. проблема в том, что я получаю плохой результат.

нужна помощь


person amnon    schedule 18.10.2018    source источник
comment
Я знаю, что не все они выгорают на панели, но, честно говоря, основная концепция одна и та же. Вам нужен Swing Timer, и вам нужно изменить уровень непрозрачности компонента - для этого вам придется подделать его, поскольку Swing считает компоненты либо непрозрачными, либо прозрачными, ничего между ними   -  person MadProgrammer    schedule 18.10.2018
comment
есть две проблемы со всеми этими примерами, одна из которых заключается в том, что система таймера не знает, запущена ли функция запуска, и она держит панель зависшей, потому что закрывает ее перед исчезновением панели, а затем до того, как она отображается, а затем она не пытается чтобы закрыть его снова. другое в том, что ни один из них не показывает это со стеклянной панелью   -  person amnon    schedule 18.10.2018
comment
Во-первых, что заставляет вас думать, что показывать это на стекле — это не то же самое, что показывать это где-либо еще. Во-вторых, вам нужно управлять состоянием, это предполагает, что у вас есть начальное значение и цель. Это означает, что когда целевое значение альфа равно 0, а Timer достигает нуля, можно предположить, что панель может быть удалена. Лично у меня был бы общий interface, который уведомлялся бы, когда Timer выполнил поставленную задачу, и принимал бы решения о том, что следует делать.   -  person MadProgrammer    schedule 18.10.2018
comment
Дублирование JProgressBar использует glassPane - оно просто делает это наоборот   -  person MadProgrammer    schedule 18.10.2018


Ответы (2)


другое в том, что ни один из них не показывает это со стеклянной панелью

Анимация состояния непрозрачности glassPane ничем не отличается от анимации состояния любого компонента Swing, в конце концов, glassPane — это просто еще один компонент.

во-первых, система таймера не знает, запущена ли функция запуска, и она держит панель висящей, потому что она закрывает ее перед исчезновением панели, а затем до того, как она отображается, и затем она не пытается закрыть ее снова

Это больше касается вашего собственного внутреннего управления состоянием. Панель не должна волноваться, она должна просто отвечать на запрос об изменении уровня непрозрачности, вперед или назад.

Что у вас должно быть, так это своего рода «движок», который может обеспечивать события при достижении определенных состояний, и в это время вы принимаете решения о том, что следует делать, удаляя функциональность из самой «панели».

Теория TL;DR

Ладно, сначала немного теории.

Анимация...

Анимация — это иллюзия изменения во времени. В вашем случае вы переходите от 0 к 1 и обратно в течение определенного периода времени. Это широко известно как «линейная прогрессия/анимация». Большинство наивных реализаций анимации просто добавляют постоянную дельту к значению и продолжают делать это до тех пор, пока не будет достигнуто желаемое состояние. Это наивно, потому что не все системы равны. Некоторые смогут достичь желаемого состояния быстрее, чем другие, что сделает анимацию неравномерной и ухудшит взаимодействие с пользователем.

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

Этот подход намного мощнее, так как позволяет очень просто поиграть со скоростью анимации. Это также позволяет вам выполнять некоторые очень сложные операции, такие как сервитут, которые было бы нелегко выполнить с помощью линейной прогрессии.

Качели и анимация...

Качели однозаходные. Это означает, что вы не можете выполнять блокирующие или длительные операции в контексте потока диспетчеризации событий.

Swing также НЕ является потокобезопасным. Это означает, что вы не должны обновлять пользовательский интерфейс (или любое состояние, от которого зависит пользовательский интерфейс) вне контекста EDT.

Что касается анимации, то вам нужен какой-то способ быстрой публикации повторяющихся событий в EDT, что позволит вам безопасно вносить изменения в пользовательский интерфейс. Для этого наиболее распространенным инструментом является Swing Timer...

Рамки

Итак, исходя из этого, нам нужен какой-то «движок», который с учетом «диапазона» и «длительности» может уведомлять об использовании «тиков» на регулярной основе, из которой мы можем вычислить прогрессию, которую воспроизвела анимация. , и вычислить значение, которое мы должны использовать на основе наших входных данных... просто...

Я лично предпочитаю использовать библиотеку анимации, но простая структура, представленная в примерах, в основном абстрагирует все эти концепции в повторно используемую структуру.

Сделай это так...

примечание: у меня не хватило места, поэтому основная структура включена в основной пример

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

Теперь нам нужен компонент, который может его использовать, что-то вроде...

public interface FaderListener {
    public void fadeDidComplete(FadePane pane);
}

public class FadePane extends JPanel {

    private double alpha = 1;
    private boolean fadingIn = true;
    private DoubleAnimatable animatable;
    private Duration duration = Duration.ofSeconds(5);
    private List<FaderListener> listeners = new ArrayList<>(5);

    public FadePane() {
        setOpaque(false);
    }

    public void addFadeListener(FaderListener listener) {
        listeners.add(listener);
    }

    public void removeFadeListener(FaderListener listener) {
        listeners.remove(listener);
    }

    public boolean isFadingIn() {
        return fadingIn;
    }

    public double getAlpha() {
        return alpha;
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setComposite(AlphaComposite.SrcOver.derive((float)getAlpha()));
        g2d.setColor(getBackground());
        g2d.fillRect(0, 0, getWidth(), getHeight());
        super.paint(g2d);
        g2d.dispose();
    }

    protected void fadeTo(double to) {
        double currentAlpha = getAlpha();
        if (animatable != null) {
            animatable.stop();
            animatable = null;
        }

        if (currentAlpha == to) {
            fadeDidComplete();
            return;
        }

        DoubleRange animationRange = new DoubleRange(currentAlpha, to);
        double maxFrom = to == 1 ? 1 : 0;
        double maxTo = to == 1 ? 0 : 1;
        DoubleRange maxRange = new DoubleRange(maxFrom, maxTo);

        animatable = new DoubleAnimatable(animationRange, maxRange, duration, new AnimatableListener<Double>() {
            @Override
            public void animationChanged(Animatable<Double> animatable) {
                alpha = animatable.getValue();
                repaint();
            }
        }, new AnimatableLifeCycleListenerAdapter<Double>() {
            @Override
            public void animationCompleted(Animatable<Double> animatable) {
                fadeDidComplete();
            }
        });

        Animator.INSTANCE.add(animatable);
    }

    public void fadeIn() {
        fadingIn = true;
        fadeTo(1);
    }

    public void fadeOut() {
        fadingIn = false;
        fadeTo(0);
    }

    protected void fadeDidComplete() {            
        for (FaderListener listener : listeners) {
            listener.fadeDidComplete(this);
        }
    }

}

Хорошо, это довольно простая концепция. Это JPanel, у которого есть свойство alpha, которое изменяет уровень непрозрачности компонента - по сути, все это подделка, поскольку Swing поддерживает только непрозрачные и прозрачные компоненты, а не полупрозрачные компоненты. Поэтому мы делаем компонент прозрачным и вручную рисуем фон.

Компонент предоставляет два метода, fadeIn и fadeOut, и поддерживает FaderListener, который можно использовать для уведомления заинтересованных сторон о завершении операции затухания.

Запускаемый пример...

Исчезновение

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setBackground(Color.RED);
            setLayout(new BorderLayout());

            FadePane pane = new FadePane();
            pane.setLayout(new GridBagLayout());
            pane.add(new JLabel("Look ma, no hands"));

            add(pane);

            JButton btn = new JButton("Switch");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    if (pane.isFadingIn()) {
                        pane.fadeOut();
                    } else {
                        pane.fadeIn();
                    }
                }
            });
            add(btn, BorderLayout.SOUTH);

            pane.addFadeListener(new FaderListener() {
                @Override
                public void fadeDidComplete(FadePane pane) {
                    btn.setEnabled(true);
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public interface FaderListener {
        public void fadeDidComplete(FadePane pane);
    }

    public class FadePane extends JPanel {

        private double alpha = 1;
        private boolean fadingIn = true;
        private DoubleAnimatable animatable;
        private Duration duration = Duration.ofSeconds(5);
        private List<FaderListener> listeners = new ArrayList<>(5);

        public FadePane() {
            setOpaque(false);
        }

        public void addFadeListener(FaderListener listener) {
            listeners.add(listener);
        }

        public void removeFadeListener(FaderListener listener) {
            listeners.remove(listener);
        }

        public boolean isFadingIn() {
            return fadingIn;
        }

        public double getAlpha() {
            return alpha;
        }

        public void setFaddedOut() {
            alpha = 0;
            fadingIn = false;
        }

        public void setFaddedIn() {
            alpha = 1;
            fadingIn = true;
        }

        @Override
        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive((float)getAlpha()));
            g2d.setColor(getBackground());
            g2d.fillRect(0, 0, getWidth(), getHeight());
            super.paint(g2d);
            g2d.dispose();
        }

        protected void fadeTo(double to) {
            double currentAlpha = getAlpha();
            if (animatable != null) {
                animatable.stop();
                animatable = null;
            }

            if (currentAlpha == to) {
                fadeDidComplete();
                return;
            }

            DoubleRange animationRange = new DoubleRange(currentAlpha, to);
            double maxFrom = to == 1 ? 1 : 0;
            double maxTo = to == 1 ? 0 : 1;
            DoubleRange maxRange = new DoubleRange(maxFrom, maxTo);

            animatable = new DoubleAnimatable(animationRange, maxRange, duration, new AnimatableListener<Double>() {
                @Override
                public void animationChanged(Animatable<Double> animatable) {
                    alpha = animatable.getValue();
                    repaint();
                }
            }, new AnimatableLifeCycleListenerAdapter<Double>() {
                @Override
                public void animationCompleted(Animatable<Double> animatable) {
                    fadeDidComplete();
                }
            });

            Animator.INSTANCE.add(animatable);
        }

        public void fadeIn() {
            fadingIn = true;
            fadeTo(1);
        }

        public void fadeOut() {
            fadingIn = false;
            fadeTo(0);
        }

        protected void fadeDidComplete() {            
            for (FaderListener listener : listeners) {
                listener.fadeDidComplete(this);
            }
        }

    }

    public class DoubleAnimatable extends AbstractAnimatable<Double> {

        public DoubleAnimatable(DoubleRange animationRange, DoubleRange maxRange, Duration duration, AnimatableListener<Double> listener, AnimatableLifeCycleListener<Double> lifeCycleListener) {
            super(animationRange, duration, listener, lifeCycleListener);

            double maxDistance = maxRange.getDistance();
            double aniDistance = animationRange.getDistance();

            double progress = Math.min(100, Math.max(0, Math.abs(aniDistance / maxDistance)));
            Duration remainingDuration = Duration.ofMillis((long) (duration.toMillis() * progress));
            setDuration(remainingDuration);
        }

    }

    public interface AnimatableListener<T> {
        public void animationChanged(Animatable<T> animatable);
    }

    public interface AnimatableLifeCycleListener<T> {
        public void animationStopped(Animatable<T> animatable);
        public void animationCompleted(Animatable<T> animatable);
        public void animationStarted(Animatable<T> animatable);
        public void animationPaused(Animatable<T> animatable);        
    }

    public class AnimatableLifeCycleListenerAdapter<T> implements AnimatableLifeCycleListener<T> {

        @Override
        public void animationStopped(Animatable<T> animatable) {
        }

        @Override
        public void animationCompleted(Animatable<T> animatable) {
        }

        @Override
        public void animationStarted(Animatable<T> animatable) {
        }

        @Override
        public void animationPaused(Animatable<T> animatable) {
        }

    }

    public abstract class AbstractAnimatable<T> implements Animatable<T> {

        private Range<T> range;
        private LocalDateTime startTime;
        private Duration duration = Duration.ofSeconds(5);
        private T value;
        private AnimatableListener<T> animatableListener;
        private AnimatableLifeCycleListener<T> lifeCycleListener;
//        private Easement easement;
        private double rawOffset;

        public AbstractAnimatable(Range<T> range, Duration duration, AnimatableListener<T> listener) {
            this.range = range;
            this.value = range.getFrom();
            this.animatableListener = listener;
        }

        public AbstractAnimatable(Range<T> range, Duration duration, AnimatableListener<T> listener, AnimatableLifeCycleListener<T> lifeCycleListener) {
            this(range, duration, listener);
            this.lifeCycleListener = lifeCycleListener;
        }

//        public AbstractAnimatable(Range<T> range, Duration duration, Easement easement, AnimatableListener<T> listener) {
//            this(range, duration, listener);
//            this.easement = easement;
//        }
//
//        public AbstractAnimatable(Range<T> range, Duration duration, Easement easement, AnimatableListener<T> listener, AnimatableLifeCycleListener<T> lifeCycleListener) {
//            this(range, duration, easement, listener);
//            this.lifeCycleListener = lifeCycleListener;
//        }
//
//        public void setEasement(Easement easement) {
//            this.easement = easement;
//        }
//
//        @Override
//        public Easement getEasement() {
//            return easement;
//        }

        public Duration getDuration() {
            return duration;
        }

        public Range<T> getRange() {
            return range;
        }

        public void setRange(Range<T> range) {
            this.range = range;
        }

        @Override
        public T getValue() {
            return value;
        }

        protected void setDuration(Duration duration) {
            this.duration = duration;
        }

        public double getCurrentProgress(double rawProgress) {
            double progress = Math.min(1.0, Math.max(0.0, getRawProgress()));
//            Easement easement = getEasement();
//            if (easement != null) {
//                progress = easement.interpolate(progress);
//            }
            return Math.min(1.0, Math.max(0.0, progress));
        }

        public double getRawProgress() {
            if (startTime == null) {
                return 0.0;
            }
            Duration duration = getDuration();
            Duration runningTime = Duration.between(startTime, LocalDateTime.now());
            double progress = rawOffset + (runningTime.toMillis() / (double) duration.toMillis());

            return Math.min(1.0, Math.max(0.0, progress));
        }

        @Override
        public void tick() {
            if (startTime == null) {
                startTime = LocalDateTime.now();
                fireAnimationStarted();
            }
            double rawProgress = getRawProgress();
            double progress = getCurrentProgress(rawProgress);
            if (rawProgress >= 1.0) {
                progress = 1.0;
            }
            value = getRange().valueAt(progress);
            fireAnimationChanged();
            if (rawProgress >= 1.0) {
                fireAnimationCompleted();
            }
        }

        @Override
        public void start() {
            if (startTime != null) {
                // Restart?
                return;
            }
            Animator.INSTANCE.add(this);
        }

        @Override
        public void stop() {
            stopWithNotification(true);
        }

        @Override
        public void pause() {
            rawOffset += getRawProgress();
            stopWithNotification(false);

            double remainingProgress = 1.0 - rawOffset;
            Duration remainingTime = getDuration().minusMillis((long) remainingProgress);
            setDuration(remainingTime);

            lifeCycleListener.animationStopped(this);
        }

        protected void fireAnimationChanged() {
            if (animatableListener == null) {
                return;
            }
            animatableListener.animationChanged(this);
        }

        protected void fireAnimationCompleted() {
            stopWithNotification(false);
            if (lifeCycleListener == null) {
                return;
            }
            lifeCycleListener.animationCompleted(this);
        }

        protected void fireAnimationStarted() {
            if (lifeCycleListener == null) {
                return;
            }
            lifeCycleListener.animationStarted(this);
        }

        protected void fireAnimationPaused() {
            if (lifeCycleListener == null) {
                return;
            }
            lifeCycleListener.animationPaused(this);
        }

        protected void stopWithNotification(boolean notify) {
            Animator.INSTANCE.remove(this);
            startTime = null;
            if (notify) {
                if (lifeCycleListener == null) {
                    return;
                }
                lifeCycleListener.animationStopped(this);
            }
        }

    }

    public interface Animatable<T> {

        public Range<T> getRange();

        public T getValue();

        public void tick();

        public Duration getDuration();

        //public Easement getEasement();

        // Wondering if these should be part of a secondary interface
        // Provide a "self managed" unit of work
        public void start();

        public void stop();

        public void pause();
    }

    public abstract class Range<T> {

        private T from;
        private T to;

        public Range(T from, T to) {
            this.from = from;
            this.to = to;
        }

        public T getFrom() {
            return from;
        }

        public T getTo() {
            return to;
        }

        @Override
        public String toString() {
            return "From " + getFrom() + " to " + getTo();
        }

        public abstract T valueAt(double progress);

    }

    public class DoubleRange extends Range<Double> {

        public DoubleRange(Double from, Double to) {
            super(from, to);
        }

        public Double getDistance() {
            return getTo() - getFrom();
        }

        @Override
        public Double valueAt(double progress) {
            double distance = getDistance();
            double value = distance * progress;
            value += getFrom();
            return value;
        }
    }

    public enum Animator {
        INSTANCE;
        private Timer timer;
        private List<Animatable> properies;

        private Animator() {
            properies = new ArrayList<>(5);
            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    List<Animatable> copy = new ArrayList<>(properies);
                    Iterator<Animatable> it = copy.iterator();
                    while (it.hasNext()) {
                        Animatable ap = it.next();
                        ap.tick();
                    }
                    if (properies.isEmpty()) {
                        timer.stop();
                    }
                }
            });
        }

        public void add(Animatable ap) {
            properies.add(ap);
            timer.start();
        }

        protected void removeAll(List<Animatable> completed) {
            properies.removeAll(completed);
        }

        public void remove(Animatable ap) {
            properies.remove(ap);
            if (properies.isEmpty()) {
                timer.stop();
            }
        }

    }

}

Но это не glassPane

... хорошо, как я уже сказал, glassPane - это просто еще один компонент

Это простой пример, в котором используется glassPane фрейма, и когда панель исчезает, glassPane сбрасывается на компонент по умолчанию.

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());

            JButton btn = new JButton("Switch");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Window window = SwingUtilities.getWindowAncestor(TestPane.this);
                    if (!(window instanceof JFrame)) {
                        System.out.println("Not out frame");
                        return;
                    }
                    JFrame frame = (JFrame) window;
                    FadePane pane = new FadePane();
                    pane.setLayout(new BorderLayout());
                    pane.add(new JLabel("All your base are belong to us"));
                    pane.setFaddedOut();
                    pane.addFadeListener(new FaderListener() {
                        @Override
                        public void fadeDidComplete(FadePane pane) {
                            System.out.println("Completed");
                            if (pane.getAlpha() == 1) {
                                System.out.println("Fade out");
                                pane.fadeOut();
                            } else {
                                System.out.println("Remove glasspane");
                                frame.setGlassPane(new JPanel());
                            }
                        }
                    });
                    frame.setGlassPane(pane);
                    System.out.println("Fade in");
                    pane.setVisible(true);
                    pane.fadeIn();
                }
            });
            add(btn);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

Примечание: необходимые классы указаны в предыдущем примере

person MadProgrammer    schedule 18.10.2018
comment
ДА !!!!!! это то что я искал!!!!! спасибо MadProgrammer - person amnon; 27.10.2018

Рассмотрите возможность использования контейнера JDialog. Когда он не украшен вы можете изменить его непрозрачность :

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;


public class FadeDialog extends JDialog  {

    private float alfa = 1;
    private JLabel label;
    private boolean isFadeIn = true;
    private JButton fadeIn, fadeOut;

    FadeDialog() {

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setLocation(new Point(300, 300));
        getContentPane().setLayout(new BorderLayout(5,0));
        setUndecorated(true); //opacity supported for undecorated JDialogs

        JButton close = new JButton("Close");
        close.addActionListener(e -> dispose());
        getContentPane().add(close, BorderLayout.PAGE_END);
        getContentPane().add(new ContentPane(), BorderLayout.CENTER);
        pack();
        setVisible(true);

        Timer timer = new Timer(2000,  e -> fade());//endless fade-in-out loop
        timer.setInitialDelay(100);
        timer.start();
    }

    void fade() {

        alfa = isFadeIn ? alfa + 0.1f : alfa -0.1f;
        if(alfa <=0 ) {
            alfa = 0; isFadeIn = true;
        }else if(alfa >= 1) {
            alfa = 1; isFadeIn = false;
        }

        fadeIn.setEnabled(! isFadeIn); fadeOut.setEnabled(isFadeIn);
        label.setText("Alfa is " + alfa);
        setOpacity(alfa); //set JDialog opacity
    }

    class ContentPane extends JPanel {

        ContentPane() {
            setPreferredSize(new Dimension(200, 100));
            setLayout(new BorderLayout());
            fadeIn = new JButton("Fade In");
            fadeIn.addActionListener(e -> isFadeIn = true);
            add(fadeIn, BorderLayout.PAGE_START);

            label = new JLabel("Alfa is " + alfa);
            add(label, BorderLayout.CENTER);

            fadeOut = new JButton("Fade Out");
            fadeOut.addActionListener(e -> isFadeIn = false);
            add(fadeOut, BorderLayout.PAGE_END);
        }
    }

    public static void main(String[] args) {
        new FadeDialog();
    }
}
person c0der    schedule 18.10.2018