I can't make JScrollPane show the list of JLabels - java

What I have: there are names of fonts on my computer (fontMassive.getFont[]);
What I need: Scrollable list of JLabel components named by these fonts;
Java shows to me one String without scroll;
I tried to replace FlowLayout with BorderLayout so that JScrollPane would understand that I need scroll, but the scroll pane just disappeared.
What am I doing wrong?
import javax.swing.*;
import java.awt.*;
public class Window extends JFrame {
public Window() {
JPanel mainPanel = new JPanel();
JPanel secondaryPanel = new JPanel();
ArrayOfFonts fontMassive = new ArrayOfFonts();
//Font font = new Font("Sitka Banner",Font.PLAIN, 14);
JScrollPane scroll = new JScrollPane();
setBounds(100,100,600,600);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("FontView");
setLayout( new FlowLayout());
JLabel[] jLabels = new JLabel[fontMassive.getLength()];
for (int i = 0; i < fontMassive.getLength(); i++) {
jLabels[i] = new JLabel(fontMassive.getFont(i));
jLabels[i].setFont(new Font(fontMassive.getFont(i),Font.PLAIN, 14));;
secondaryPanel.add(jLabels[i]);
}
secondaryPanel.setLayout(new FlowLayout());
scroll.setViewportView(secondaryPanel);
mainPanel.add(scroll);
setContentPane(mainPanel);
setVisible(true);
}
}

Related

Increase a row size in Gridlayout

