Java堆叠组件

标签 java swing jlabel layout-manager

我正在用 Java 编写一个具有 UI 的程序。我想做一种健康棒之类的东西。我必须使用 JLabel 的 HealthBarUnder 和 HealthBarOver。我想将它们放置在彼此的顶部,以便可以减小 HealthBarOver 的宽度(从而形成健康栏的外观)。最好使用什么布局。我正在使用 BorderLayout,但它不允许我重新调整组件的大小。

谢谢

最佳答案

你“可以”做这样的事情......

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class SlidingLabels {

    public static void main(String[] args) {
        new SlidingLabels();
    }

    public SlidingLabels() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel lower = new JLabel();
        private JLabel upper = new JLabel();

        private float progress = 1f;
        private boolean ignoreUpdates;

        public TestPane() {
            setLayout(new GridBagLayout());
            lower.setOpaque(true);
            lower.setBackground(Color.GRAY);
            lower.setBorder(new LineBorder(Color.BLACK));
            lower.setPreferredSize(new Dimension(200, 25));

            upper.setOpaque(true);
            upper.setBackground(Color.BLUE);
            upper.setBorder(new LineBorder(Color.BLACK));
            upper.setPreferredSize(new Dimension(200, 25));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.fill = GridBagConstraints.NONE;
            add(upper, gbc);
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(lower, gbc);

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    progress -= 0.01;
                    if (progress <= 0.001) {
                        ((Timer)e.getSource()).stop();
                    }
                    updateProgress();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void updateProgress() {
            ignoreUpdates = true;
            int width = (int) (getWidth() * progress);
            upper.setPreferredSize(new Dimension(width, 25));
            revalidate();
            repaint();
            ignoreUpdates = false;
        }

        @Override
        public void invalidate() {
            super.invalidate(); 
            if (!ignoreUpdates) {
                updateProgress();
            }
        }

    }
}

但它使用了许多令人讨厌的黑客技术,可能很快就会在你面前爆炸......

应该使用JProgressBar

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class ProgressBar {

    public static void main(String[] args) {
        new ProgressBar();
    }

    public ProgressBar() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JProgressBar pb;
        private float progress = 1f;

        public TestPane() {
            setLayout(new GridBagLayout());

            pb = new JProgressBar();
            pb.setBorderPainted(false);
            pb.setStringPainted(true);
            pb.setBorder(new LineBorder(Color.BLACK));
            pb.setForeground(Color.BLUE);
            pb.setBackground(Color.GRAY);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.insets = new Insets(4, 4, 4, 4);
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(pb, gbc);

            updateProgress();
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    progress -= 0.01;
                    if (progress <= 0.001) {
                        ((Timer)e.getSource()).stop();
                    }
                    updateProgress();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void updateProgress() {
            pb.setValue((int) (100 * progress));
        }

    }
}

但是,如果这不能满足您的需求,您最好编写自己的进度组件......

enter image description here

public class ProgressPane {

    public static void main(String[] args) {
        new ProgressPane();
    }

    public ProgressPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private float progress = 1f;

        public TestPane() {

            setOpaque(false);

            setForeground(Color.BLUE);
            setBackground(Color.GRAY);

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    progress -= 0.01;
                    if (progress <= 0.001) {
                        ((Timer)e.getSource()).stop();
                    }
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            FontMetrics fm = getFontMetrics(getFont());
            return new Dimension(200, fm.getHeight() + 4);
        }

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

            int width = getWidth() - 4;
            int height = getHeight() - 4;
            int x = 2;
            int y = 2;

            g.setColor(getBackground());
            g.fillRect(x, y, width, height);
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);

            g.setColor(getForeground());
            g.fillRect(x, y, (int) (width * progress), height);
            g.setColor(Color.BLACK);
            g.drawRect(x, y, (int) (width * progress), height);

            FontMetrics fm = g.getFontMetrics();
            String value = NumberFormat.getPercentInstance().format(progress);
            x = x + ((width - fm.stringWidth(value)) / 2);
            y = y + ((height - fm.getHeight()) / 2);

            g.setColor(Color.WHITE);
            g.drawString(value, x, y + fm.getAscent());

        }

    }
}

强烈推荐最后两个示例之一,随着时间的推移,它们更容易实现和维护。第一个会在你脸上爆炸,非常不愉快

ps-Kleo,请不要伤害我:(

关于Java堆叠组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15125388/

相关文章:

java - 如何在子方法中访问子类中的父类变量?

java - Python 中的分层任务网络规划器

java - 如何在 Kafka KStream 中过滤无效传入的 json 数据

java - 如何访问匿名内部actionListener类和actionPerformed方法中的局部变量?

java - 仅 jlabel 的鼠标单击事件正确更新 jlabel 文本属性

java - JTextField文本显示

java 。 GUI WindowBuilder 通过单击按钮从 JTextField 读取

java - 更改 JCheckBox/JRadioButton 选择颜色

java - 将 JTextarea 添加到 JScrollPane。什么是可见的,第一还是第二?

java - 如何将一个 JLabel 的内容传输到另一个 JLabel?