Java Swing: JScrollPane not working - java

I have a JPanel which contains some fields. The height of the JPanel is limited so I have to put a JScrollPane around it so people can scroll down.
As you can see below, it displays perfectly. But you can't scroll down (or up).
DetailPanel detail = new DetailPanel();
JScrollPane jsp = new JScrollPane(detail);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setBounds(745, 10, 235, 225);
add(jsp);
Detail panel:
private void init(){
setLayout(null);
setSize(140, 400);
int x = 5, y = 0;
for(int i = 0; i < lbls.length; i++) {
JLabel lbl = new JLabel(lbls[i]);
lbl.setBounds(x, y, 200, 25);
add(lbl);
fields[i] = new JTextField();
fields[i].setBounds(x, y+26, 200, 25);
add(fields[i]);
y+=50;
}
}

Your DetailPanel has no layout manager associated with it, which means it doesn't expand when you add children to it, which means the JScrollPane doesn't have anywhere to scroll. Either call setLayout() on your DetailPanel or override getPreferredSize() to add up the heights of its children and return a meaningful value.

I could be wrong, but I think this might be happening because DetailPanel's layout is null. What happens if you use a BoxLayout in vertical orientation and call detail.setPreferredSize(new Dimension(140,400));?

Related

Generating java swing fields based on user input

Java beginner here.
I am trying to generate Labels based on user input(take input for the number of labels to generate between 0 to 50) in a JPanel inside a JScrollPane.
The labels are generating correctly but the problem is the panel cant be scrolled down to view all the Labels.
Is it because I am using absolute layout for the panel? If yes then what might be the solution? Please guide.
Note: I made the labels using an array of 50 JLabels in a for loop. Terrible programming practice maybe but works.
Here's the code snippet
frame = new JFrame();
frame.setSize(800, 800);
frame.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(103, 37, 439, 350);
frame.getContentPane().add(scrollPane);
JPanel panel = new JPanel();
scrollPane.setViewportView(panel);
panel.setLayout(null);
JButton btnGenerateLabels = new JButton("Generate Labels");
btnGenerateLabels.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JLabel[] lab = new JLabel[50];
int y = 50;
for(int i=0; i<50; i++)
{
lab[i] = new JLabel();
lab[i].setText("Label "+(i+1));
panel.add(lab[i]);
lab[i].setBounds(180, y, 97, 25);
y += 30;
}
}
});
btnGenerateLabels.setBounds(129, 23, 152, 25);
panel.add(btnGenerateLabels);
Is it because I am using absolute layout for the panel?
Yes. Don't use a null layout. Swing was designed to be used with layout managers.
The solution is to use a layout manager, probably the GridLayout as was suggested.
After all the components have been added to the panel you then need to invoke revalidate() and repaint() on the panel. This will invoke the layout manager and each component will be given a size/location.
Scrollbars will then appear as required.

How to scroll my JPanel

