java - honeycomb layout in javafx (with flowpane?) -
i'm trying make honeycomb flow buttons in javafx far flowpane
so far got half working using negative vgap on flowpane, resize , make 3-4 row go 3-3-1 goes wrong
i'm trying find solution keep honeycomb layout variable amounts of buttons, far havent had success. wondering if knows solution this.
edit: here basic code have @ moment
flowpane root = new flowpane(); root.sethgap(3.0); root.setvgap(-23.0); root.setalignment(pos.center); button[] array = new button[7]; for(int = 0; <= 6; i++){ button button = new button(); button.setshape(polygon); (made polygon in same of hexagon) array[i] = button; } root.getchildren().addall(array);
predetermined columns/ rows
this bit more convenient using flowpane
place fields.
you can observe using column spans can place button
s in gridpane
: every field fills 2 columns of sqrt(3/4)
times field height; odd/even rows start @ column 0/1 respectively. every field fills 3 rows , size of column constraints alternate between 1 quarter , 1 half of field height.
example
public static gridpane createhoneycomb(int rows, int columns, double size) { double[] points = new double[12]; (int = 0; < 12; += 2) { double angle = math.pi * (0.5 + / 6d); points[i] = math.cos(angle); points[i + 1] = math.sin(angle); } polygon polygon = new polygon(points); gridpane result = new gridpane(); rowconstraints rc1 = new rowconstraints(size / 4); rc1.setfillheight(true); rowconstraints rc2 = new rowconstraints(size / 2); rc2.setfillheight(true); double width = math.sqrt(0.75) * size; columnconstraints cc = new columnconstraints(width/2); cc.setfillwidth(true); (int = 0; < columns; i++) { result.getcolumnconstraints().addall(cc, cc); } (int r = 0; r < rows; r++) { result.getrowconstraints().addall(rc1, rc2); int offset = r % 2; int count = columns - offset; (int c = 0; c < count; c++) { button b = new button(); b.setprefsize(width, size); b.setshape(polygon); result.add(b, 2 * c + offset, 2 * r, 2, 3); } } result.getrowconstraints().add(rc1); return result; }
flowpane
-like behavior
making x position depend on row child added not idea in flowpane
. instead recommend extending pane
, overriding layoutchildren
method place children @ custom positions.
in case following class used:
public class offsetpane extends pane { public interface positionfunction { public point2d getnextposition(int index, double x, double y, double width, double height); } private static final positionfunction default_function = new positionfunction() { @override public point2d getnextposition(int index, double x, double y, double width, double height) { return new point2d(x, y); } }; private final objectproperty<positionfunction> hpositionfunction; private final objectproperty<positionfunction> vpositionfunction; private objectproperty<positionfunction> createposproperty(string name) { return new simpleobjectproperty<positionfunction>(this, name, default_function) { @override public void set(positionfunction newvalue) { if (newvalue == null) { throw new illegalargumentexception(); } else if (get() != newvalue) { super.set(newvalue); requestlayout(); } } }; } public offsetpane() { this.hpositionfunction = createposproperty("hpositionfunction"); this.vpositionfunction = createposproperty("vpositionfunction"); } @override protected void layoutchildren() { super.layoutchildren(); double width = getwidth(); list<node> children = getmanagedchildren(); final int childsize = children.size(); if (childsize > 0) { int row = 0; node lastrowstart = children.get(0); node lastnode = lastrowstart; lastrowstart.relocate(0, 0); positionfunction hfunc = gethpositionfunction(); positionfunction vfunc = getvpositionfunction(); int index = 1; int columnindex = 0; while (index < childsize) { node child = children.get(index); bounds lastbounds = lastnode.getlayoutbounds(); bounds bounds = child.getlayoutbounds(); point2d pt = hfunc.getnextposition(columnindex, lastnode.getlayoutx(), lastnode.getlayouty(), lastbounds.getwidth(), lastbounds.getheight()); if (pt.getx() + bounds.getwidth() > width) { // break row lastbounds = lastrowstart.getlayoutbounds(); pt = vfunc.getnextposition(row, lastrowstart.getlayoutx(), lastrowstart.getlayouty(), lastbounds.getwidth(), lastbounds.getheight()); child.relocate(pt.getx(), pt.gety()); lastrowstart = child; row++; columnindex = 0; } else { child.relocate(pt.getx(), pt.gety()); columnindex++; } lastnode = child; index++; } } } public final positionfunction gethpositionfunction() { return this.hpositionfunction.get(); } public final void sethpositionfunction(positionfunction value) { this.hpositionfunction.set(value); } public final objectproperty<positionfunction> hpositionfunctionproperty() { return this.hpositionfunction; } public final positionfunction getvpositionfunction() { return this.vpositionfunction.get(); } public final void setvpositionfunction(positionfunction value) { this.vpositionfunction.set(value); } public final objectproperty<positionfunction> vpositionfunctionproperty() { return this.vpositionfunction; } }
double[] points = new double[12]; (int = 0; < 12; += 2) { double angle = math.pi * (0.5 + / 6d); points[i] = math.cos(angle); points[i + 1] = math.sin(angle); } polygon polygon = new polygon(points); offsetpane op = new offsetpane(); double fieldheight = 100; double fieldwidth = math.sqrt(0.75) * fieldheight; (int = 0; < 23; i++) { button button = new button(); button.setshape(polygon); button.setprefsize(fieldwidth, fieldheight); op.getchildren().add(button); } // horizontal placement right of last element op.sethpositionfunction((int index, double x, double y, double width, double height) -> new point2d(x + width, y)); // vertical position half size left/right depending on index , // 1/4 node height above bottom of last node op.setvpositionfunction((int index, double x, double y, double width, double height) -> new point2d(x + (index % 2 == 0 ? width : -width) / 2, y + height * 0.75));
Comments
Post a Comment