как вы можете сделать индикатор выполнения без использования JProgressBar?

я собираюсь поместить индикатор выполнения в игру, которую я делаю, с обратным отсчетом от случайного числа от 5 до 20 до 0. это мой код до сих пор:

пакет программного обеспечения;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;

public class CountDownProgressBar extends JPanel {

    RandomValues randomNum;
    int timeValue;
    Timer timer;
    int length, newLength;

    public CountDownProgressBar() {
        timer = new Timer(24, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               for (int i = timeValue; i > 0; --i) {
                        newLength = length - (length / timeValue);
                        length = newLength;
                        repaint();
                    }
                }
            });
        randomNum = new RandomValues();
        this.timeValue = 0;
        this.setBackground(Color.GRAY);
    }

    @Override
    public void paint(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.green);
        g.fillRect(0, 0, length, 50);
    }

    public void setTimeLength() {
        this.timeValue = randomNum.integer(5, 20);
    }

    public int getTimeLength() {
        return this.timeValue;
    }
}

Я знаю, что большая часть этого неверна, я просто не могу понять, как это сделать. ему нужно не использовать JProgressBar, вместо этого использовать графику (зеленый прямоугольник), где он становится все меньше и меньше, а время отсчитывается. и как мне сделать так, чтобы размер экрана можно было изменять, а полоса по-прежнему шла в обратном направлении относительно размера экрана. так что это не просто один фиксированный размер, а просто идет по нижней части экрана.


person KrazyKat89    schedule 26.12.2012    source источник
comment
Вы можете сделать собственный JComponent   -  person Extreme Coders    schedule 26.12.2012
comment
1) JProgressBar может быть нарисовано непосредственно в экземпляре Graphics. 2) Не блокируйте EDT (поток отправки событий) — когда это произойдет, графический интерфейс «зависнет». Вместо вызова Thread.sleep(n) реализуйте Swing Timer для повторяющихся задач. Дополнительные сведения см. в разделе Параллелизм в Swing. 3) проходит через нижнюю часть экрана. Поместите JProgressBar в PAGE_END BorderLayout вместо над игровым полем.   -  person Andrew Thompson    schedule 26.12.2012
comment
+1 к комментарию @AndrewThompson. См. мой ответ для примера использования этой логики: stackoverflow.com/a/14052118/1133011   -  person David Kroukamp    schedule 27.12.2012
comment
Также рассмотрите пользовательский ProgressBarUI.   -  person trashgod    schedule 27.12.2012
comment
@andrew Это ответ, а не комментарий. Почему бы не опубликовать это как таковое?   -  person dstibbe    schedule 27.12.2012
comment
@dstibbe Обычно с таким типом комментариев / ответов возникает суждение. Поскольку сейчас есть 3 хороших примера либо в теме, либо по ссылке из нее, я думаю, что на этот раз оставлю это в качестве комментария.   -  person Andrew Thompson    schedule 27.12.2012
comment
@Эндрю без использования JProgressBar   -  person Yousha Aleayoub    schedule 22.11.2018


Ответы (4)


Это код пользовательского JProgressBar, который я сделал давным-давно (я знаю, что в вопросе говорится, что не следует использовать JProgressBar, но вы можете почерпнуть идеи кода из него), он был разработан, чтобы напоминать внешний вид индикатора выполнения из «Человек» тема в убунту 9.04:

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JProgressBar;

/**
 * A progressBar that looks like the progress bar from Ubuntu 9.04 Human Theme
 */
public class HumanProgressBar extends JProgressBar {
    private static final long serialVersionUID = 1L;

    private static final String DISABLED_PERCENT_STRING = " --- ";

    private static final Color gradientEndingColor = new Color(0xc0c0c0);
    private static final Color borderColor = new Color(0x736a60);
    private static final Color disabledBorderColor = new Color(0xbebebe);    

