问题
My program writes text in a JProgressBar. The problem is the text is wider than the JProgressBar's width.
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.
How to change the JProgressBar's overflow to make the text going back to the next line if it is too wide?
I hope this is clear enough :)
Here is what I would like:

Thanks
EDIT
After @mKorbel reply the result looks like this:

The label works quite fine but why those strips?
My code:
// 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);
回答1:
the program is developed with Java 6. It seems JLayer is not available. If I'm wrong, could you provide some code on how to do this?
could you provide some code on how to do this? --- > JLayer & JProgressBar by @aterai, for more ideas see his blog, for Java6 you can to use JXLayer
or with very similair logics by using GlassPane



some notes
should be used GBC instead of NullLayout
can be nicer with added Icon or transparent background
(by add LayoutManager to JLabel) there can be placed bunch of JComponents with the same effect as for JPanel
for example
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();
}
}
EDIT
- comments
my first thought was using html, but astonishingly (for me) the progressbar doesn't support it ... by @kleopatra
and
I think my question may not be clear enough. I don't want the text to exceed the JProgressBar borders. Plus, I don't want to insert manually line returns (ie no
). I added a picture of what I want. by @Maxbester
- result is to use
JProgressBar
asContainer
, put there properLayoutManager
, overlayJProgressBar
byJLabel

- enhancements, to set
EmptyBorder
forJLabel
, e.g.label.setBorder(new EmptyBorder(15, 15, 15, 15));

EDIT2 (Icon is, can be semi_transparent too, can overlay JProgressBar)

code could be something like as
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();
}
});
}
}
EDIT3:
default stripping for WindowsClassicLookAndFeel (Icon isn't semi_transparent)

回答2:
The available answers didn't satisfy me. Thus I implemented the following alternative solution for my own needs.
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);
}
}
来源:https://stackoverflow.com/questions/18350786/jprogressbar-text-overflow