I'm creating a list of bank movements with the following code. pane is a JPanel and array is an ArrayList that contains respectively amount and description data. Setting is a little icon that allow you to modify each movement.
MouseClass is a class that extends MouseAdapter that I've created to add "k" index to mouseClicked method. I'm new with java gui programming. I'd like to know if there is a quick method to add a scroll to my panel
JLabel[] movement = new JLabel[array.size()];
JLabel[] description = new JLabel[array.size()];
JLabel[] data = new JLabel[array.size()];
JLabel[] setting = new JLabel[array.size()];
System.out.println(array.size());
int i = 0;
for(int k=0; k<array.size(); k++){
movement[k] = new JLabel("");
movement[k].setForeground(SystemColor.text);
movement[k].setFont(new Font("Segoe UI", Font.PLAIN, 20));
movement[k].setBounds(17, i, 145, 30);
movement[k].setText(array.get(array.size() - k - 1).getAmount() + "€");
panel.add(movement[k]);
description[k] = new JLabel("");
description[k].setForeground(SystemColor.text);
description[k].setFont(new Font("Segoe UI", Font.PLAIN, 20));
description[k].setBounds(187, i, 274, 30);
description[k].setText(array.get(array.size() - k - 1).getDescription());
panel.add(description[k]);
data[k] = new JLabel("");
data[k].setForeground(SystemColor.text);
data[k].setFont(new Font("Segoe UI", Font.PLAIN, 20));
data[k].setBounds(478, i, 145, 30);
data[k].setText(array.get(array.size() - k - 1).getDate());
panel.add(data[k]);
setting[k] = new JLabel();
setting[k].setIcon(new ImageIcon(List.class.getResource("/it/andreavaiuso/financemanager/images/edit.png")));
setting[k].setForeground(SystemColor.text);
setting[k].setFont(new Font("Segoe UI", Font.PLAIN, 20));
setting[k].addMouseListener(new MouseClass(array.size() - k - 1) {
#Override
public void mouseClicked(MouseEvent arg0) {
Modify mdf = new Modify(this.index);
mdf.setVisible(true);
dispose();
}
});
setting[k].setBounds(640, i, 82, 30);
panel.add(setting[k]);
i += 40;
}
But I don't know how to scroll it. I've tried woth JScrollPane but don't work!
I'm sure there is a simplest way to add these items to my panel...
I've tried woth JScrollPane but don't work!
Well I see lots of code with setBounds(...) which implies you are using a null layout.
Don't use a null layout. Swing was designed to be used with layout managers. In fact the scroll pane will only work when used with a layout manager because the scroll pane needs to know the preferred size of the panel so it can determine when you use scrollbars.
I would also suggest you should also be using a JTable for something like this. It is more efficient because you don't need to create individual components for each row of data. Read the section from the Swing tutorial on How to Use Tables for more information and examples.
For a JScrollPane you need, 1 JScrollPane, 1 JList and one DefaultListModel.
First you add your items to DefaultListModel, then you add the model to the JList and then you make a JSCrollPane with passing as argument your JList
Example:
DefaultListModel model = new DefaultListModel<String>();
JList list = new JList<String>();
model.addElemenet("1");
model.addElemenet("3");
model.addElemenet("2");
list.setModel(model);
JScrollPane scrollPane = new JScrollPane(list);

JList of TextFields and JScrollPane doesn't show / Java Swing

