簡體   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