我使用Nimbus look& amp;编程Java应用程序感觉。不幸的是,Nimbus的不确定JProgressBars外观和外观。感觉是 AWFUL (见下文):
另一方面,我注意到Netbeans的Nimbus外观&感觉有一个不同的不确定的JProgressBar风格,看起来好多了(见下文):
如何在我自己的应用程序中使用此样式?
答案 0 :(得分:3)
您可以自己编写Painter<JComponent>
:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.nimbus.*;
public final class IndeterminateStyleTest {
private final BoundedRangeModel model = new DefaultBoundedRangeModel();
public JComponent makeUI() {
JProgressBar progressBar0 = new JProgressBar(model);
UIDefaults d = new UIDefaults();
d.put("ProgressBar[Enabled+Indeterminate].foregroundPainter", new IndeterminateRegionPainter());
JProgressBar progressBar1 = new JProgressBar(model);
progressBar1.putClientProperty("Nimbus.Overrides", d);
progressBar0.setIndeterminate(true);
progressBar1.setIndeterminate(true);
JPanel p = new JPanel();
p.setBorder(BorderFactory.createEmptyBorder(32, 5, 32, 5));
p.add(progressBar0);
p.add(progressBar1);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new IndeterminateStyleTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class IndeterminateRegionPainter extends AbstractRegionPainter {
// Copied from javax.swing.plaf.nimbus.ProgressBarPainter.java
private Color color17 = decodeColor("nimbusOrange", .0f, .0f, .0f, -156);
private Color color18 = decodeColor("nimbusOrange", -.015796512f, .02094239f, -.15294117f, 0);
private Color color19 = decodeColor("nimbusOrange", -.004321605f, .02094239f, -.0745098f, 0);
private Color color20 = decodeColor("nimbusOrange", -.008021399f, .02094239f, -.10196078f, 0);
private Color color21 = decodeColor("nimbusOrange", -.011706904f, -.1790576f, -.02352941f, 0);
private Color color22 = decodeColor("nimbusOrange", -.048691254f, .02094239f, -.3019608f, 0);
private Color color23 = decodeColor("nimbusOrange", .003940329f, -.7375322f, .17647058f, 0);
private Color color24 = decodeColor("nimbusOrange", .005506739f, -.46764207f, .109803915f, 0);
private Color color25 = decodeColor("nimbusOrange", .0042127445f, -.18595415f, .04705882f, 0);
private Color color26 = decodeColor("nimbusOrange", .0047626942f, .02094239f, .0039215684f, 0);
private Color color27 = decodeColor("nimbusOrange", .0047626942f, -.15147138f, .1607843f, 0);
private Color color28 = decodeColor("nimbusOrange", .010665476f, -.27317524f, .25098038f, 0);
private Rectangle2D rect = new Rectangle2D.Float(0, 0, 0, 0);
private Path2D path = new Path2D.Float();
private PaintContext ctx = new PaintContext(new Insets(5, 5, 5, 5), new Dimension(29, 19), false);
@Override public void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) {
path = decodePath1();
g.setPaint(color17);
g.fill(path);
rect = decodeRect3();
g.setPaint(decodeGradient5(rect));
g.fill(rect);
rect = decodeRect4();
g.setPaint(decodeGradient6(rect));
g.fill(rect);
}
@Override public PaintContext getPaintContext() {
return ctx;
}
private Path2D decodePath1() {
path.reset();
path.moveTo(decodeX(0.6f), decodeY(0.12666667f));
path.curveTo(decodeAnchorX(0.6000000238418579f, -2.0f), decodeAnchorY(0.12666666507720947f, 0.0f), decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(0.6000000238418579f, -2.0f), decodeX(0.12666667f), decodeY(0.6f));
path.curveTo(decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(0.6000000238418579f, 2.0f), decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(2.4000000953674316f, -2.0f), decodeX(0.12666667f), decodeY(2.4f));
path.curveTo(decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(2.4000000953674316f, 2.0f), decodeAnchorX(0.6000000238418579f, -2.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeX(0.6f), decodeY(2.8933334f));
path.curveTo(decodeAnchorX(0.6000000238418579f, 2.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeAnchorX(3.0f, 0.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeX(3.0f), decodeY(2.8933334f));
path.lineTo(decodeX(3.0f), decodeY(2.6f));
path.lineTo(decodeX(0.4f), decodeY(2.6f));
path.lineTo(decodeX(0.4f), decodeY(0.4f));
path.lineTo(decodeX(3.0f), decodeY(0.4f));
path.lineTo(decodeX(3.0f), decodeY(0.120000005f));
path.curveTo(decodeAnchorX(3.0f, 0.0f), decodeAnchorY(0.12000000476837158f, 0.0f), decodeAnchorX(0.6000000238418579f, 2.0f), decodeAnchorY(0.12666666507720947f, 0.0f), decodeX(0.6f), decodeY(0.12666667f));
path.closePath();
return path;
}
private Rectangle2D decodeRect3() {
rect.setRect(decodeX(0.4f), //x
decodeY(0.4f), //y
decodeX(3.0f) - decodeX(0.4f), //width
decodeY(2.6f) - decodeY(0.4f)); //height
return rect;
}
private Rectangle2D decodeRect4() {
rect.setRect(decodeX(0.6f), //x
decodeY(0.6f), //y
decodeX(2.8f) - decodeX(0.6f), //width
decodeY(2.4f) - decodeY(0.6f)); //height
return rect;
}
private Paint decodeGradient5(Shape s) {
Rectangle2D bounds = s.getBounds2D();
float x = (float)bounds.getX();
float y = (float)bounds.getY();
float w = (float)bounds.getWidth();
float h = (float)bounds.getHeight();
return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y,
new float[] { 0.038709678f, 0.05483871f, 0.07096774f, 0.28064516f, 0.4903226f, 0.6967742f, 0.9032258f, 0.9241935f, 0.9451613f },
new Color[] { color18,
decodeColor(color18, color19, 0.5f),
color19,
decodeColor(color19, color20, 0.5f),
color20,
decodeColor(color20, color21, 0.5f),
color21,
decodeColor(color21, color22, 0.5f),
color22
});
}
private Paint decodeGradient6(Shape s) {
Rectangle2D bounds = s.getBounds2D();
float x = (float)bounds.getX();
float y = (float)bounds.getY();
float w = (float)bounds.getWidth();
float h = (float)bounds.getHeight();
return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y,
new float[] { 0.038709678f, 0.061290324f, 0.08387097f, 0.27258065f, 0.46129033f, 0.4903226f, 0.5193548f, 0.71774197f, 0.91612905f, 0.92419356f, 0.93225807f },
new Color[] { color23,
decodeColor(color23, color24, 0.5f),
color24,
decodeColor(color24, color25, 0.5f),
color25,
decodeColor(color25, color26, 0.5f),
color26,
decodeColor(color26, color27, 0.5f),
color27,
decodeColor(color27, color28, 0.5f),
color28
});
}
}
答案 1 :(得分:0)
您也可以从 JProgressBar 继承子类并覆盖 PaintComponent 方法。这使您可以完全自由地绘制任何您喜欢的东西。甚至可能比公认的解决方案更少的代码。
这是一个仅覆盖 Nimbus 不确定行为的示例,该示例具有更多类似窗口的渐变外观:
这个解决方案的缺点是你需要显式地 dispose() 组件(或者我可能还没有找到自动关闭执行器的合适方法)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
public final class Test
{
public JComponent makeUI()
{
final JProgressBar progressBar=new GradientProgressBar();
progressBar.setPreferredSize(new Dimension(700, 30));
progressBar.setIndeterminate(true);
progressBar.setStringPainted(true);
progressBar.setString("Loading...");
final JPanel p=new JPanel();
p.setBorder(BorderFactory.createEmptyBorder(32, 5, 32, 5));
p.add(progressBar);
return p;
}
public static void main(String[] args)
{
EventQueue.invokeLater(()->createAndShowGUI());
}
public static void createAndShowGUI()
{
try
{
for (UIManager.LookAndFeelInfo laf:UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(laf.getName()))
{
UIManager.setLookAndFeel(laf.getClassName());
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
JFrame f=new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new Test().makeUI());
f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class GradientProgressBar extends JProgressBar
{
private static final long serialVersionUID=8886375125424236114L;
private static final int UPDATE_INTERVAL_MS=50;
private static final AtomicInteger THREAD_NUM=new AtomicInteger();
private static final AtomicReference<ScheduledThreadPoolExecutor> executor=new AtomicReference<>();
private static final Font FONT=new Font("SansSerif", Font.BOLD, 12);
private static final int R_BACK=214;
private static final int G_BACK=217;
private static final int B_BACK=223;
private static final int COLOR_DELTA=20;
private static final Color COLOR_BAR=new Color(191, 98, 4);
private final AtomicInteger position=new AtomicInteger(-20);
@Override
protected void paintComponent(final Graphics g)
{
if (isIndeterminate())
{
drawGradient((Graphics2D) g);
adjustPosition();
}
else
{
super.paintComponent(g);
}
}
private void drawGradient(final Graphics2D g)
{
if (getWidth() > 0 && getHeight() > 0)
{
final int gradWidth=getWidth() / 4;
final float posF=(float) position.get();
for (int y=0;y < getWidth();y++)
{
GradientPaint grad=new GradientPaint(posF, 0.0f, getBackgroundAtY(y), posF + (float) gradWidth / 2.0f, 0.0f, COLOR_BAR);
Rectangle rect=new Rectangle(0, y, position.get() + gradWidth / 2, 1);
g.setPaint(grad);
g.fill(rect);
grad=new GradientPaint(posF + (float) gradWidth / 2.0f, 0.0f, COLOR_BAR, posF + (float) gradWidth, 0.0f, getBackgroundAtY(y));
rect=new Rectangle(position.get() + gradWidth / 2, y, getWidth() - position.get(), 1);
g.setPaint(grad);
g.fill(rect);
}
drawTitle(g);
}
}
public void drawTitle(final Graphics g)
{
if (isStringPainted() && getString() != null && !getString().isBlank())
{
g.setColor(Color.BLACK);
final FontMetrics metrics=g.getFontMetrics(FONT);
final int x=(getWidth() - metrics.stringWidth(getString())) / 2;
final int y=(getHeight() - metrics.getHeight()) / 2 + metrics.getAscent();
g.setFont(FONT);
g.drawString(getString(), x, y);
}
}
private Color getBackgroundAtY(final int y)
{
if (y <= 2 || y >= getHeight() - 2)
{
// Border
return new Color(R_BACK - COLOR_DELTA, G_BACK - COLOR_DELTA, B_BACK - COLOR_DELTA);
}
// Vertical gradient
final int height=(getHeight() - 4) / 2;
final int delta=Math.abs(height - y);
final int colorDelta=COLOR_DELTA * delta / height;
return new Color(R_BACK + colorDelta, G_BACK + colorDelta, B_BACK + colorDelta);
}
@Override
public void setIndeterminate(boolean newValue)
{
if (newValue != isIndeterminate())
{
super.setIndeterminate(newValue);
if (newValue)
{
executor.set(new ScheduledThreadPoolExecutor(1, r -> new Thread(r, "guihelper_progress-" + THREAD_NUM.incrementAndGet())));
executor.get().scheduleAtFixedRate(() -> repaint(), 0, UPDATE_INTERVAL_MS, TimeUnit.MILLISECONDS);
}
else
{
if (executor.get() != null)
{
executor.get().shutdownNow();
}
}
}
}
public void dispose()
{
if (executor.get() != null)
{
executor.get().shutdownNow();
}
}
private void adjustPosition()
{
int step=getWidth() * UPDATE_INTERVAL_MS / 10000;
if (step <= 0)
{
step=1;
}
position.set(position.get() + step);
if (position.get() > getWidth())
{
position.set(-getWidth() / 4);
}
}
}