java - 如何调整 Swing 进度指示器上的图形?

标签 java swing progress-bar

下面的源代码,以及图片示例,来自帖子 Circular Progress Bar for Java Swing not working ,是一个很棒的 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();
    }
}
} 

最佳答案

我发现的一个问题是代码将组合设置在循环中的错误位置。它有效,但正如您所发现的,它很难维护或更改。

g2.setComposite 在循环的末尾被调用。这将设置下一个绘制的花瓣的 alpha。这意味着您无法轻松更改第一个花瓣的 Alpha。

首先,我会让代码更符合人类的思维方式(至少是我的思维方式):在绘制之前设置要绘制的线条的 alpha:

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);
}

现在,使其适用于任何任意背景 Alpha 都很容易。我们只是调整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);
}

关于java - 如何调整 Swing 进度指示器上的图形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27710639/

相关文章:

java - 如何在 Android 中将字节数组转换为 PDF 文件?

java - ArrayList构造函数错误

java - 覆盖 getPreferredSize() 会破坏 LSP

java - Hadoop:使用自定义输入格式拆分大图像文件

使用 SQL 的 Java 登录表单

Java GUI 替代品

java - 创建用于设置 GridBagConstraints 的方法

android - 每个 gridview 项目 Android 中的进度条

jquery - 有没有办法将 jquery UI 进度条分成不同的部分并支持 > 100%?

java - 使用 Android 4.4.4 找不到可绘制资源