    private static final Composite transparent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.45f);
    private static final Composite veryTransparent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f);

    private static GradientPaint gradient;

    private int oldWidth;
    private int oldHeight;

    private int displayWidth;
    private int displayHeight;

    private int insets[] = new int[4];
    private static final int TOP_INSET = 0;
    private static final int LEFT_INSET = 1;
    private static final int BOTTOM_INSET = 2;
    private static final int RIGHT_INSET = 3;

    private static final int PREFERRED_PERCENT_STRING_MARGIN_WIDTH = 3;

    public static final Color PREFERRED_PROGRESS_COLOR = new Color(0x1869A6);

    private boolean percentStringVisible = true;

    private Color progressColor;

    private String maxPercentString;

    public HumanProgressBar() {
        progressColor = PREFERRED_PROGRESS_COLOR;
    }

    public void updateGraphics() {
        update(getGraphics());
    }

    @Override
    protected void paintComponent(Graphics g) {
        int w = displayWidth != 0 ? displayWidth - 1 : getWidth() - 1;
        int h = displayHeight != 0 ? displayHeight - 1 : getHeight() - 1;

        int x = insets[LEFT_INSET];
        int y = insets[TOP_INSET];
        w -= (insets[RIGHT_INSET] << 1);
        h -= (insets[BOTTOM_INSET] << 1);

        if (gradient == null) {
            gradient = new GradientPaint(0.0f, 0.0f, Color.WHITE, 0.0f, h, gradientEndingColor);
        }
        Graphics2D g2d = (Graphics2D) g;
        // Clean background
        if (isOpaque()) {
            g2d.setColor(getBackground());
            g2d.fillRect(0, 0, getWidth(), getHeight());
        }

        g2d.translate(x, y);

        if (percentStringVisible) {
            FontMetrics fm = g.getFontMetrics();
            int stringW = 0;
            int stringH = 0;

            g2d.setColor(getForeground());

            if (isEnabled()) { 
                int p = getValue();
                String percent = Integer.toString(p, 10) + "%";
                if (p < 10) {
                    percent = "0" + percent;
                }

                if (maxPercentString == null) {
                    maxPercentString = Integer.toString(getMaximum(), 10) + "%";
                }
                stringW = fm.stringWidth(maxPercentString);
                stringH = ((h - fm.getHeight()) / 2) + fm.getAscent();

                g2d.drawString(percent, w - stringW, stringH);
            } else {
                stringW = fm.stringWidth(DISABLED_PERCENT_STRING);
                stringH = ((h - fm.getHeight()) / 2) + fm.getAscent();

                g2d.drawString(DISABLED_PERCENT_STRING, w - stringW, stringH);
            }
            w -= (stringW + PREFERRED_PERCENT_STRING_MARGIN_WIDTH);            
        }

        // Control Border
        g2d.setColor(isEnabled() ? borderColor : disabledBorderColor);
        g2d.drawLine(1, 0, w - 1, 0);
        g2d.drawLine(1, h, w - 1, h);
        g2d.drawLine(0, 1, 0, h - 1);
        g2d.drawLine(w, 1, w, h - 1);

        // Fill in the progress
        int min = getMinimum();
        int max = getMaximum();
        int total = max - min;
        float dx = (float) (w - 2) / (float) total;
        int value = getValue();
        int progress = 0; 
        if (value == max) {
            progress = w - 1;
        } else {
            progress = (int) (dx * getValue());            
        }

        g2d.setColor(progressColor);
        g2d.fillRect(1, 1, progress, h - 1);

        // A gradient over the progress fill
        g2d.setPaint(gradient);
        g2d.setComposite(transparent);
        g2d.fillRect(1, 1, w - 1, (h >> 1));
        final float FACTOR = 0.20f;
        g2d.fillRect(1, h - (int) (h * FACTOR), w - 1, (int) (h * FACTOR));

        if (isEnabled()) {
            for (int i = h; i < w; i += h) {
                g2d.setComposite(veryTransparent);
                g2d.setColor(Color.GRAY);
                g2d.drawLine(i, 1, i, h - 1);
                g2d.setColor(Color.WHITE);
                g2d.drawLine(i + 1, 1, i + 1, h - 1);
            }
        } else {
            for (int i = 0; i < w; i += h) {
                g2d.setComposite(veryTransparent);
                g2d.setColor(Color.RED);
                g2d.drawLine(i, h - 1, i + h, 1);
                g2d.setColor(Color.WHITE);
                g2d.drawLine(i + 1, h - 1, i + 1 + h, 1);
            }            
        }
    }

    public void setInsets(int top, int left, int bottom, int right) {
        insets[TOP_INSET] = top;
        insets[LEFT_INSET] = left;
        insets[BOTTOM_INSET] = bottom;
        insets[RIGHT_INSET] = right;
    }

    public void setPercentStringVisible(boolean percentStringVisible) {
        this.percentStringVisible = percentStringVisible;
    }

    @Override
    protected void paintBorder(Graphics g) {
    }

    @Override
    public void validate() {
        int w = getWidth();
        int h = getHeight();

        super.validate();
        if (oldWidth != w || oldHeight != h) {
            oldWidth = w;
            oldHeight = h;
            gradient = null;
        }
    }

    @Override
    public void setMaximum(int n) {
        super.setMaximum(n);
        maxPercentString = Integer.toString(n, 10) + "%";
    }

    public void setDisplaySize(int width, int height) {
        displayWidth = width;
        displayHeight = height;
    }

    public Color getProgressColor() {
        return progressColor;
    }

    public void setProgressColor(Color progressColor) {
        this.progressColor = progressColor;
    }
}

