Question

I am trying to create a panel that can dynamically insert components based on events. The panel is row based with variable amount of components per row. However, I have problems inserting components between existing ones.

For example, if I have following layout (lines represent MigLayout cells) :

+----+----+----+  
| X1 | X2 | X3 |
+----+----+----+----+
| Y1 | Y2 | Y3 | Y4 |
+----+----+----+----+

Is it possible to create a cell between rows X and Y, to get:

+----+----+----+  
| X1 | X2 | X3 |
+----+----+----+
| Z1 |
+----+----+----+----+
| Y1 | Y2 | Y3 | Y4 |
+----+----+----+----+

I tried content.add(component, "cell 1 0, wrap"); but it inserts the component into the Y1 cell.

The only solution I have so far is to call content.add(component, "wrap", index);. However, this requires that I know a total count of preceding components.

Was it helpful?

Solution

Instead of using the "cell" concept, you could use "absolute" positioning for your cells in migLayout, and glue the cells together by referencing the coordinates of the neighbouring cells. You need to give names to your cells in order to reference them in migLayout.

Then, you can re-arrange the cells at any time by altering the name-references in the coordinates of the cells, you just need to call setComponentConstraints(...) for the affected cells.

f.i. you for insertige cell Z, you

See the miglayout demo application. some code might look like:

myPanel.add(createCell("X1"), "pos 0 0 100 100");
myPanel.add(createCell("X2"), "pos X1.x2 0 200 X1.y2");

and so on.

When you insert cell "Z",

myPanel.add(createCell("Z"), "pos 0 X1.z2 200 100");

you only need to change the y reference of Y1 from X1.y2 to Z.y2.

I did sth. similar to create a kind of multi-splitpane, and it seems to work well.

OTHER TIPS

"hidemode" constrain help you:

new MigLayout("hidemode 3","","[][][]")

There is no direct way to insert a new component, however it is fairly simple to remove and re-add all the existing components without copy-pasta. The important part in this is that wherever the original component layout is done does not have to be accessible, and you don't have to have all the layout code in more than one place.

  Map<Component,Object> constraintMap = migLayout.getConstraintMap();
  Component[] allComps = jPanel.getComponents();
  jPanel.removeAll();
  for (Component c : allComps) {
    if ( condition_to_insert ) {
      jPanel.add(insertComponent, new CC());
    } 
    jPanel.add(c, constraintMap.get(c));

  }
  migLayout.invalidateLayout(jPanel);

i'm not sure if this is the best solution, but you could re-lay the whole container again, including your new component. I don't think there's a way to insert components the way you want to.

hopefully i'm wrong.

but it shouldn't be much overhead to do this and it would occur to fast for the user to notice!

Panels and Swing components in general are not really designed for dynamic restructuring, so I think psanton's solution is probably the safest and simplest way. You can reuse the panel by calling removeAll() on it before re-adding the elements using your existing code.

If your own suggestion of using an index also works, then I'd go with that - keeping track of preceding rows in your model should be very easy to implement, and restructuring your components will be a little faster, though it's unlikely that you'll feel the difference unless you have hundreds of sub-elements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top