Arhn - архитектура программирования

Как настроить графику на индикаторе прогресса Swing?

Нижний исходный код с изображенным примером из сообщения Круговой индикатор выполнения для Java Swing не работает — отличный Swing особенность.

Я хотел бы иметь возможность использовать его с «прозрачной» JFrame или стеклянной панелью, но графические «лепестки» в paint() хотят взаимодействовать с фоном, поэтому, если непрозрачность фона очень низкая, вы еле видны "лепестки". Не будучи знакомым с функциями Graphics2D, я предпринял много ударов в темноте, пытаясь настроить код, но безуспешно, поэтому мог бы кто-нибудь, кто знает, как работают эти функции, предложить изменения, чтобы «лепестки» не взаимодействовать с фоном и начинать с сплошного белого цвета, а затем постепенно исчезать, как это делает код?

Мне также не нужны никакие задержки появления или исчезновения, и у меня тоже есть трудности с этим, но если бы кто-то мог просто предложить модификации для «лепестков», это было бы здорово!

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;

public class Loading_Test {

static final WaitLayerUI layerUI = new WaitLayerUI();
JFrame frame = new JFrame("JLayer With Animated Gif");

public Loading_Test() {
    JPanel panel = new JPanel() {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 300);
        }
    };
    JLayer<JPanel> jlayer = new JLayer<>(panel, layerUI);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(jlayer);
    frame.pack();
    frame.setVisible(true);
    layerUI.start();
}

public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            Loading_Test loading_Test = new Loading_Test();

        }
    });
}
}

class WaitLayerUI extends LayerUI<JPanel> implements ActionListener {

private boolean mIsRunning;
private boolean mIsFadingOut;
private Timer mTimer;
private int mAngle;
private int mFadeCount;
private int mFadeLimit = 15;

@Override
public void paint(Graphics g, JComponent c) {
    int w = c.getWidth();
    int h = c.getHeight();
    super.paint(g, c); // Paint the view.
    if (!mIsRunning) {
        return;
    }
    Graphics2D g2 = (Graphics2D) g.create();
    float fade = (float) mFadeCount / (float) mFadeLimit;
    Composite urComposite = g2.getComposite(); // Gray it out.
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f * fade));
    g2.fillRect(0, 0, w, h);
    g2.setComposite(urComposite);
    int s = Math.min(w, h) / 5;// Paint the wait indicator.
    int cx = w / 2;
    int cy = h / 2;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    g2.setPaint(Color.white);
    g2.rotate(Math.PI * mAngle / 180, cx, cy);
    for (int i = 0; i < 12; i++) {
        float scale = (11.0f - (float) i) / 11.0f;
        g2.drawLine(cx + s, cy, cx + s * 2, cy);
        g2.rotate(-Math.PI / 6, cx, cy);
        g2.setComposite(AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, scale * fade));
    }
    g2.dispose();
}

@Override
public void actionPerformed(ActionEvent e) {
    if (mIsRunning) {
        firePropertyChange("tick", 0, 1);
        mAngle += 3;
        if (mAngle >= 360) {
            mAngle = 0;
        }
        if (mIsFadingOut) {
            if (--mFadeCount == 0) {
                mIsRunning = false;
                mTimer.stop();
            }
        } else if (mFadeCount < mFadeLimit) {
            mFadeCount++;
        }
    }
}

public void start() {
    if (mIsRunning) {
        return;
    }
    mIsRunning = true;// Run a thread for animation.
    mIsFadingOut = false;
    mFadeCount = 0;
    int fps = 24;
    int tick = 1000 / fps;
    mTimer = new Timer(tick, this);
    mTimer.start();
}

public void stop() {
    mIsFadingOut = true;
}

@Override
public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
    if ("tick".equals(pce.getPropertyName())) {
        l.repaint();
    }
}
} 
30.12.2014

  • Вы спрашиваете, как заставить этот код работать с полупрозрачным компонентом (то есть отображать его содержимое с альфа-каналом от 0 до 1)? 30.12.2014
  • Довольно много. Я могу сказать, что инструкции, связанные с Composite, в paint() взаимодействуют с пунктом назначения, фоном, и я хочу, чтобы индикатор Progress отображался красиво. Кроме того, я видел упоминание JXBusyLabel, но я бы предпочел использовать этот гораздо более короткий код. 31.12.2014

Ответы:


1

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

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

Во-первых, я бы сделал код более соответствующим человеческому мышлению (по крайней мере, моему мышлению): установите альфа-канал линии, которую вы собираетесь нарисовать, прямо перед тем, как вы ее нарисуете:

for (int i = 0; i < 12; i++) {
    float scale = (12 - i) / 12f;
    g2.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, scale * fade));
    g2.drawLine(cx + s, cy, cx + s * 2, cy);
    g2.rotate(-Math.PI / 6, cx, cy);
}

Теперь заставить его работать с любой произвольной фоновой альфой несложно. Мы просто корректируем значение scale:

float componentAlpha = 0.5f;

for (int i = 0; i < 12; i++) {
    float scale = (12 - i) / 12f;

    // Give petals the same relative alpha as the component
    // they're overlaying.
    scale *= componentAlpha;   

    g2.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, scale * fade));
    g2.drawLine(cx + s, cy, cx + s * 2, cy);
    g2.rotate(-Math.PI / 6, cx, cy);
}
30.12.2014
  • Большое спасибо! Если кому-то интересно, исходный код Taptaptap.java взят отсюда: liafa.jussieu.fr/~yunes/cours/annexes/java/docs/tutorial/ 31.12.2014
  • плюс один, но я уверен, что здесь есть несколько отличных примеров кода от @aterai 01.01.2015
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..