Вот тестовая программа для компонента:

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class T extends JFrame {
    public T() {
        super();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        this.setSize(350, 75);
        HumanProgressBar p = new HumanProgressBar();
        p.setValue(50);
        p.setBounds(15, 15, 300, 15);
        this.add(p);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new T();
            }
        });
    }
}

введите здесь описание изображения

person higuaro    schedule 26.12.2012
comment
+1 хороший пример. пожалуйста, используйте SwingUtilities.invokeLater для поднятия качелей. - person vels4j; 26.12.2012
comment
спасибо, вроде помогает. просто это должен быть очень простой обратный отсчет, скажем, от 20 до 0, который заполняет всю панель jpanel внизу экрана. каждую секунду часть полосы убирается, пока не истечет время. - person KrazyKat89; 26.12.2012
comment
Очень хорошо, если бы OP не сказал без класса JProgressBar - person David Kroukamp; 27.12.2012

Возможно, вы сможете адаптировать ProgressIcon, как показано здесь на вкладках файла JTabbedPane.

изображение

person trashgod    schedule 26.12.2012

+1 к комментарию Эндрю Томпсона.

Вот небольшой пример, который я сделал, не самый лучший, но он показывает логику, необходимую для создания собственного JProgressBar с нуля с помощью JPanel:

введите здесь описание изображения

его также можно установить как неопределенное:

введите здесь описание изображения

через раскомментирование:

    myProgressBar.setBackground(new Color(0, 255, 0, 127));
    myProgressBar.setIndeterminate(true); //if progress unknown show ball moving from side to side

CustomProgressBarTest.java:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

public class CustomProgressBarTest {

    public CustomProgressBarTest() {
        createAndShowGui();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new CustomProgressBarTest();
            }
        });
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final MyProgressBar myProgressBar = new MyProgressBar(0, 100);
        myProgressBar.setProgressColor(new Color(0, 255, 0, 127));
        //myProgressBar.setIndeterminate(true); //if progress unknown show ball moving from side to side

        JPanel dummyPanel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
        };

        dummyPanel.add(new JLabel("DummyPanel"));

        frame.add(dummyPanel);

        frame.add(myProgressBar, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);

        //create timer to decrease progressbar
        createAndStartDecrementTimer(myProgressBar);

        //create timer to increase progressbar
        //myProgressBar.setValue(0);//set to 0 so we can increment
        //createAndStartIncrementTimer(myProgressBar);
    }

    private void createAndStartIncrementTimer(final MyProgressBar myProgressBar) {
        Timer progressBarIncrementTimer = new Timer(100, new AbstractAction() {
            int count = 0;

            @Override
            public void actionPerformed(ActionEvent ae) {
                if (count == 100) {
                    System.out.println("Done");
                    ((Timer) ae.getSource()).stop();
                } else if (count < 100) {
                    //System.out.println("Here");
                    count++;
                    myProgressBar.setValue(count);
                }
            }
        });
        progressBarIncrementTimer.start();
    }

    private void createAndStartDecrementTimer(final MyProgressBar myProgressBar) {
        Timer progressBArCountDownTimer = new Timer(100, new AbstractAction() {
            int count = 100;

            @Override
            public void actionPerformed(ActionEvent ae) {
                if (count == 0) {
                    System.out.println("Done");
                    ((Timer) ae.getSource()).stop();
                } else if (count > 0) {
                    count--;
                    myProgressBar.setValue(count);
                    System.out.println(myProgressBar.getValue());
                }
            }
        });
        progressBArCountDownTimer.start();
    }
}