The above frame contains gridlayout with two rows. First row is text area,second is a panel with two checkboxes. I want to increase height of first row so that first row should be 75% of Total height and second row should be 25%. How can I do that? Here is my code snippet:
setLayout(new GridLayout(2, 0, 0, 0));
Panel text_panel = new Panel();
add(text_panel);
text_panel.setLayout(new GridLayout(1, 0, 0, 0));
JTextArea textArea = new JTextArea();
textArea.setText("text to be displayed");
JScrollPane scroll = new JScrollPane (textArea);
text_panel.add(scroll);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
Border border = BorderFactory.createLineBorder(Color.GRAY);
textArea.setBorder(border);
textArea.setFont(new Font("Arial",Font.PLAIN,12));
textArea.setCaretPosition(0);
textArea.requestFocus();
Panel checebox_panel = new Panel();
checebox_panel.setBackground(Color.WHITE);
add(checebox_panel);
checebox_panel.setLayout(new GridLayout(1, 0, 0, 0));
androidCheckBox = new JCheckBox("Open start page");
androidCheckBox.setBackground(Color.WHITE);
androidCheckBox.addItemListener(itemListener);
androidCheckBox.setSelected(true);
checebox_panel.add(androidCheckBox);
eclipseCheckBox = new JCheckBox("register for updates");
eclipseCheckBox.setBackground(Color.WHITE);
eclipseCheckBox.addItemListener(itemListener);
eclipseCheckBox.setSelected(true);
checebox_panel.add(eclipseCheckBox);
This is not possible with GridLayout. GridLayout will always use even spacing. Look into another layout manager.
Here is a good reference:
https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
With GridLayout you can't have two rows that are different sizes. Look into BoxLayout. Something like this:
JPanel content = new JPanel();
frame.getContentPane().add(content);
LayoutManager layout = new BoxLayout(content, BoxLayout.Y_AXIS);
Box boxes[] = new Box[2];
boxes[0] = Box.createHorizontalBox();
boxes[1] = Box.createHorizontalBox();
boxes[0].createGlue();
boxes[1].createGlue();
content.add(boxes[0]);
content.add(boxes[1]);
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
panel.setPreferredSize(new Dimension(500,300));
panel2.setPreferredSize(new Dimension(500,200));
boxes[0].add(panel);
boxes[1].add(panel2);
Using setPreferredSize is never optimal, but it works. This is just an example of how you could do it, I'm sure there is better ways though! ;)
"Increase a row size in Gridlayout" I came across this requirement and by trying to device a solution I got one, tried border instead grid layout. it might be helpful :)
here is the code:
import ComponentMeta.RequiredComp;
import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PromptPopup extends JDialog {
private final JScrollPane scrollPane = new JScrollPane();
private int rows;
private int cols;
private int vGap;
private int hGap;
private Map<String, Component> componentRepo;
public PromptPopup(JFrame parent) {
super(parent);
componentRepo = new HashMap<>();
this.setModalityType(ModalityType.APPLICATION_MODAL);
}
public void setComponentsDisplayStyle(int rows, int cols, int vGap, int hGap) {
this.rows = rows;
this.cols = cols;
this.vGap = vGap;
this.hGap = hGap;
}
public void setComponentReop() {
JTextField dynamicParamTextField = new JTextField();
this.componentRepo.put("COMPANY_CODE", dynamicParamTextField);
JTextField dynamicParamTextField2 = new JTextField();
this.componentRepo.put("DIST_CODE", dynamicParamTextField2);
JTextField dynamicParamTextField3 = new JTextField();
this.componentRepo.put("LOCA_CODE", dynamicParamTextField3);
JTextField dynamicParamTextField4 = new JTextField();
this.componentRepo.put("TOKEN_EXEC", dynamicParamTextField4);
}
public void initPopupUI() {
//Setting content panes layout
getContentPane().setLayout(new BorderLayout(0, 0));
//Creating a root panel(root container) to hold the child components
JPanel rootContainer = new JPanel();
rootContainer.setLayout(new BorderLayout());
//Creating header panel(header container) to hold the header components
JPanel header = new JPanel();
header.setLayout(new FlowLayout());
JLabel headerText = new JLabel("Source query parameters required ");
headerText.setForeground(Color.WHITE);
header.add(headerText);
header.setBackground(Color.BLUE);
//Creating footer panel(footer container ) to hold the footer components
JPanel footer = new JPanel();
footer.setLayout(new FlowLayout());
JButton executeWithParamsButton = new JButton("Execute with params");
executeWithParamsButton.setBackground(Color.BLACK);
executeWithParamsButton.setForeground(Color.WHITE);
JButton cancelButton = new JButton("Cancel");
cancelButton.setBackground(Color.RED);
cancelButton.setForeground(Color.WHITE);
footer.add(executeWithParamsButton);
footer.add(cancelButton);
footer.setBackground(Color.BLUE);
//Creating content panel(content container) to hold the all dynamically generated components
JPanel contentContainer = new JPanel();
GridLayout gridLayout = new GridLayout(this.rows, this.cols, this.hGap, this.vGap);
contentContainer.setLayout(gridLayout);
for (Map.Entry entry : componentRepo.entrySet()) {
JLabel dynamicParamLabel = new JLabel(entry.getKey().toString());
contentContainer.add(dynamicParamLabel);
contentContainer.add((Component) entry.getValue());
}
// Adding all the created containers to the root container one by one
rootContainer.add(header, BorderLayout.NORTH);
rootContainer.add(contentContainer, BorderLayout.CENTER);
rootContainer.add(footer, BorderLayout.SOUTH);
//Adding the root container to the scroll pane in order the view to be scrollable nno matter how many components are there.
scrollPane.setViewportView(rootContainer);
getContentPane().add(scrollPane);
}
}
And Here is output I wanted i.e The Header to be on top consuming space only based on it's components and same for the Center panel and The footer containing button controls.
output

usage of BorderLayout

