2

我的程序在 JProgressBar 中写入文本。问题是文本比 JProgressBar 的宽度更宽。

我已经更改了 JProgressBar 的高度,以便能够在两行上写入文本,但我不想更改宽度。

如果 JProgressBar 太宽,如何更改 JProgressBar 的溢出以使文本返回到下一行?

我希望这足够清楚:)

这是我想要的:

JProgressBar 中的溢出

谢谢


编辑

@mKorbel 回复后,结果如下所示:

在此处输入图像描述

标签工作得很好,但为什么这些条带?

我的代码:

// Construct progress bar
JProgressBar progressBar = new JProgressBar(0, 100);
// Set progressBar color
progressBar.setForeground(new Color(0,176,80));

// Edit progress bar height
Dimension prefSize = progressBar.getPreferredSize();
prefSize.height = 50;
progressBar.setPreferredSize(prefSize);

// Set the layout
progressBar.setLayout(new BorderLayout(5, 5));

// Set progress bar value
progressBar.setValue(38);

// Construct the label
JLabel progressLabel = new JLabel("<html>I have already changed the JProgressBar's height to be able to write the text on two lines but I don't want to the change the width.</html>");
// Set alignment
progressLabel.setHorizontalAlignment(JLabel.CENTER);
progressLabel.setVerticalAlignment(JLabel.CENTER);

// Set the borders
progressLabel.setBorder(new EmptyBorder(15, 15, 15, 15));

// Change the font
font = progressLabel.getFont();
font = font.deriveFont(Font.BOLD, 12);
progressLabel.setFont(font);

// Add label to the progress bar
progressBar.add(progressLabel, BorderLayout.CENTER);

// Add progress bar to the frame
frame.add(progressBar);
4

2 回答 2

4

该程序是用 Java 6 开发的。似乎 JLayer 不可用。如果我错了,您能否提供一些有关如何执行此操作的代码?

  • 你能提供一些关于如何做到这一点的代码吗?--- > JLayer & JProgressBar by @aterai,更多想法请参见他的博客,对于 Java6,您可以使用 JXLayer

  • 或通过使用 GlassPane 具有非常相似的逻辑

在此处输入图像描述在此处输入图像描述在此处输入图像描述

一些笔记

  • 应该使用 GBC 而不是 NullLayout

  • 添加图标或透明背景会更好

  • (通过将 LayoutManager 添加到 JLabel)可以放置一堆 JComponent,其效果与 JPanel 相同

例如

import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
//https://stackoverflow.com/questions/14560680/jprogressbar-low-values-will-not-be-displayed
public class ProgressSample {

    private JFrame frame = new JFrame("GlassPane instead of JLayer");
    private JLabel label;
    private GridBagConstraints gbc = new GridBagConstraints();
    private JProgressBar progressSeven;

    public ProgressSample() {
        frame.setLayout(new FlowLayout());
        frame.add(new JButton("test"));
        frame.add(new JCheckBox("test"));
        frame.add(new JRadioButton("test"));
        // Nothing is displayed if value is lover that 6
        JProgressBar progressSix = new JProgressBar(0, 100);
        progressSix.setValue(2);
        frame.add(progressSix);
        // but this works value is higher that 6
        progressSeven = new JProgressBar(0, 100);
        progressSeven.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentMoved(ComponentEvent e) {
                label.setBounds(
                        (int) progressSeven.getBounds().getX(),
                        (int) progressSeven.getBounds().getY(),
                        label.getPreferredSize().width,
                        label.getPreferredSize().height);
            }
        });
        progressSeven.setValue(7);
        frame.add(progressSeven);
        label = new JLabel();
        label.setText("<html> Concurency Issues in Swing<br>"
                + " never to use Thread.sleep(int) <br>"
                + " durring EDT, simple to freeze GUI </html>");
        label.setPreferredSize(new Dimension(label.getPreferredSize().width, label.getPreferredSize().height));
        Container glassPane = (Container) frame.getRootPane().getGlassPane();
        glassPane.setVisible(true);
        glassPane.setLayout(null);
        glassPane.add(label, gbc);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        ProgressSample dialogTest = new ProgressSample();
    }
}

编辑

  • 评论

我的第一个想法是使用 html,但令人惊讶的是(对我而言)进度条不支持它...... by @kleopatra

我想我的问题可能不够清楚。我不希望文本超出 JProgressBar 边界。另外,我不想手动插入换行符(即 no
)。我添加了我想要的图片。通过@Maxbester

  • 结果是JProgressBar用作Container,放在那里,LayoutManager覆盖JProgressBarJLabel

在此处输入图像描述

  • 增强,设置EmptyBorderJLabel,例如label.setBorder(new EmptyBorder(15, 15, 15, 15));

在此处输入图像描述

EDIT2(图标是,也可以是半透明的,可以覆盖JProgressBar)

在此处输入图像描述

代码可能类似于

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

public class JProgressBarWithJLabel {

    private JFrame frame = new JFrame("JLabel in JProgressBar");
    private JLabel label;
    private JProgressBar progressSeven;

    public JProgressBarWithJLabel() {
        progressSeven = new JProgressBar(0, 100){
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 60);
            }
        };
        progressSeven.setValue(38);
        progressSeven.setLayout(new BorderLayout(5, 5));
        label = new JLabel();
        label.setHorizontalTextPosition(JLabel.CENTER);
        label.setVerticalTextPosition(JLabel.CENTER);
        label.setBorder(new EmptyBorder(15, 15, 15, 15));
        label.setText("<html>I have already changed the JProgressBar's height "
                + "to be able to write the text on two lines but I don't want "
                + "to the change the width.</html>");
        progressSeven.add(label, BorderLayout.CENTER);
        frame.add(progressSeven);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(laf.getName())) {
                    UIManager.setLookAndFeel(laf.getClassName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JProgressBarWithJLabel();
            }
        });
    }
}

编辑3:

WindowsClassicLookAndFeel 的默认剥离(图标不是半透明的)

在此处输入图像描述

于 2013-08-21T10:40:23.180 回答
0

可用的答案并没有让我满意。因此,我根据自己的需要实施了以下替代解决方案。

import javax.swing.JProgressBar;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;

public class MultilineProgressBar extends JProgressBar
{
    private static final String FONT_NAME = "Dialog";
    private static final int FONT_SIZE = 12;

    private static final int INTERLINE_COEFFICIENT = 2;
    private static final int NEWLINE_OFFSET = FONT_SIZE * INTERLINE_COEFFICIENT;
    private static final int CENTERING_DIVISOR = 2;


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

        final String componentString = getString();

        int i = componentString.indexOf('\n');
        if (i == -1)
            return;

        // Draw first line of the component's string
        String currentString = componentString.substring(0, i);
        Rectangle2D stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
        graphics.setFont(new Font(FONT_NAME, Font.BOLD, FONT_SIZE));
        graphics.setColor(Color.WHITE);
        graphics.drawString(currentString,
                            (int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
                            (int) (getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR);

        ++i;
        if (i >= componentString.length())
            return;

        // Draw second line of the component's string
        currentString = componentString.substring(i);
        stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
        graphics.drawString(currentString,
                            (int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
                            (int) ((getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR) + NEWLINE_OFFSET);
    }
}
于 2015-10-16T16:54:22.700 回答