class MyProgressBar extends JPanel {

    private final int minValue, maxValue;
    private boolean indeterminate = false;
    private int currentValue;
    private ArrayList<Rectangle> rects = new ArrayList<>();
    private Color PROGRESS_COLOR = Color.blue;
    private int removeValue = 0;
    private Timer indeterminateTimer;
    private int x = 0, y = 0, ballSize = 25;
    private boolean changeDirection = false;

    public MyProgressBar(int min, int max) {
        indeterminateTimer = new Timer(50, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                repaint();
            }
        });
        maxValue = max;
        minValue = min;
        currentValue = maxValue;
        setBorder(new LineBorder(Color.BLACK));
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        if (!indeterminate) {//if normal progress bar
            rects.clear();
            int rectWidths = getWidth() / maxValue;
            int startingX = 0;

            if (currentValue < maxValue) {//we started off with a value less than the max
                for (int i = minValue; i < currentValue; i++) {
                    rects.add(new Rectangle(startingX, 0, rectWidths, getHeight()));
                    startingX += rectWidths;
                }
            } else {
                for (int i = minValue; i < (maxValue - removeValue); i++) {
                    rects.add(new Rectangle(startingX, 0, rectWidths, getHeight()));
                    startingX += rectWidths;
                }
            }

            for (Rectangle r : rects) {
                g2d.setColor(PROGRESS_COLOR);
                g2d.fillRect(r.x, r.y, r.width, r.height);
            }
        } else {//if indeterminate
            if (!indeterminateTimer.isRunning()) {
                indeterminateTimer.start();
            }
            g2d.setColor(PROGRESS_COLOR);
            if (!changeDirection) {
                if (x + 10 < getWidth() - (ballSize / 2)) {
                    x += 10;
                } else {
                    changeDirection = true;
                }
            } else if (changeDirection) {
                if (x + 10 > 0) {
                    x -= 10;
                } else {
                    changeDirection = false;
                }
            }
            g2d.fillOval(x, y, ballSize, getHeight());
        }
    }

    int getValue() {
        return currentValue;
    }

    public void setIndeterminate(boolean indeterminate) {
        this.indeterminate = indeterminate;
    }

    void setValue(int value) {
        if (value > maxValue) {
            return;
        }
        if (value < minValue) {
            return;
        }
        if (value < currentValue) {
            removeValue++;
        } else {
            int rem = value - currentValue;
            removeValue -= rem;
        }
        currentValue = value;
        repaint();
    }

    void setProgressColor(Color c) {
        PROGRESS_COLOR = c;
    }

    Color getProgressColor() {
        return PROGRESS_COLOR;
    }
}
person David Kroukamp    schedule 27.12.2012
comment
myProgressBar.setBackground(Color.GREEN); Это может быть лучше myProgressBar.setBackground(new Color(0,255,0,127)); // partially transparent, так как он предположительно появляется над активной игровой областью. - person Andrew Thompson; 27.12.2012
comment
@AndrewThompson +1 обновил мой код, чтобы он соответствовал приведенному выше, с несколькими дополнениями, такими как setIndeterminate(..) и getValue(..), чтобы сделать его более похожим на JProgressBar: P - person David Kroukamp; 27.12.2012
comment
protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.gray); int width = getWidth(); g.fillRect(0, 0, width, 20); for (int i = maxValue; i > 0; --i) { int rectWidth = width / maxValue; int newWidth = width - rectWidth; g.setColor(Color.green); g.fillRect(0, 0, newWidth, 20); привет, я позаимствовал, но изменил много вашего кода, но я просто не могу заставить работать свой. Вы видите, где я могу ошибаться в своих компонентах краски ?? - person KrazyKat89; 27.12.2012
comment
@KrazyKat89 этого кода недостаточно, вам нужно больше. То есть все в блоке if(!indeterminate), id предлагает взять мой класс и заставить его работать в вашем приложении, а не изменять его по мере необходимости. - person David Kroukamp; 27.12.2012
comment
Хорошо, может быть, это простой вопрос, но, похоже, сейчас он работает, но я хочу, чтобы его высота была, возможно, в три раза больше, чем есть. ничего, что я пытаюсь, не работает. где я должен был бы изменить размер? - person KrazyKat89; 28.12.2012
comment
@KrazyKat89, где бы вы изменили размер? изменить размер изменить размер чего? Также мы видим, что в вашем отредактированном вопросе вы переопределяете paint(..), пожалуйста, проверьте, что я не переопределяю этот метод, а paintComponent - person David Kroukamp; 28.12.2012
comment
@DavidKroukamp должен ли он переопределять paint () или переопределять paintComponent ()? у меня есть переопределение paintComponent(). что я хотел сделать больше, так это индикатор выполнения. я хотел сделать его высоту, может быть, в 3 раза больше, чем в вашем примере. - person KrazyKat89; 28.12.2012
comment
@KrazyKat89, если вы хотите изменить размер, переопределите getPreferredSize, как я сделал с фиктивным JPanel. И вернуть соответствующие размеры. - person David Kroukamp; 28.12.2012
comment
@KrazyKat89, пожалуйста, посмотрите, как работает принятие ответа?: meta.stackexchange.com/questions/5234/ - person David Kroukamp; 29.12.2012

Вот что я сделал для своей игры. Не стесняйтесь использовать это для всех, кто может найти этот вопрос, как я.

Наслаждаться.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;

import javax.swing.JPanel;

import com.jayavon.game.client.MyClient;

public class CustomJProgressBar extends JPanel {
    private static final long serialVersionUID = 1L;
    private Color color;
    private int width, height;
    private double minimum = 0.0;
    private double maximum = 100.0;
    private double value = 100.0;
    private Font font = MyClient.theme_font.deriveFont(Font.PLAIN, 12);

    public CustomJProgressBar(Color color) {
        super();
        this.color = color;
        setBounds(0, 0, width, height);
        setFont(font);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        //border
        g.setColor(MyClient.THEME_LIGHT_TEXT);
        g.drawRect(0, 0, getWidth()-1, getHeight()-1);

        //progress
        int drawAmount = (int) (((value - minimum) / (maximum - minimum)) * getWidth());
        g.setColor(color);
        g.fillRect(1, 1, drawAmount-2, getHeight()-2); //-2 to account for border

        //string painting
        String stringToPaint = (int)value + "/" + (int)maximum;
        Canvas c = new Canvas();
        FontMetrics fm = c.getFontMetrics(font);
        final int stringWidth = fm.stringWidth(stringToPaint);
        final int stringHeight = fm.getHeight();
        g.setColor(MyClient.THEME_LIGHT_TEXT);
        g.drawString(stringToPaint, (getWidth()/2) - (stringWidth/2), ((getHeight()/2) + (stringHeight/2))-2); //-2 to account for border
    }

    public void setColor(Color _color){
        this.color = _color;
    }

    public void setMinimum(double _minimum){
        this.minimum = _minimum;
    }

    public void setMaximum(double _maximum){
        this.maximum = _maximum;
    }

    public void setValue(double _value){
        this.value = _value;
    }
}
person KisnardOnline    schedule 02.02.2016