Круговой индикатор выполнения для Java Swing не работает
Я обнаружил этот тестовый проект с сайта Oracle, потому что я хочу добавить в свой круговой индикатор выполнения.
Я разрабатываю приложение с Netbeans, и когда я запускаю приложение, JPanel, где должен быть круг... разочаровывает.
Я удалил весь код, который бесполезен для решения этой проблемы, и у меня есть этот код:
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 extends javax.swing.JFrame
{
static final WaitLayerUI layerUI = new WaitLayerUI();
public Loading_Test()
{
JPanel panel = new JPanel();
JLayer<JPanel> jlayer = new JLayer<>(panel, layerUI);
add(jlayer);
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new Loading_Test();
frame.setVisible(true);
layerUI.start();
}
});
}
}
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();
// Paint the view.
super.paint(g, c);
if (!mIsRunning)
{
return;
}
Graphics2D g2 = (Graphics2D) g.create();
float fade = (float) mFadeCount / (float) mFadeLimit;
// Gray it out.
Composite urComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f * fade));
g2.fillRect(0, 0, w, h);
g2.setComposite(urComposite);
// Paint the wait indicator.
int s = Math.min(w, h) / 5;
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;
}
// Run a thread for animation.
mIsRunning = true;
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();
}
}
}
Если вы запустите этот код "как есть", у вас должна появиться та же проблема, что и у JPanel.
Но я обнаружил, что если я удаляю строки, связанные с макетом (27~36), индикатор выполнения начинает работать.
Вы также должны установить вручную добавление размера окна
setSize(300, 300);
после
pack();
Поскольку строки макета автоматически генерируются Netbeans, я пытаюсь понять, как решить эту проблему, потому что эти конкретные строки кода заблокированы для редактирования редактором Netbeans.
3 ответа
Я потерял один день, и он все еще не работает.... Я буду использовать анимированный GIF на JLabel.... Конец истории!
@Robin имеет важную информацию, и похоже, что вы ограничены использованием GuiBulder..., тогда я не хочу комментировать что-то, результат
из немного измененного кода
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();
}
}
}
должен добавить два
JButtons
один для начала и второй для остановки (показать и скрыть анимированный концерт)не подделывай это
JPanel
реализовалFlowLayout
, что довольно принимаетPreferredSize
пришел от своих детей,
Нашли лучшее простое (и работающее) решение с расширением Swing Components от SwingLabs
JXBusyLabel
Для редактора имеется полностью интегрируемый плагин с NetBeans, поэтому он очень прост в использовании.
Судя по вашему вопросу и комментариям, у вас возникли проблемы с JLayer
в Netbeans я бы посоветовал CardLayout
что позволит вам переключаться между вашими обычными JPanel
и тот, что с вертушкой.
Вот простое руководство: CardLayout с Netbeans