Domanda

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:

Overflow in JProgressBar

Thanks


EDIT

After @mKorbel reply the result looks like this:

enter image description here

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);
È stato utile?

Soluzione

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

enter image description hereenter image description hereenter image description here

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 as Container, put there proper LayoutManager, overlay JProgressBar by JLabel

enter image description here

  • enhancements, to set EmptyBorder for JLabel, e.g. label.setBorder(new EmptyBorder(15, 15, 15, 15));

enter image description here

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

enter image description here

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)

enter image description here

Altri suggerimenti

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);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top