JScrollBar Layout Manager and SpringLayout Manager not working together - java

public void createSpringLayout(SpringLayout spring, JLabel label, JScrollPane scrollPane, JPanel buttonPanel) {
spring.putConstraint(SpringLayout.NORTH, label, 10, SpringLayout.NORTH, this);
spring.putConstraint(SpringLayout.WEST, label, 10, SpringLayout.WEST, this);
spring.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.SOUTH, label);
spring.putConstraint(SpringLayout.WEST, scrollPane, 0, SpringLayout.WEST, label);
spring.putConstraint(SpringLayout.EAST, scrollPane, -10, SpringLayout.EAST, this);
spring.putConstraint(SpringLayout.NORTH, buttonPanel, Spring.constant(10, 30, 30), SpringLayout.SOUTH, scrollPane);
spring.putConstraint(SpringLayout.SOUTH, buttonPanel, -10, SpringLayout.SOUTH, this);
spring.putConstraint(SpringLayout.WEST, buttonPanel, 0, SpringLayout.WEST, label);
}
The two Jpanels with all the stuff on them are using the same superclass for better looks.
However as you can see if the contents of the scrollpane are to wide the scrollpane just uses extra space in the bottom to create a horizontal scrollbar.
Even if I tell the Springlayout that the spring between the scrollpane and the buttonPanel can be between 10 and 30.
I think that first the SpringLayoutManager is called to layout its components and then the ScrollPane comes along and notices that its displayed Components do not fit in the Viewport and creates a Scrollbar, which the SpringLayoutManager is unaware of.
I can't find any solution tha tell the ScrollPane beforehand to calculate its needed Size or for it to just dont use more Space than it has from the beginning.

