Layout Manager and Positioning
Asked Answered
C

1

6
  • how to stick JLabel in GlassPane to rellative, floating coordinates from JProgressBar without using ComponentListener or another listener,

  • is there built_in notifiers in Standard LayoutManagers that can notify about its internal state, and can be accesible for override, instead my attempt with ComponentListener and NullLayout

enter image description here

.

enter image description here

SSCCE about ComponentListener and with NullLayout

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://mcmap.net/q/1467516/-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(),
                        progressSeven.getPreferredSize().width,
                        label.getPreferredSize().height);
            }
        });
        progressSeven.setValue(7);
        frame.add(progressSeven);
        label = new JLabel();
        label.setText("<html>Blablabla, Blablablabla<br>"
                + "Blablabla, Blablablabla<br>"
                + "Blablabla, Blablablabla</html>");
        label.setPreferredSize(new Dimension(
                progressSeven.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();
    }
}
Cephalonia answered 21/8, 2013 at 11:18 Comment(3)
layoutContainer() can be overridden to fire an event that could be listened by a custom layout manager for the glass pane. I'm not sure if that's what you want.Bobbitt
without using ComponentListener or another listener what a weird requirement, homework? <g>Swarth
@Swarth can't I hide that ??? :-)Cephalonia
D
5

how to stick JLabel in GlassPane to rellative, floating coordinates from JProgressBar without using ComponentListener or another listener

My idea would be to wrap the two components in a container with the OverlayLayout and "play" with AlignementX/AlignementY for the relative coordinates. Then just put the wrapping container in the original hierarchy. (See my SSCCE below)

is there built_in notifiers in Standard LayoutManagers that can notify about its internal state, and can be accesible for override, instead my attempt with ComponentListener and NullLayout

There is no such contract in the LayoutManager API, hence you can't rely safely on any such mechanism. Moreover, you will face issues with standard LayoutManager because they will take your extra JLabel into account in the layout.

Imagine you use FlowLayout and you put 1 component, then your extra JLabel, then another component. When you move the extra JLabel the last component will remain "away" from the first component and you will see a gap between these two.

If this last issue is not a problem, you could simply extend FlowLayout (or any other LayoutManager), override layoutContainer and place the extra JLabel wherever you would like.

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.OverlayLayout;
import javax.swing.UIManager;

//https://mcmap.net/q/1467516/-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);
        JPanel wrappingPanel = new JPanel();
        OverlayLayout mgr = new OverlayLayout(wrappingPanel);
        wrappingPanel.setLayout(mgr);
        progressSeven = new JProgressBar(0, 100);
        progressSeven.setAlignmentX(0.0f);
        progressSeven.setAlignmentY(0.0f);
        frame.add(wrappingPanel);
        label = new JLabel();
        label.setText("<html>Blablabla, Blablablabla<br>" + "Blablabla, Blablablabla<br>" + "Blablabla, Blablablabla</html>");
        label.setAlignmentX(0.0f);
        label.setAlignmentY(0.0f);
        wrappingPanel.add(label);
        wrappingPanel.add(progressSeven);
        Container glassPane = (Container) frame.getRootPane().getGlassPane();
        glassPane.setVisible(true);
        glassPane.setLayout(new FlowLayout());
        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();
    }
}
Dexterous answered 21/8, 2013 at 13:51 Comment(3)
+1 hmmm agree, probably answering my question ....., then better, safer could be use JProgressBar as Container(as always for me), btw this question is based on my knowledges lacks on code posted there as my answer,Cephalonia
@Cephalonia There is one drawback to use JProgressBar as a container: the progress bar will stretch over the entire bounds provided so it looks pretty weird.Dexterous
bounds are side effect, caused by used LayoutManager, e.g. GBC caused the same issue for JPanel, you are right this isn't standard in Swing, quite requirements in Htlm5/JavaFXCephalonia

© 2022 - 2024 — McMap. All rights reserved.