I am having a problem with BorderLayout, that was set to the green JPanel side. It does not display elements on the EAST in a row order. Do I have to combine this with GridBagLayout ? Could someone advice me how should I tackle this problem?
Basically the problem is of displaying objects inside green area below when I am using
Current layout:
My aim is to achieve this layout:
public class GUILayout {
public static void main(String[] args) {
JFrame jf = new JFrame();
JButton jbO = new JButton("CSIS0396");
JButton jbl = new JButton("Final");
JButton jb2 = new JButton("2010");
JButton jb3 = new JButton("Exam");
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
JButton object_btn = new JButton("Object");
JButton oriented_btn = new JButton("Oriented");
JButton programming_btn = new JButton("Programming");
JButton and_btn = new JButton("and");
JButton java_btn = new JButton("Java");
BorderLayout layout = new BorderLayout();
panel.setLayout(layout);
panel2.setLayout(layout);
panel.add(BorderLayout.CENTER,object_btn);
panel.add(BorderLayout.WEST,oriented_btn);
panel.add(BorderLayout.WEST,programming_btn);
panel.add(BorderLayout.WEST,and_btn);
panel.add(BorderLayout.WEST,java_btn);
panel2.add(BorderLayout.NORTH, jbO);
panel2.add(BorderLayout.SOUTH, jb2);
panel2.add(BorderLayout.WEST, jbl);
panel2.add(BorderLayout.EAST, jb3);
panel.setBackground(Color.GREEN);
panel2.setBackground(Color.RED);
jf.getContentPane().add(panel);
jf.getContentPane().add(panel2, BorderLayout.EAST);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(400, 300);
jf.setVisible(true);
}
}
don't share same layout for multiple component and use box layout for left panel to positioning buttons
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUILayout {
public static void main(String[] args) {
JFrame jf = new JFrame();
JButton jbO = new JButton("CSIS0396");
JButton jbl = new JButton("Final");
JButton jb2 = new JButton("2010");
JButton jb3 = new JButton("Exam");
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
JButton object_btn = new JButton("Object");
JButton oriented_btn = new JButton("Oriented");
JButton programming_btn = new JButton("Programming");
JButton and_btn = new JButton("and");
JButton java_btn = new JButton("Java");
BorderLayout layout = new BorderLayout();
panel2.setLayout(layout);
panel.setLayout( new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(object_btn);
panel.add(oriented_btn);
panel.add(programming_btn);
panel.add(and_btn);
panel.add(java_btn);
panel2.add(BorderLayout.NORTH, jbO);
panel2.add(BorderLayout.SOUTH, jb2);
panel2.add(BorderLayout.WEST, jbl);
panel2.add(BorderLayout.EAST, jb3);
panel.setBackground(Color.GREEN);
panel2.setBackground(Color.RED);
jf.setLayout(new BorderLayout());
jf.getContentPane().add(panel ,BorderLayout.WEST);
jf.getContentPane().add(panel2, BorderLayout.EAST);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(400, 300);
jf.setVisible(true);
}
}
The first problem is that you're having your panels share a layout. You must use a new BorderLayout for each of them.
The second problem is that a BorderLayout can only have one component in each constraint position. When you try to add multiple components to the WEST position, each one replaces the one that was previously in that position:
panel.add(BorderLayout.WEST,oriented_btn);
// Implicitly removes oriented_btn from panel
panel.add(BorderLayout.WEST,programming_btn);
// Implicitly removes programming_btn from panel
panel.add(BorderLayout.WEST,and_btn);
// Implicitly removes and_btn from panel
panel.add(BorderLayout.WEST,java_btn);
The solution is to put them in their own container, such as a Box or a JPanel with a GridLayout:
Box box = Box.createVerticalBox();
// Or:
//JComponent box = new JPanel(new GridLayout(0, 1));
box.add(oriented_btn);
box.add(programming_btn);
box.add(and_btn);
box.add(java_btn);
panel.add(BorderLayout.WEST, box);

How to get a JScrollPane to resize with its parent JPanel

My question is similar to this one (How to get JScrollPanes within a JScrollPane to follow parent's resizing), but that question wasn't clear and the answer there didn't help me..
I have this SSCCE (using MigLayout):
public static final int pref_height = 500;
public static void main(String[] args) {
JPanel innerPanel = new JPanel(new MigLayout());
innerPanel.setBorder(new LineBorder(Color.YELLOW, 5));
for(int i = 0; i < 15; i++) {
JTextArea textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);
innerPanel.add(new JLabel("Notes" + i));
innerPanel.add(jsp, "span, grow");
}
JScrollPane jsp = new JScrollPane(innerPanel) {
#Override
public Dimension getPreferredSize() {
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Dimension dim = new Dimension(super.getPreferredSize().width + getVerticalScrollBar().getSize().width, pref_height);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
return dim;
}
};
jsp.setBorder(new LineBorder(Color.green, 5));
JPanel outerPanel = new JPanel();
outerPanel.setBorder(new LineBorder(Color.RED, 5));
outerPanel.add(jsp);
JFrame frame = new JFrame();
JDesktopPane jdp = new JDesktopPane();
frame.add(jdp);
jdp.setPreferredSize(new Dimension(800, 600));
frame.pack();
JInternalFrame jif = new JInternalFrame("Title", true, true, true, true);
jif.pack();
jif.add(outerPanel);
jdp.add(jif);
jif.pack();
jif.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
I want the JScrollPane to resize whenever the parent JPanel is resized. Basically, I want the green border to line up with the red border. Right now, the green border stays the same size no matter the red border (unless you resize too small).
JPanel outerPanel = new JPanel();
A JPanel uses a FlowLayout by default which always respects the size of the component added to it. As a guess, maybe you can use:
JPanel outerPanel = new JPanel( new BorderLayout() );
A BorderLayout give all the space available to the component added to the panel. By default a JInternalFrame also uses a BorderLayout. So since all the parent components of your scroll pane use a BorderLayout all the space should go to the scroll pane.
When you post a SSCCE you should post code using classes from the JDK that simulates your problem so that everybody can test your SSCCE.
I noticed this did not have an answer that uses the original layout so here is one.
In order to make the JScrollPane resize when the parent JPanel is resized you need to do two things.
1) Set the layout of the panel to grow. This can be using the following code.
new MigLayout("", //Layout Constraints
"grow", //Column Constraints
"grow"); //Row Constraints
2) Set the component to grow. This is as simple as adding an extra argument in the add() function.
add(jsp, "grow");
ExtraIn order to make the JTextArea column grow when you resize the JScrollPane you can change the layout to only make the second column change. For example
new MigLayout("", //Layout Constraints
"[/*Column 1*/][grow /*Column 2*/]", //Column Constraints
""); //Row Constraints
Also, I would recommend you use wrap instead of span to use the next row as span refers using so many columns. For example span 2 //Means use 2 columns for this component. This would mean when you add your jsp to innerPanel it would become
innerPanel.add(jsp, "wrap, grow");
Edited SSSCE
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import net.miginfocom.swing.MigLayout;
public class JSPR extends JFrame {
public static final int pref_height = 500;
public static void main(String[] args) {
JPanel innerPanel = new JPanel(new MigLayout("", "[][grow]", ""));
innerPanel.setBorder(new LineBorder(Color.YELLOW, 5));
for(int i = 0; i < 15; i++) {
JTextArea textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);
innerPanel.add(new JLabel("Notes" + i));
innerPanel.add(jsp, "wrap, grow");
}
JScrollPane jsp = new JScrollPane(innerPanel) {
#Override
public Dimension getPreferredSize() {
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Dimension dim = new Dimension(super.getPreferredSize().width + getVerticalScrollBar().getSize().width, pref_height);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
return dim;
}
};
jsp.setBorder(new LineBorder(Color.green, 5));
JPanel outerPanel = new JPanel(new MigLayout("", "grow", "grow"));
outerPanel.setBorder(new LineBorder(Color.RED, 5));
outerPanel.add(jsp, "grow");
JFrame frame = new JFrame();
JDesktopPane jdp = new JDesktopPane();
frame.add(jdp);
jdp.setPreferredSize(new Dimension(800, 600));
frame.pack();
JInternalFrame jif = new JInternalFrame("Title", true, true, true, true);
jif.pack();
jif.add(outerPanel);
jdp.add(jif);
jif.pack();
jif.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Adding elements (i.e. JLabels) outside of the set layout

As part of a project we've got to have 9 boxes, here I've just implemented alternating colors as an example in place of the images we should be using. But whilst I want these 9 JLabels in this grid layout (3,3), I also want to have a message at the top (a JLabel) that I can just centralize, like a welcoming message as well as having around four JButtons underneath? Can somebody please point me in the right direction as to how to achieve this?
Thank you!
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class HomeController extends JPanel implements MouseListener
{
HomeController()
{
setLayout(new GridLayout(3,3));
JLabel apl1 = new JLabel("");
apl1.setBackground(Color.WHITE);
apl1.setOpaque(true);
this.add(apl1);
JLabel apl2 = new JLabel("");
apl2.setBackground(Color.BLACK);
apl2.setOpaque(true);
this.add(apl2);
JLabel apl3 = new JLabel("");
apl3.setBackground(Color.WHITE);
apl3.setOpaque(true);
this.add(apl3);
JLabel apl4 = new JLabel("");
apl4.setBackground(Color.BLACK);
apl4.setOpaque(true);
this.add(apl4);
JLabel apl5 = new JLabel("");
apl5.setBackground(Color.WHITE);
apl5.setOpaque(true);
this.add(apl5);
JLabel apl6 = new JLabel("");
apl6.setBackground(Color.BLACK);
apl6.setOpaque(true);
this.add(apl6);
JLabel apl7 = new JLabel("");
apl7.setBackground(Color.WHITE);
apl7.setOpaque(true);
this.add(apl7);
JLabel apl8 = new JLabel("");
apl8.setBackground(Color.BLACK);
apl8.setOpaque(true);
this.add(apl8);
JLabel apl9 = new JLabel("");
apl9.setBackground(Color.WHITE);
apl9.setOpaque(true);
this.add(apl9);
JLabel message = new JLabel("hello world");
this.add(message);
}
}
You can combine multiple panels with different layouts. For details take a look at A Visual Guide to Layout Managers.
For example, default layout of JFrame is BorderLayout. Using BorderLayout, you can place the title at BorderLayout.NORTH, panel with buttons at BorderLayout.SOUTH and panel with grid of labels at BorderLayout.CENTER. Each panel may have its own more complex layout. For example, grid of labels is using GridLayout, and buttons panel is using FlowLayout.
Here is a very simple example based on the posted code that demonstrates this approach:
import java.awt.*;
import javax.swing.*;
public class TestGrid {
public TestGrid() {
final JFrame frame = new JFrame("Grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel(new GridLayout(3, 3));
for (int idx = 0; idx < 9; idx++) {
JLabel label = new JLabel();
label.setBackground(idx % 2 == 0 ? Color.WHITE : Color.BLACK);
label.setOpaque(true);
mainPanel.add(label);
}
mainPanel.setPreferredSize(new Dimension(200, 200));
frame.add(mainPanel, BorderLayout.CENTER);
frame.add(new JLabel("Title", JLabel.CENTER), BorderLayout.NORTH);
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton("Start"));
buttonsPanel.add(new JButton("Stop"));
frame.add(buttonsPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestGrid();
}
});
}
}