Do not pass negative numbers to putConstraint.
From the documentation of putConstraint:
Links edge e1 of component c1 to edge e2 of component c2, with a fixed distance between the edges.
The pad value is not an absolute pixel offset, it is the amount of padding (the distance) between the component and the linked edge. It should always be positive.
The same javadoc also describes the pad parameter as:
pad - the fixed distance between dependent and anchor
SpringLayout is complex, which means it’s easy to make mistakes with it. You can easily accomplish the same layout with a BorderLayout:
setLayout(new BorderLayout());
add(label, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

Related

JList disappears when added to JScrollPane

I don't know why this is happening, I've looked up nearly every Stack Overflow question regarding this.
The error is, When I add a JScrollPane to JList, Nothing shows up. Even if I'm adding it to the frame.
JList mainlist = new JList();
JScrollPane listScroller = new JScrollPane(mainlist);
listScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
listScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
mainlist.setToolTipText("List of People");
mainlist.setFont(new Font("Consolas", Font.BOLD, 13));
int pos = mainlist.getModel().getSize();
DefaultListCellRenderer renderer = (DefaultListCellRenderer)mainlist.getCellRenderer();
renderer.setHorizontalAlignment(JLabel.CENTER);
mainlist.setModel(model);
mainlist.setForeground(Color.GREEN);
mainlist.setBackground(new Color(44, 47, 51));
mainlist.setBounds(10, 108, 780, 248);
mainlist.setFixedCellHeight(20);
mainlist.setFixedCellWidth(30);
mainlist.setBorder(new EmptyBorder(10,10, 10, 10));
frm.getContentPane().add(listScroller);
You should apply bounds to your scrollPane and not Your List
listScroller.setBounds(10, 108, 780, 248);
Also make sure Your Content Pane has null layout for setBounds() to work or better just use an border layout and set the preferred&maximum Size() to what works for you

How to set the margin in GridLayout's first Column?

I want the margin from the left side in Grid layout first column only. The Jlabel in the first column is LEFT aligned.
Code for the Row is
lbl1 = new JLabel("Hold");
lbl1 .setFont(new Font("Arial Black", Font.PLAIN, text));
lbl1 .setHorizontalAlignment(SwingConstants.LEFT);
lbl1 .setForeground(Color.decode(textColor));
panel1.add(lbl1 );
lbl2= new JLabel("100");
lbl2.setFont(new Font("Arial Black", Font.PLAIN, text));
lbl2.setHorizontalAlignment(SwingConstants.CENTER);
lbl2.setForeground(Color.decode(textColor));
panel1.add(lbl2);
Code for the panel is
setLayout(new GridLayout(0,2));
In your case you can set an empty border for all your "left" label.
lb1.setBorder(new EmptyBorder(0, 10, 0, 0));
This code will provide 10 points offset from the left side of the label.
Usually GridLayout is not a best choice for your purposes. I would advise you to look for another layout manager. The standard GridBagLayout is a little bit too verbouse so it would be better to learn a third-party layout like MigLayout or FormLayout.

Jpanel is not repainting properly

I'm making a pacman game using java swing.
in my code i use 2 jpanels in the component panel
the first is for the map and the second is for the pacman.
now i am trying to move pacman to other cell when a button is clicked.it is moved but the old picture is not deleted.image before clicking, image after clicking
as you can see the new pacman appears but the old didn't disappear. and some trash also appeared.
this is the code of creating the jpanel for the pacman
JLabel pacman = new JLabel("", new ImageIcon("pacman.png"), JLabel.CENTER);
player = new JPanel(new BorderLayout());
player.setBounds(n*1, n*1, n, n);
//pacman.setOpaque(true);
pacman.setBackground(new Color(0, 0, 0, 0));
player.add(pacman);
//player.setOpaque(true);
player.setBackground(new Color(0, 0, 0, 0));
contentPane.setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(0, 0, 1000, 1000);
panel.setLayout(null);
panel.add(player);
panel.setBackground(new Color(0, 0, 0,0));
contentPane.add(panel);
the code inside the button actionPreformed method is :
panel.remove(player);
player.setLocation(new Point(n*1, n*2));
panel.add(player);
panel.revalidate();
panel.repaint();
how can i make the old pacman disappears ?
player.setBackground(new Color(0, 0, 0, 0));
Don't use transparent colors. Swing does not handle transparency properly.
For full transparency there is a simple solution. Just make the component transparent:
player.setOpaque( false );
If you ever need partial transparency then check out Backgrounds With Transparency for a solution.

GridBagLayout anchor & JScrollPane issues

I have the following class
public class Demo {
private JFrame mainFrame;
static public Color BGCOLOUR1 = new Color(240, 240, 240);
public Demo() {
mainFrame = new JFrame("Demo");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLayout(new BorderLayout());
mainFrame.setSize(900, 800);
JPanel centralPanel = new JPanel();
centralPanel.setOpaque(true);
centralPanel.setBackground(BGCOLOUR1);
centralPanel.setLayout(new GridBagLayout());
centralPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20),
BorderFactory.createTitledBorder("Panel")));
JPanel insidePanel = new JPanel();
insidePanel.setOpaque(true);
insidePanel.setBackground(BGCOLOUR1);
insidePanel.setLayout(new BorderLayout());
insidePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Inside panel"),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
JTextArea insidePanelText = new JTextArea(6, 50);
insidePanelText.setLineWrap(true);
insidePanel.add(insidePanelText);
centralPanel.add(insidePanel, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0));
JScrollPane scrollPane = new JScrollPane(centralPanel);
mainFrame.add(scrollPane);
}
Why is the inside panel positioned in the centre of the centralPanel (vertically) when I set the GridBagConstraints anchor to NORTH? I would like it positioned at the top.
Also, if I add the centralPanel in a JScrollPane before adding it to the mainFrame as per the example I can resize the application larger just fine, but as soon as I resize it smaller (even though it is still larger than I originally started it) a scroll bar appears. How can I prevent that from happening?
Edit: To illustrate the scrolling problem (I packed the frame when I took these screens):
When I start the application it has no scrollbars
I resize the window larger, and then smaller again. As soon as I make it smaller, the scrollbar appears.
As far as GridBagLayout is concerned, based on the properties you've supplied, it is been laid out to the NORTH of the cell.
GridBagLayout works mostly to the preferred size of the components and calculates the positions of each component around the center of the parent container.
If, instead of:
new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)
I use something like:
new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)
it will produce the desired result.
Basically, by using gridy and setting it to 1, we're asking GridBagLayout to give all the remaining vertical space to this cell, but because we're not filling the cell, the contents is pushed to the NORTH of the cell
Also, if I add the centralPanel in a JScrollPane before adding it to the mainFrame as per the example I can resize the application larger just fine, but as soon as I resize it smaller (even though it is still larger than I originally started it) a scroll bar appears. How can I prevent that from happening?
I couldn't really replicate this particular problem, I could use either pack or setSize and resized the window smaller to its "packed" size and the scroll bars would appear, but once I resized the window beyond the "packed" size the scroll bars would disappear

