【问题标题】:how to keep JLabel over JProgressbar如何让 JLabel 超过 JProgressbar
【发布时间】:2014-08-21 01:59:12
【问题描述】:

这是我的java代码的一部分,在这段代码中我希望进度条应该始终保持在标签下(在标签的后面),当我启动程序时进度条在标签下,但是进度条当我单击按钮并开始进度时,会出现在标签上。所以请告诉我怎样才能让标签总是在进度条上???

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;


public class Test {

    JFrame frame = new JFrame();
    JLabel label = new JLabel();
    JProgressBar bar = new JProgressBar(JProgressBar.VERTICAL,0,100);
    JButton button = new JButton();

    public static void main(String arg[]) {
        new Test();
    }

    public Test() {
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setUndecorated(true);
        frame.setLayout(null);
        label.setOpaque(true);
        label.setBackground(Color.BLACK);
        label.setBounds(100,100,100,50);
        bar.setBounds(140,25,20,200);
        button.setBounds(220,100,50,50);
        button.addActionListener(new Progress());
        frame.add(label);
        frame.add(bar);
        frame.add(button);
        frame.setVisible(true);
    }

    class Progress extends SwingWorker<Void, Void> implements ActionListener {

        public Void doInBackground() {
            for(int i=0; i<101; i++) {
                bar.setValue(i);
                try {
                    Thread.sleep(100);
                } 
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        public void actionPerformed(ActionEvent e) {
            this.execute();
        }
    }

}

【问题讨论】:

  • 不要使用空布局。学习和使用布局管理器。
  • 为什么需要这样做?你不能改用JProgressBar#setStringPainted 吗?避免使用null 布局,像素完美的布局是现代 ui 设计中的一种错觉。影响组件单个尺寸的因素太多,您无法控制。 Swing 旨在与核心布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正
  • @HovercraftFullOfEels 为什么人们会考虑按照设计使用的方式使用工具?什么启示...
  • 有没有办法解决我保持空布局的问题???
  • @KickButtowski 我仍在尝试找出 JProgressBar#setStringPainted 的问题所在

标签: java swing layout-manager null-layout-manager


【解决方案1】:

JProgressBar 已经提供了显示String 值的方法时,我不确定你为什么要这样做...

更多详情请见JProgressBar#setStringPainted...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ProgressBarTest {

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

    public ProgressBarTest() {
        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());
                JProgressBar pb = new JProgressBar();
                pb.setValue(0);
                pb.setStringPainted(true);
                pb.setString("Look ma, no hands");
                frame.add(pb);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                SwingWorker worker = new SwingWorker() {
                    @Override
                    protected Object doInBackground() throws Exception {
                        for (int index = 0; index < 1000; index++) {
                            int progress = (int)Math.round((index / 1000f) * 100);
                            setProgress(progress);
                            Thread.sleep(10);
                        }
                        return null;
                    }
                };

                worker.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equals(evt.getPropertyName())) {
                            int value = (int) evt.getNewValue();
                            System.out.println(value);
                            pb.setValue(value);
                        }
                    }
                });

                worker.execute();

            }
        });
    }

}

更新

现在,如果您“真的”想在进度条顶部放置标签,可以使用一些技巧,例如...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ProgressBarTest {

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

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

                JLabel label = new JLabel("I feel the need for speed");
                JProgressBar pb = new JProgressBar();

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.weightx = 1;
                gbc.fill = GridBagConstraints.BOTH;
                gbc.ipady = 20;

                frame.add(pb, gbc);

                gbc.weightx = 0;
                gbc.fill = GridBagConstraints.NONE;
                gbc.insets = new Insets(5, 0, 5, 0);
                frame.add(label, gbc);


                frame.add(pb, gbc);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                SwingWorker worker = new SwingWorker() {
                    @Override
                    protected Object doInBackground() throws Exception {
                        for (int index = 0; index < 1000; index++) {
                            int progress = (int) Math.round((index / 1000f) * 100);
                            setProgress(progress);
                            Thread.sleep(10);
                        }
                        return null;
                    }
                };

                worker.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equals(evt.getPropertyName())) {
                            int value = (int) evt.getNewValue();
                            System.out.println(value);
                            pb.setValue(value);
                        }
                    }
                });

                worker.execute();

            }
        });
    }

}

基本上,这会将标签和进度条放在GridBagLayout...内的同一位置...

【讨论】:

  • 我想你正在寻找这个stackoverflow.com/questions/25416336/…问题
  • 操作询问如何将 JLabel 保留在 JProgressbar 之上
  • @KickButtowski 我知道 OP 要求什么,我在问为什么 JProgressBar 已经支持它。当 OP 说“over”时,它们的意思是“ontop off”,看看他们正在使用的边界,进度条将覆盖标签......;)
  • @KickButtowski 另见Is “Don't do it” a valid answer?(是)和What is the XY problem?(到目前为止,这是一个XY问题)。
  • “我觉得需要速度” “我觉得安全很重要”(Leela)。
【解决方案2】:

基于@MadProgrammer 给我的这篇文章和想法

"You can use:

Initialising:

progressBar.setStringPainted(true);
Updating:

progressBar.setValue(newValue);
progressBar.setString(newValue + "%");"

这个答案的来源:

How to add text on jprogressbar?

我对这个问题的回答是

代码:

JFrame frame = new JFrame();

    JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100);
    JButton button = new JButton("Button");

    public static void main(String arg[]) {
        new Test();
    }

    public Test() {


        bar.setStringPainted(true);
        bar.setString("I am a JProgressBar and ready to go here");
        button.addActionListener(new Progress());

        JPanel pane = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        c.fill = GridBagConstraints.HORIZONTAL;
        c.ipady = 40;      //make this component tall
        c.weightx = 0.0;
        c.gridwidth = 2;
        c.gridx = 2;
        c.gridy = 2;

        pane.add(bar, c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 3;
        pane.add(button, c);

        frame.add(pane);
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class Progress extends SwingWorker<Void, Void> implements ActionListener {

        @Override
        public Void doInBackground() {
            for (int i = 0; i < 101; i++) {
                bar.setValue(i);
                bar.setString(Integer.toString(i) + "%");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            this.execute();
        }
    }
}

输出:

【讨论】:

  • bar.setBounds。此外,您通过在 EDT 之外更新进度条违反了 Swing 的单线程规则
  • 什么意思bar.setBounds?
  • 您刚刚告诉 OP 不要使用 null 布局,虽然我知道您不是,但您随后在非窗口组件上调用了 setBounds...跨度>
  • @MadProgrammer 你是如何制作 gif 的?
  • 我使用了一个叫做LICECap的工具,我喜欢它,因为它是跨平台的,所以我可以在我的Windows和Mac机器上使用它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多