GridBagLayout within JScrollPane not resizing properly

I have a JPanel with a GridBagLayout inside of a JScrollPane. I also have an 'add' button within the JPanel which, when clicked, will be removed from the JPanel, adds a new instance of a separate component to the JPanel, then adds itself back to the JPanel. This sort of makes a growing list of components, followed by the 'add' button.
Adding new components works fine, the JPanel stretches to accommodate the new components, and the JScrollPane behaves as expected, allowing you to scroll through the entire length of the JPanel.
This is how the add works:
jPanel.remove(addButton);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
jPanel.add(new MyComponent(), c);
jPanel.add(addButton, c);
jPanel.validate();
jPanel.repaint();`
Removal works by clicking a button inside the added components themselves. They remove themselves from the JPanel just fine. However, the JPanel keeps it's stretched-out size, re-centering the list of components.
This is how removal works:
Container parent = myComponent.getParent();
parent.remove(myComponent);
parent.validate();
parent.repaint();`
The question is, why does my GridBagLayout JPanel resize when adding components, but not when removing components?
You have to revalidate and repaint the JScrollPane, here is an example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingTest {
public static void main(String[] args) {
final JPanel panel = new JPanel(new GridBagLayout());
for (int i = 0; i < 25; i++) {
JTextField field = new JTextField("Field " + i, 20);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridy = i;
panel.add(field, constraints);
}
final JScrollPane scrollPane = new JScrollPane(panel);
JButton removeButton = new JButton("Remove Field");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (panel.getComponentCount() >= 1) {
panel.remove(panel.getComponentCount() - 1);
scrollPane.revalidate();
scrollPane.repaint();
}
}
});
JFrame frame = new JFrame("Swing Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(640, 480);
frame.setLocation(200, 200);
frame.getContentPane().add(scrollPane);
frame.getContentPane().add(removeButton, BorderLayout.SOUTH);
frame.setVisible(true);
}
}

Categories

Resources