Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem JavaFX - Jak vybarvit uzavřenou oblast?

Dobrý den,

Potřeboval bych vybarvit uzavřenou oblast.

Když např. nakreslím (obrázek v příloze) pomocí kódu,

Arc arc = new Arc(500, 500, 500, 500, 0, 20);
arc.setType(ArcType.OPEN);
arc.setStroke(Color.BLACK);
arc.setFill(Color.TRANSPARENT);
Arc arc1 = new Arc(400, 400, 500, 500, 0, 20);
arc1.setType(ArcType.OPEN);
arc1.setStroke(Color.BLACK);
arc1.setFill(Color.TRANSPARENT);
Line line = new Line(1000, 500, 900, 400);
Line line1 = new Line(970, 330, 870, 230);

jak vybarvím vnitřek?

V malování bych jednoduše použil fill with color, ale tady vůbec netuším.

Jak to, prosím Vás, udělám?

Děkuji

PS. Nešlo by k tomu využít CSS?

Předmět Autor Datum
Nějak mi hlava nebere ten dotaz. Čeho chceš dosáhnout? Nějaké animace vybarvení? Nebo jak mají třeba…
Kráťa 17.03.2019 23:43
Kráťa
Nakreslíš tvar pomocou Path a nastavíš výplň vo vlastnosti fill.
moose 18.03.2019 04:30
moose
To vypadá slibně. Path path = new Path(); MoveTo moveTo = new MoveTo(1000, 500); LineTo lineTo = ne…
MichalDM 18.03.2019 23:24
MichalDM
Zkusil bych tohle: MoveTo moveTo = new MoveTo(1000, 500); LineTo lineTo = new LineTo(900, 400); Arc…
Wikan 19.03.2019 07:39
Wikan
Jak jsem říkal, tu třídu jsem moc nepochopil a tvůj kód (pokud ho přidám k původnímu) zobrazí tohle…
MichalDM 19.03.2019 14:04
MichalDM
Asi jsem si spletl body: arcTo.setX(870); arcTo.setY(230);
Wikan 19.03.2019 14:16
Wikan
Aha, ty vlastně udáváš jenom koncové body. Pomocí tohoto kódu nakreslím to samé, co v zadání a naví…
MichalDM 19.03.2019 17:20
MichalDM
A proč to neuděláš cyklem?
Wikan 19.03.2019 18:23
Wikan
Aha. Já se pořád cyklu vyhýbám, ale v tomhle případě je to ideální. Position position[] = new Posit…
MichalDM 20.03.2019 16:28
MichalDM
To nevím proč se tomu vyhýbáš. Pokud se něco v kódu opakuje, je téměř vždy lepší to napsat cyklem. A…
Wikan 20.03.2019 19:50
Wikan
Nevím, odněkud jsem měl vštípenou potřebu se vyhýbat cyklu, ale to teď není podstatné. Zjednodušil…
MichalDM 20.03.2019 23:30
MichalDM
Má tam být jenom radius. Ten kruh máš rozdělený do 20 části, ne? double centerX = 500; double cente…
Wikan 21.03.2019 06:22
Wikan
Vlastně jo. Mají 18%, ale je jich 20. Ano, změnit na radius jsem to už předtím zkoušel, ale nakresl…
MichalDM 21.03.2019 14:46
MichalDM
A nechceš náhodou nakreslit terč na šipky? http://www.hameister.org/JavaFX_Dartboard.html
Wikan 21.03.2019 15:06
Wikan
Sorry, ale byl jsem zaneprázdněn a pak se to snažil vyřešit. Ale to není podstatné. Šlo mi o nakres…
MichalDM 10.05.2019 00:24
MichalDM
je vždy rozdílný a nelze ho nějak odvodit Odvodit musí jít, jak jinak bys to dokázal nakreslit? Na…
Wikan 10.05.2019 07:40
Wikan
Dobře. A jak by jste napsal metodu, která by nakreslila všechny čtyři, zadáním specifickým parametrů…
MichalDM 10.05.2019 12:32
MichalDM
Nikdo neříká, že máš vzít současnou metodu bez úprav a pustit ji čtyřikrát. Jaké klonování máš na my…
Wikan 10.05.2019 12:37
Wikan
Klonování není v tomhle případě vhodné, lepší je tohle. ... var paths = new ArrayList<Path>(20); pa…
MichalDM 10.05.2019 14:52
MichalDM
Tak jsem trochu upravil kód. ... var paths = new ArrayList<Path>(20); paths.addAll(arc(0.0, height3… poslední
MichalDM 10.05.2019 23:18
MichalDM

To vypadá slibně.

Path path = new Path();
MoveTo moveTo = new MoveTo(1000, 500);
LineTo lineTo = new LineTo(900, 400);
path.getElements().addAll(moveTo, lineTo);

Tohle se prozatím shoduje s proměnnou line v kódu výše.

Napsal jsem pouze tohle, protože nevím jak dál respektive jak nakreslit oblouk pomocí ArcTo, aby se shodoval s arc1?

Prosím o radu? Tu třídu jsem vážně nepochopil.

Díky

Aha, ty vlastně udáváš jenom koncové body.

Pomocí tohoto kódu nakreslím to samé, co v zadání a navíc to obarvím - obrázek3.

Path path = new Path();
MoveTo moveTo = new MoveTo(1000, 500);
LineTo lineTo = new LineTo(900, 400);
ArcTo arcTo = new ArcTo();
arcTo.setX(870);
arcTo.setY(230);
arcTo.setRadiusX(500);
arcTo.setRadiusY(500);
LineTo lineTo2 = new LineTo(970, 330);
ArcTo arcTo2 = new ArcTo();
arcTo2.setX(1000);
arcTo2.setY(500);
arcTo2.setRadiusX(500);
arcTo2.setRadiusY(500);
arcTo2.setSweepFlag(true);
path.setFill(Color.GREEN);
path.getElements().addAll(moveTo, lineTo, arcTo, lineTo2, arcTo2);

Jenže, když např. nakreslíš, pomocí tohohle kódu - obrázek 4.

Circle circle = new Circle(500, 500, 500, Color.TRANSPARENT);
circle.setStroke(Color.BLACK);
Line line1 = new Line(0, 500, 1000, 500);
Line line2 = new Line(500, 0, 500, 1000);
double a = 500 * Math.cos(Math.toRadians(18));
double b = 500 * Math.sin(Math.toRadians(18));
Line line3 = new Line(500 - a, 500 - b, 500 + a, 500 + b);
Line line4 = new Line(500 + a, 500 - b, 500 - a, 500 + b);
a = 500 * Math.cos(Math.toRadians(36));
b = 500 * Math.sin(Math.toRadians(36));
Line line5 = new Line(500 - a, 500 - b, 500 + a, 500 + b);
Line line6 = new Line(500 + a, 500 - b, 500 - a, 500 + b);
a = 500 * Math.cos(Math.toRadians(54));
b = 500 * Math.sin(Math.toRadians(54));
Line line7 = new Line(500 - a, 500 - b, 500 + a, 500 + b);
Line line8 = new Line(500 + a, 500 - b, 500 - a, 500 + b);
a = 500 * Math.cos(Math.toRadians(72));
b = 500 * Math.sin(Math.toRadians(72));
Line line9 = new Line(500 - a, 500 - b, 500 + a, 500 + b);
Line line10 = new Line(500 + a, 500 - b, 500 - a, 500 + b);
getChildren().addAll(circle, line1, line2, line3, line4, line5, line6, line7, line8, line9, line10);

tak obarvit všechny různými barvami, pomocí Path, je obrovský problém respektive napsat takový kód je strašně zdlouhavé.

Neexistuje, prosím Vás, nějaká jednodušší alternativa?

Díky

Aha. Já se pořád cyklu vyhýbám, ale v tomhle případě je to ideální.

Position position[] = new Position[20];
var a = 500 * Math.sin(Math.toRadians(18));
var b = 500 * Math.sin(Math.toRadians(36));
var c = 500 * Math.sin(Math.toRadians(54));
var d = 500 * Math.sin(Math.toRadians(72));
position[0] = new Position(0, 500);
position[1] = new Position(500 - d, 500 - a);
position[2] = new Position(500 - c, 500 - b);
position[3] = new Position(500 - b, 500 - c);
position[4] = new Position(500 - a, 500 - d);
position[5] = new Position(500, 0);
position[6] = new Position(500 + a, 500 - d);
position[7] = new Position(500 + b, 500 - c);
position[8] = new Position(500 + c, 500 - b);
position[9] = new Position(500 + d, 500 - a);
position[10] = new Position(1000, 500);
position[11] = new Position(500 + d, 500 + a);
position[12] = new Position(500 + c, 500 + b);
position[13] = new Position(500 + b, 500 + c);
position[14] = new Position(500 + a, 500 + d);
position[15] = new Position(500, 1000);
position[16] = new Position(500 - a, 500 + d);
position[17] = new Position(500 - b, 500 + c);
position[18] = new Position(500 - c, 500 + b);
position[19] = new Position(500 - d, 500 + a);
Path path;
MoveTo moveTo;
LineTo lineTo, lineTo2;
ArcTo arcTo;
for (int i = 0;; i++) {
    path = new Path();
    moveTo = new MoveTo(500, 500);
    lineTo = new LineTo(position[i].getX(), position[i].getY());
    arcTo = new ArcTo();
    if (i == 19) {
        i = -1;
    }
    arcTo.setX(position[i + 1].getX());
    arcTo.setY(position[i + 1].getY());
    arcTo.setRadiusX(500);
    arcTo.setRadiusY(500);
    arcTo.setSweepFlag(true);
    lineTo2 = new LineTo(500, 500);
    path.getElements().addAll(moveTo, lineTo, arcTo, lineTo2);
    path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
    getChildren().add(path);
    if (i == -1) {
        break;
    }
}

V příkladu výše kreslím pouze 10 line, tak jsem to předělal na 20, kvůli tomu cyklu. Všechny začínají na specifickém místě kružnice a končí ve středu.
To je však zhola k ničemu. Pomocí Path se kruh nakreslí "sám", takže je zbytečné do Pane (ve kterém to celé je) dávat Circle ani Line.
Navíc, Circle vůbec nepotřebuji a Line jsem nahradil vlastní třídou (Position), která pouze obsahuje x a y specifických bodů na kružnici.

Na rychlo jsem napsal náhodnou barvu. Tu bych teď neřešil, problém je, jak mám napsat ten cyklus. V každé 1/20 musím spojit obloukem bod v poli s následujícím bodem - 0 a 1, 1 a 2, 2 a 3 atd.
Problémem je 20 část, která spojuje 19 a 0 bod. V takovém případě to pochopitelně zhavaruje, protože prvek position[20] neexistuje.

Proto, v příkladu výše používám dvě podmínky, což je absurdní, jenom kvůli jedné situaci. Podmínka v hlavičce byla sice zbytečná, ale i tak mně to přijde zbytečně složité.

Je to možné, prosím Vás, nějak zjednodušit?

Děkuji

To nevím proč se tomu vyhýbáš. Pokud se něco v kódu opakuje, je téměř vždy lepší to napsat cyklem. Ale taky to pak nesmíš psát takhle zbytečně složitě.


double centerX = 500;
double centerY = 500;
MoveTo moveToCenter = new MoveTo(centerX, centerY);
double radius = 500;
double lineX = centerX + radius;
double lineY = centerY;
int steps = 20;
double step = 360.0 / steps;
for (double deg = step; deg <= 360; deg += step) {
    Path path = new Path();
    path.getElements().addAll(moveToCenter, new LineTo(lineX, lineY));
    double rad = Math.toRadians(deg);
    lineX = radius * Math.cos(rad);
    lineY = radius * Math.sin(rad);
    path.getElements().add(new ArcTo(radiusX, radiusY, 0, lineX, lineY, false, true), moveToCenter);
    path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
    getChildren().add(path);
}

Nevím, odněkud jsem měl vštípenou potřebu se vyhýbat cyklu, ale to teď není podstatné.

Zjednodušil jsem kód nejvíce co jsem byl schopen.

Váš kód vypadá mnohem jednodušeji, ale nepochopil jsem metodu step respektive proč je zrovna 20.

Navíc, nejde to ani spustit, protože tenhle řádek je špatný

path.getElements().add(new ArcTo(radiusX, radiusY, 0, lineX, lineY, false, true), moveToCenter);

Má tam být addAll, ale hlavně proměnná radiusX a radiusY neexistují.

Jak to má být, prosím Vás, správně?

Děkuji

Má tam být jenom radius.
Ten kruh máš rozdělený do 20 části, ne?

double centerX = 500;
double centerY = 500;
MoveTo moveToCenter = new MoveTo(centerX, centerY);
double radius = 500;
double lineX = centerX + radius;
double lineY = centerY;
int steps = 20;
double step = 360.0 / steps;
for (double deg = step; deg <= 360; deg += step) {
    Path path = new Path();
    path.getElements().addAll(moveToCenter, new LineTo(lineX, lineY));
    double rad = Math.toRadians(deg);
    lineX = centerX + radius * Math.cos(rad);
    lineY = centerY + radius * Math.sin(rad);
    path.getElements().addAll(new ArcTo(radius, radius, 0, lineX, lineY, false, true), moveToCenter);
    path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
    getChildren().add(path);
}

Pak si z toho můžeš udělat jednoduchou znovupoužitelnou metodu:

drawCircle(500, 500, 500, 20);

void drawCircle(double centerX, double centerY, double radius, int steps) {
    MoveTo moveToCenter = new MoveTo(centerX, centerY);
    double lineX = centerX + radius;
    double lineY = centerY;
    double step = 360.0 / steps;
    for (double deg = step; deg <= 360; deg += step) {
        Path path = new Path();
        path.getElements().addAll(moveToCenter, new LineTo(lineX, lineY));
        double rad = Math.toRadians(deg);
        lineX = centerX + radius * Math.cos(rad);
        lineY = centerY + radius * Math.sin(rad);
        path.getElements().addAll(new ArcTo(radius, radius, 0, lineX, lineY, false, true), moveToCenter);
        path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
        getChildren().add(path);
    }
}

Vlastně jo. Mají 18%, ale je jich 20.

Ano, změnit na radius jsem to už předtím zkoušel, ale nakreslilo to pěkný patvar, protože, v předchozím kódu, je špatně vypočítané lineX a lineY

Díky, ale ještě poslední otázka. Zde je pro všechny části shodný střed, ale jak musím kód upravit, aby mě uprostřed vznikl další kruh r=100, do kterého by to nezasahovalo.

Něco obdobného, jak jsem řešil na začátku. Dvě LineTo a dvě ArcTo, až na to, že ArcTo by nebyli stejně velké.

Díky

Sorry, ale byl jsem zaneprázdněn a pak se to snažil vyřešit. Ale to není podstatné.

Šlo mi o nakreslení tohohle - obrázek

Levý "oblouk je nakreslený pomocí

private static ArrayList<Path> arc(double lineX, double lineY, double moveX, double moveY) {
    var arc_big = lineY;
    var arc_small = moveY - moveX;
    LineTo lineTo = new LineTo(lineX, lineY);
    MoveTo moveToCenter = new MoveTo(moveX, moveY);
    ArrayList<Path> list = new ArrayList<>(5);
    for (double deg = 198; deg <= 270; deg += 18) {
        Path path = new Path(moveToCenter, lineTo);
        lineTo = new LineTo(lineY + arc_big * Math.cos(Math.toRadians(deg)), lineY + arc_big * Math.sin(Math.toRadians(deg)));
        path.getElements().add(new ArcTo(arc_big, arc_big, 0, lineTo.getX(), lineTo.getY(), false, true));
        MoveTo move = new MoveTo(moveY + arc_small * Math.cos(Math.toRadians(deg)), moveY + arc_small * Math.sin(Math.toRadians(deg)));
        path.getElements().add(new LineTo(move.getX(), move.getY()));
        path.getElements().add(new ArcTo(arc_small, arc_small, 0, moveToCenter.getX(), moveToCenter.getY(), false, false));
        moveToCenter = move;
        path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
        list.add(path);
    }
    return list;
}

V konstruktoru to volám

...
var paths = new ArrayList<Path>(20);
for (int i = 0; i < 4; i++) {
    paths.addAll(arc(0.0, g30, g20, g38));
}
getChildren().addAll(paths);
...

Abych to vysvětlil. Pouze levý horní oblouk je nakreslený pomocí metody a zbylé jsou pomocí čar a oblouků pro znázornění. Nakreslení všech oblouků je však složité, protože střed velké a malé "kružnice" je vždy rozdílný a nelze ho nějak odvodit. Proto jsem to chtěl vytvořit čtyřikrát na jednom místě a pak posunout a otočit. To by bylo ale zbytečně složité a ani se mi to nepodařilo.

Mnohem jednoduší by to bylo tzv. překlopit přes čáry, které jsou zde znázorněné. Navíc mně přijde cyklus nesmyslný. Lepší by bylo, kdybych zavolal metodu pouze jednou a pak to třikrát "naklonoval". Jak to, prosím Vás, udělám?

Děkuji

Dobře. A jak by jste napsal metodu, která by nakreslila všechny čtyři, zadáním specifickým parametrů, a nebyla složitá.

Ano, cyklus je jednoduchý. Ale musíte uznat, že metoda rozhodně jednoduchá není. A volat ji čtyřikrát, přitom mají všechny stejný tvar, pouze rozdílnou pozici a otočení, mně přijde nesmyslné.

Klonování jsem nikdy nepoužíval, ale proto tam přece je? Ne?

Díky

Klonování není v tomhle případě vhodné, lepší je tohle.

...
var paths = new ArrayList<Path>(20);
paths.addAll(arc(0.0, g30, g20, g38));
for (int i = 0; i < 3; i++) {
    paths.addAll(paths.stream().limit(5).collect(Collectors.toList()));
}
getChildren().addAll(paths);
...

Problémem je, že to na konci zhavaruje, protože přidávám duplicitní objekty.

A tady jsem opět u otázky, jak to dostat na požadované místo?

Tak jsem trochu upravil kód.

...
var paths = new ArrayList<Path>(20);    
paths.addAll(arc(0.0, height30, height20, height38, new Rotate()));
paths.addAll(arc(0.0, height30, height20, height38, new Rotate(90, height50, height50, height50)));
paths.addAll(arc(0.0, height30, height20, height38, new Rotate(180, height50, height50, height50)));
paths.addAll(arc(0.0, height30, height20, height38, new Rotate(270, height50, height50, height50)));
getChildren().addAll(paths);
...
private static ArrayList<Path> arc(double lineX, double lineY, double moveX, double moveY, Rotate rotate) {
    var arc_big = lineY;
    var arc_small = moveY - moveX;
    LineTo lineTo = new LineTo(lineX, lineY);
    MoveTo moveToCenter = new MoveTo(moveX, moveY);
    ArrayList<Path> list = new ArrayList<>(5);
    for (double deg = 198; deg <= 270; deg += 18) {
        Path path = new Path(moveToCenter, lineTo);
        lineTo = new LineTo(lineY + arc_big * Math.cos(Math.toRadians(deg)), lineY + arc_big * Math.sin(Math.toRadians(deg)));
        path.getElements().add(new ArcTo(arc_big, arc_big, 0, lineTo.getX(), lineTo.getY(), false, true));
        MoveTo move = new MoveTo(moveY + arc_small * Math.cos(Math.toRadians(deg)), moveY + arc_small * Math.sin(Math.toRadians(deg)));
        path.getElements().add(new LineTo(move.getX(), move.getY()));
        path.getElements().add(new ArcTo(arc_small, arc_small, 0, moveToCenter.getX(), moveToCenter.getY(), false, false));
        moveToCenter = move;
        path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
        path.getTransforms().add(rotate);
        list.add(path);    
    }
    return list;
}

Jenže, jednak nevím, jak rozumně pojmenovat proměnné a jak bych to zjednodušil.

Máte, prosím Vás, nějaký nápad?

Děkuji

PS. Proměnné, začínající height, určují % výšku obrazovky, znázorněnou číslem na konci - height50 = 50% z height

Zpět do poradny Odpovědět na původní otázku Nahoru