繁体   English   中英

Java摇摆不定JProgressBar从结束时从左侧开始而不是弹跳

[英]Java swing indeterminate JProgressBar starting from the left when reaching end instead of bouncing

我在GUI应用程序中创建了一个JProgressBar ,并将其设置为“ indeterminate” ,但是我不喜欢它反弹而不是每次到达终点重新启动 我该怎么做才能解决此图形设置?

更改JProgressBar的UI。

UI是绘制进度条的类。 BasicProgressBarUI,默认情况下使框反弹。 您只需要编写自己的类即可扩展MetalProgressBarUI(如果您使用的是Metal)并覆盖getBox(Rectangle) ,这是将框的位置存储在给定矩形中的方法。

使用JProgressBar.setUI将UI应用于进度栏。 您也可以使用UIManager.put(“ ProgressBarUI”,“ fullyQualifiedClassName”)更改默认值,以更改进度栏的默认UI。

正如Snowy_1803已经说过的那样,您将需要重写BasicProgressBarUI#getBox(...)

import java.awt.*;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.swing.*;
import javax.swing.plaf.basic.BasicProgressBarUI;

public final class MainPanel extends JPanel implements HierarchyListener {
  private transient SwingWorker<String, Void> worker;

  private MainPanel() {
    super(new BorderLayout());

    BoundedRangeModel model = new DefaultBoundedRangeModel();
    JProgressBar progressBar = new JProgressBar(model) {
      @Override public void updateUI() {
        super.updateUI();
        setUI(new OneDirectionProgressBarUI());
      }
    };

    List<JProgressBar> list = Arrays.asList(new JProgressBar(model), progressBar);

    JPanel p = new JPanel(new GridLayout(5, 1));
    list.forEach(bar -> p.add(makePanel(bar)));

    JButton button = new JButton("Test start");
    button.addActionListener(e -> {
      if (Objects.nonNull(worker) && !worker.isDone()) {
        worker.cancel(true);
      }
      worker = new BackgroundTask();
      list.forEach(bar -> {
        bar.setIndeterminate(true);
        worker.addPropertyChangeListener(new ProgressListener(bar));
      });
      worker.execute();
    });

    Box box = Box.createHorizontalBox();
    box.add(Box.createHorizontalGlue());
    box.add(button);
    box.add(Box.createHorizontalStrut(5));

    addHierarchyListener(this);
    add(p);
    add(box, BorderLayout.SOUTH);
    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    boolean isDisplayableChanged = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
    if (isDisplayableChanged && !e.getComponent().isDisplayable() && Objects.nonNull(worker)) {
      worker.cancel(true);
      worker = null;
    }
  }

  private static Component makePanel(Component cmp) {
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.insets = new Insets(5, 5, 5, 5);
    c.weightx = 1d;

    JPanel p = new JPanel(new GridBagLayout());
    p.add(cmp, c);
    return p;
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new MainPanel());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class OneDirectionProgressBarUI extends BasicProgressBarUI {
  @Override
  protected Rectangle getBox(Rectangle r) {
    Rectangle rect = super.getBox(r);

    boolean vertical = progressBar.getOrientation() == JProgressBar.VERTICAL;
    Insets ins = new Insets(0, 0, 0, 0); // progressBar.getInsets();

    int currentFrame = getAnimationIndex();
    int framecount = getFrameCount() / 2;
    currentFrame = currentFrame % framecount;

    // @see com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java
    // this code adjusts the chunk size to properly account for the
    // size and gap specified in the XP style. It also does it's own
    // box placement for the chunk animation. This is required because
    // the inherited algorithm from BasicProgressBarUI goes back and
    // forth whereas XP only goes in one direction. XP also has ghosted
    // trailing chunks to create the illusion of speed. This code
    // adjusts the pixel length of the animation to account for the
    // trails.
    if (!vertical) {
      rect.y = rect.y + ins.top;
      rect.height = progressBar.getHeight() - ins.top - ins.bottom;
      int len = progressBar.getWidth() - ins.left - ins.right;
      len += rect.width * 2; // add 2x for the trails
      double delta = (double) (len) / (double) framecount;
      rect.x = (int) (delta * currentFrame) + ins.left;
    } else {
      rect.x = rect.x + ins.left;
      rect.width = progressBar.getWidth() - ins.left - ins.right;
      int len = progressBar.getHeight() - ins.top - ins.bottom;
      len += rect.height * 2; // add 2x for the trails
      double delta = (double) (len) / (double) framecount;
      rect.y = (int) (delta * currentFrame) + ins.top;
    }
    return rect;
  }
}

class BackgroundTask extends SwingWorker<String, Void> {
  @Override public String doInBackground() {
    try { // dummy task
      Thread.sleep(5000);
    } catch (InterruptedException ex) {
      return "Interrupted";
    }
    int current = 0;
    int lengthOfTask = 100;
    while (current <= lengthOfTask && !isCancelled()) {
      try { // dummy task
        Thread.sleep(50);
      } catch (InterruptedException ex) {
        return "Interrupted";
      }
      setProgress(100 * current / lengthOfTask);
      current++;
    }
    return "Done";
  }
}

class ProgressListener implements PropertyChangeListener {
  private final JProgressBar progressBar;

  protected ProgressListener(JProgressBar progressBar) {
    this.progressBar = progressBar;
    this.progressBar.setValue(0);
  }

  @Override public void propertyChange(PropertyChangeEvent e) {
    String strPropertyName = e.getPropertyName();
    if ("progress".equals(strPropertyName)) {
      progressBar.setIndeterminate(false);
      int progress = (Integer) e.getNewValue();
      progressBar.setValue(progress);
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM