The components inside a JPanel (which has a BoxLayout) are getting resized when there's lack of space.
The JPanel is inside a JScrollPane, but because of the fact that the components get resized, the scroll bar is useless.
The JScrollPane is also content inside a JTabbedPane by the way.
Setting a minimum size and preferred size to every component doesn't fix the problem:
this.setPreferredSize(new Dimension(100,20));
this.setMinimumSize(new Dimension(100,20));
Any idea of how to deal with this?.
Screenshot of the problem:
This is how I wan't it to look like, with a fixed size:
CodePudding user response:
I took what information was visible in your image and created an example Swing GUI that displays the same information.
I don't know how my code is different from your code. I placed a JLabel
and two JTextAreas
inside of a download JPanel
. I created a main JPanel
to hold the download JPanels
.
Here's the complete runnable code I used. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class MusicDownloadGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MusicDownloadGUI());
}
private final MusicDownloadModel model;
public MusicDownloadGUI() {
this.model = new MusicDownloadModel();
}
@Override
public void run() {
JFrame frame = new JFrame("Music Download");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createMainPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBackground(Color.WHITE);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
for (Track track : model.getDownloads()) {
panel.add(createDownloadPanel(track));
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
return scrollPane;
}
private JPanel createDownloadPanel(Track track) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
panel.setBackground(Color.WHITE);
JLabel label = new JLabel(new ImageIcon(track.getAlbumCover()));
panel.add(label);
JTextArea titleArea = new JTextArea(3, 30);
titleArea.setEditable(false);
titleArea.setText(createTitleArea(track));
panel.add(titleArea);
JTextArea artistArea = new JTextArea(3, 25);
artistArea.setEditable(false);
artistArea.setText(createArtistArea(track));
panel.add(artistArea);
return panel;
}
private String createTitleArea(Track track) {
StringBuilder builder = new StringBuilder();
builder.append(track.getTitle());
builder.append(System.lineSeparator());
builder.append("Download -- ");
builder.append(track.getPercentDownloaded());
builder.append("%");
// System.out.println(builder.toString());
return builder.toString();
}
private String createArtistArea(Track track) {
StringBuilder builder = new StringBuilder();
builder.append("Artist: ");
builder.append(track.getArtist());
builder.append(System.lineSeparator());
builder.append("Duration: ");
int minutes = track.getDuration() / 60;
int seconds = track.getDuration() % 60;
builder.append(minutes);
builder.append(" minutes, ");
builder.append(seconds);
builder.append(" seconds");
builder.append(System.lineSeparator());
builder.append("Quality: ");
builder.append(track.getQuality());
return builder.toString();
}
public class MusicDownloadModel {
private final List<Track> downloads;
public MusicDownloadModel() {
this.downloads = new ArrayList<>();
Track track = new Track("Bandaga", "Otra Copa", "0.6 kbytes", 216);
track.setPercentDownloaded(42);
addDownload(track);
addDownload(new Track("Bandaga", "Ahora Dice Que Me Ama", "0.6 kbytes", 198));
addDownload(new Track("Camin", "Tu Nombre (feat. JC Reyes, El Daddy) - Remix",
"0.6 kbytes", 246));
addDownload(new Track("Bandaga", "Como Tu", "0.6 kbytes", 205));
addDownload(new Track("Pablo Alboran", "Liueve Sobre Mo Jado", "0.6 kbytes", 228));
}
public void addDownload(Track track) {
this.downloads.add(track);
}
public List<Track> getDownloads() {
return downloads;
}
}
public class Track {
private int percentDownloaded;
private final int duration;
private final String artist, quality, title;
private final BufferedImage albumCover;
public Track(String artist, String title, String quality, int duration) {
this.artist = artist;
this.title = title;
this.quality = quality;
this.duration = duration;
this.percentDownloaded = 0;
this.albumCover = new BufferedImage(40, 20, BufferedImage.TYPE_INT_RGB);
Graphics g = albumCover.getGraphics();
g.setColor(Color.BLUE);
g.fillRect(0, 0, albumCover.getWidth(), albumCover.getHeight());
g.dispose();
}
public int getPercentDownloaded() {
return percentDownloaded;
}
public void setPercentDownloaded(int percentDownloaded) {
this.percentDownloaded = percentDownloaded;
}
public int getDuration() {
return duration;
}
public String getArtist() {
return artist;
}
public String getQuality() {
return quality;
}
public String getTitle() {
return title;
}
public BufferedImage getAlbumCover() {
return albumCover;
}
}
}
CodePudding user response:
A BoxLayout respects the minimum and maximum sizes of components added to it.
By default a JPanel doesn't have a maximum size so it grows to fill the space available.
So one solution is to override the getMaximumSize()
method of the panel to be equal to the preferred size.
a) Run the code as is below to see the default behavour. Click the "Add Row" button to see how the layout changes as rows are added.
b) Then repeat after changing the getMaximumSize()
method to use the preferred size.
import java.awt.*;
import javax.swing.*;
public class BoxLayoutRow extends JPanel
{
private int rowIndex;
private JPanel rowPanel;
public BoxLayoutRow()
{
setLayout( new BorderLayout() );
rowPanel = new JPanel();
rowPanel.setLayout( new BoxLayout(rowPanel, BoxLayout.Y_AXIS) );
add(new JScrollPane(rowPanel), BorderLayout.CENTER);
JButton addRow = new JButton("Add Row");
add(addRow, BorderLayout.PAGE_END);
addRow.addActionListener((e) -> this.addRow());
}
private void addRow()
{
rowIndex ;
JPanel row = new JPanel()
{
@Override
public Dimension getMaximumSize()
{
return super.getMaximumSize();
//return getPreferredSize();
}
};
row.setAlignmentX(0.0f);
row.add( new JLabel("Row: " rowIndex) );
row.setBorder(BorderFactory.createLineBorder(Color.RED));
rowPanel.add( row );
revalidate();
repaint();
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("BoxLayoutRow");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new BoxLayoutRow() );
frame.setSize(400, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(() -> createAndShowUI());
}
}