I am trying to create a window that shows a dynamic list of textFields and
if the number of textfields is large then I want to add a scroller.
I am using GridLayout.
The problem is that the panel I added the Jlist and scroller doesn't show anything, neither the list nor the scroller. Below you will find a part of my code.
//Label
JLabel numberOfTxt = new JLabel("Please enter the number in every TextField");
int n = 11; //A random number of TextFields
firstPanel.add(numberOfTxt, BorderLayout.NORTH); //Add label to panel
JList textFieldList = new JList(); //Create a list of TextFields
for (int i = 0; i < n; i++) {
//Add TextFields to list
JTextField textField = new JTextField();
textField.setBounds(0, 0, 6, 0);
textFieldList.add(textField);
System.out.println("textFieldList" + textFieldList);
}
textFieldList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
textFieldList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
textFieldList.setVisibleRowCount(8);
//Create scroller
JScrollPane listScroller = new JScrollPane(textFieldList);
listScroller.setBounds(0, 20, 600, 600);
//Create layout for panel where the textfields will be added
if (n % 2 != 0) {
n = n + 1;
}
thirdPanel.setLayout(new GridLayout(n / 2, 2, 10, 6));
thirdPanel.add(textFieldList);
thirdPanel.setVisible(true);
//ContentPane has BoxLayout
contentPane.add(firstPanel);
contentPane.add(thirdPanel);
contentPane.repaint();
window.pack();
}
window.revalidate();
}
});
JList does not works this way. If you really need a JList of TextFields you should use ListCellRenderer (probably you don't, see p.3).
You adding textFieldList both to listScroller and thirdPanel. Probably, you should replace thirdPanel.add(textFieldList); by thirdPanel.add(listScroller);.
thirdPanel uses GridLayout, but only one control is ever added to it. You should either add TextField directly to thirdPanel (easier way), or let the JList manage them.

Overlapping components in JPanel

I have a JButton and a Point (it's motion controlled by leap motion) on the same JPanel.
However, they are overlapping with JButton on top.
Is there a way to have my Point always on top in the JPanel application window?
Here's a code snippet:
public leapPanel()
{
setLayout(null); //18-12-13
setBackground(Color.WHITE);
setVisible(true); //18-12-13
button = new JButton();
button.setBounds(100, 150, 100, 100);
button.setBackground(Color.BLACK);
add(button);
points[nPoints] = new Point(PWIDTH/2, PHEIGHT/2);
nPoints++;
listener = new leapListener(this);
controller = new Controller();
controller.addListener(listener);
}
public Dimension getPreferredSize()
{
return new Dimension(PWIDTH, PHEIGHT);
}
public void paintComponent(Graphics shape)
{
super.paintComponent(shape);
Graphics2D shaped = (Graphics2D)shape;
shaped.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for(int i=0; i<nPoints; i++)
{
shaped.setColor(Color.ORANGE);
shaped.fillOval(points[i].x, points[i].y, 12, 12);
}
}
private Point2D.Float calcScreenNorm(Hand hand, Screen screen)
/* The dot position is calculated using the screen position that the
user's hand is pointing at, which is then normalized to an (x,y)
value between -1 and 1, where (0,0) is the center of the screen.
*/
{
Vector palm = hand.palmPosition();
Vector direction = hand.direction();
Vector intersect = screen.intersect(palm, direction, true);
// intersection is in screen coordinates
// test for NaN (not-a-number) result of intersection
if (Float.isNaN(intersect.getX()) || Float.isNaN(intersect.getY()))
return null;
float xNorm = (Math.min(1, Math.max(0, intersect.getX())) - 0.5f)*2; // constrain to -1 -- 1
float yNorm = (Math.min(1, Math.max(0, (1-intersect.getY()))) - 0.5f)*2;
return new Point2D.Float(xNorm, yNorm);
} // end of calcScreenNorm()
I have a JButton and a Point (it's motion controlled by leap motion) on the same JPanel.
Not when components are on the same panel. The order of painting is to paint the component first (ie. your paintComponent() method is invoked). Then the child components of the panel are painted (ie. the button is painted). This is how Swing implements the parent/child relationship between components.
Try using two panels. The main panel will have a BorderLayout. Then you can use:
main.add(button, BorderLayout.NORTH);
main.add(leapPanel, BorderLayout.CENTER);
The other option is to try to use the OverlayLayout. It allows you to stack two components on top of one another, although I must admit I have problems controlling the exact location of components when using this layout. The basic code would be:
JPanel main = new JPanel();
main.setLayout( new OverlayLayout(main) );
JPanel buttonPanel = new JPanel();
buttonPanel.add( button );
main.add(buttonPanel);
main.add(leapPanel);
Using the OverlayLayout you may experience weird painting problems with the button. If so then check out the suggestion to override isOptimizedDrawingEnabled() from Overlap Layout.
JPanel main = new JPanel();
main.setLayout(new OverlayLayout(main));
//main.setBackground(Color.WHITE);
setSize(800, 600); //18-12-13
Container con = getContentPane();
con.setBackground(Color.WHITE);
BPanel = new buttonPanel();
panel = new leapPanel();
main.add(BPanel);
main.add(panel);
con.add(main);
This only allows me to show only BPanel on the application window.
What i need is to have both the point(panel) and button(BPanel) to be displayed on the application window with the point always on top.
Correct me if i am missing something here. Thanks!

Java GridBagLayout + Absolute Layout

I am trying to make a 3 column layout, in each column i want to be able to absolute position labels and textboxes.
Problem is that my label (jLabel2) never even gets displayed..
Here is my code:
/**
* Top JPanel (Top)
*/
JPanel pnlTop = new JPanel();
pnlTop.setBackground(new java.awt.Color(223, 223, 217));
pnlTop.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new java.awt.Color(173, 173, 166)));
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 5; // five rows
c.gridheight = 1; // one column
c.fill = GridBagConstraints.BOTH;
//c.weighty = 0.04;
add(pnlTop, c);
/**
* Top JPanel Content (Here is where i want to put absolute content)
*/
JPanel pnlTopContent = new JPanel();
pnlTopContent.setLayout(null);
jLabel2.setFont(new java.awt.Font("Lucida Grande", 1, 16)); // NOI18N
jLabel2.setText("Hello");
jLabel2.setLocation(150, 50);
pnlTopContent.add(jLabel2);
pnlTop.add(pnlTopContent);
Any ideas what i am doing wrong?
Then its showing but not in the right place
What does "right place" mean to you? Why are you even adding you label to a second panel? Why not just add the label directly to the pnlTopContent?
GridBagLayout has a constraint that allows you to position the component right/left/center of the column. Read the section from the Swing tutorial on How to Use GridBagLayout. You might want to start with the anchor constraint.
Use layout manager for pnlTopContent. Which one is right depends on what you want. Even the default FlowLayout might work. If you want to center the label, you can for example use FlowLayout with center alignment:
pnlTopContent.setLayout(new FlowLayout(FlowLayout.CENTER));

Categories

Resources