Swing Draw 1px border lines between components in a GridBagLayout component

I have components laid out in a GridBagLayout. I want a 1px black line between all the components, as well as around the JPanel itself.
Currently, I am using a MatteBorder to do this. The parent component has a 1px MatteBorder on the top and left edges. Each child component has a 1px MatteBorder on the right and bottom edges. The horizontal and vertical gaps are zero on the GridBagLayout.
This mostly works, except I'm getting occasional gaps where the child borders meet the parent border.
I suspect this is due to a rounding/floating point inaccuracy in the distribution of extra space to the child components.
Is there a better way to achieve this look?
Attached is a simpler example:
public class SSBGuiTest extends JDialog {
public SSBGuiTest(Frame owner) {
super(owner);
initComponents();
}
public SSBGuiTest(Dialog owner) {
super(owner);
initComponents();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
wrapperPanel = new JPanel();
panelWithTopLeftMatteBorder = new JPanel();
panel1 = new JPanel();
label1 = new JLabel();
panel2 = new JPanel();
label2 = new JLabel();
panel3 = new JPanel();
label3 = new JLabel();
//======== this ========
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
//======== wrapperPanel ========
{
wrapperPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
wrapperPanel.setLayout(new BorderLayout());
//======== panelWithTopLeftMatteBorder ========
{
panelWithTopLeftMatteBorder.setBorder(new MatteBorder(1, 1, 0, 0, Color.black));
panelWithTopLeftMatteBorder.setLayout(new GridBagLayout());
((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).columnWidths = new int[] {0, 0};
((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).rowHeights = new int[] {0, 0, 0, 0};
((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).columnWeights = new double[] {1.0, 1.0E-4};
((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).rowWeights = new double[] {1.0, 1.0, 1.0, 1.0E-4};
//======== panel1 ========
{
panel1.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
panel1.setLayout(new BorderLayout());
//---- label1 ----
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setText("label1");
panel1.add(label1, BorderLayout.CENTER);
}
panelWithTopLeftMatteBorder.add(panel1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
//======== panel2 ========
{
panel2.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
panel2.setLayout(new BorderLayout());
//---- label2 ----
label2.setHorizontalAlignment(SwingConstants.CENTER);
label2.setText("label2");
panel2.add(label2, BorderLayout.CENTER);
}
panelWithTopLeftMatteBorder.add(panel2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
//======== panel3 ========
{
panel3.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
panel3.setLayout(new BorderLayout());
//---- label3 ----
label3.setHorizontalAlignment(SwingConstants.CENTER);
label3.setText("label3");
panel3.add(label3, BorderLayout.CENTER);
}
panelWithTopLeftMatteBorder.add(panel3, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
}
wrapperPanel.add(panelWithTopLeftMatteBorder, BorderLayout.CENTER);
}
contentPane.add(wrapperPanel, BorderLayout.CENTER);
pack();
setLocationRelativeTo(getOwner());
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JPanel wrapperPanel;
private JPanel panelWithTopLeftMatteBorder;
private JPanel panel1;
private JLabel label1;
private JPanel panel2;
private JLabel label2;
private JPanel panel3;
private JLabel label3;
// JFormDesigner - End of variables declaration //GEN-END:variables
}
Which looks like this:
I think I'd use BorderFactory.createLineBorder(color, thickness) rather than ...matteBorder, since LineBorder seems to be a bit closer to what you're looking to do. As a convenience, you could also use LineBorder.createBlackLineBorder().
If the outsides of some components aren't quite hitting the insides of their containers, check that the containers (i.e. outer components) don't have non-zero insets set!
An alternate solution might be to let your background container have a black background and 1 pixel insets, and place non-bordered components on it with 1 pixel gaps between them. That should result in very precise black lines everywhere you don't have a component on top, and also eliminates the problem of multiple borders meeting up and resulting in a double-width border.
Finally, it looks to me like you're using components to draw tables. Do you need these components to have behavior of some sort, or would it be fine to really just put tables on your components? You could do this pretty conveniently using e.g. JLabels JTextPanels and setting their text properties to HTML for whatever you'd like to display. Java incorporates a fairly sophisticated HTML layout engine which even handles a goodly subset of CSS, either inline or even from a href'd file.

Categories

Resources