How to position objects on JPanel in a circular fashion without using NullLayout?

So my problem is this: I have a class extending JProgressBar and basically it looks like a flashing circle(it also breaks into segments depending on the amount of tasks, assigned to that indicator and I need to use setUI each time I switch indicator to the next task, which is pretty bad, but it’ll do for now). I need to position 37 of those circles on a JPanel so that they form a circle of their own. Right now I do it like this:

private void addToPane(JPanel pane){
        pane.setLayout(null);
        Insets insets = pane.getInsets();
        int width = pane.getWidth();
        int height = pane.getHeight();
        Dimension size = new Dimension(30, 30);
        //Dimension mid = new Dimension(width/2, height/2);
        Dimension mid = new Dimension(200, 250);
        int r = 210;
        double revox, revoy, angle = -Math.PI/2;
        double revangle = 2*Math.PI/37;
        for(int i=1; i<38; i++){
            FlashingIndicator templabel = new FlashingIndicator();
            templabel.setPreferredSize(size);
            templabel.setUI(new ProgressIndicator(flash, 0, false));
            templabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
            indicate.add(templabel);
            revox = r*Math.cos(angle);
            revoy = r*Math.sin(angle);
            indicate.get(i - 1).setBounds(insets.left + mid.width + (int) revox, insets.top + mid.height + (int) revoy, size.width, size.height);
            pane.add(indicate.get(i - 1));
            angle-=revangle;
        }
    }

No need to say: this is pretty bad. I wanted to locate them depending on the size of the panel, but when the function is being called in createUIComponents() (I use IntelliJ Idea’s GUI builder) – the panel is not properly created yet, so getWidth() just returns 0. Using random numbers like 200 and 250 is bad for the obvious reasons. Also seems like the general consensus is: Null Layout is bad and I shouldn’t use it. So here’s the question:

Which LayoutManager should I use in order to locate indicators properly? All I can think of is GridLayout, but the way I do it now indicators nicely overlap a bit, using a grid will make it look rough. And if I can’t use managers for this – how can I make it dependnant on the size of the panel?

Right now it looks like this:

Answer

Override the paintDeterminate() method in a custom BasicProgressBarUI to render your indicator; a related example is seen here. You can scale the rendering, as shown here, in a way that fills the component; this will obviate the need for a custom layout manager internal to your component. Override getPreferredSize(), as discussed here, so that your custom progress indicator works correctly with enclosing layouts.

image

image

Leave a Reply

Your email address will not be published. Required fields are marked *