JavaFX StackedBar Implementieren?

lam_tr

Top Contributor
Hallo zusammen,

habt ihr eine Idee wie ich die StackedBar von dem unten angehängten Foto in Javafx nachbilden kann? Ist auf der rechten Seite bei Sprint 8 oder im zweiten Bild bei Projects gemeint. An sich ist es eine Komponente von Stacked Bar CHart. Kann man da es entnehmen? Oder muss man da selber was basteln? Wenn das zweite zutrifft, wie geht man da am besten vor?

Image1_JIRA-Insiders-April16-Blog_600x-retina2x-pretty_dash.png

jira-4_1-jira-dashboard-example.png


Grüße
lam
 

dzim

Top Contributor
Also du kannst sicher so ziemlich alles ausschalten und umgestalten, so dass eine StackedBarChart so aussehen könnte, wie du möchtest. Aber ich würde es, ehrlich gesagt, eher selbst machen.
Das sollte IMHO recht leicht sein:
HBox als container (oder VBox, wenn es vertikal sein soll), kein Spacing und dann Child-Elemenente deren Breite (min+max) per Property-Binding vom Parent abgeleitet werden.
Wenn ich mal Langeweile habe, muss ich das mal glatt probieren. :D
 

lam_tr

Top Contributor
Hallo MaxG,
ich meinte schon die Komponente alleine.

@dzim
Ja an sich hast du recht, jetzt wo du es kurz ausschlüsselst, ist mir auch klar, wie einfach das ist. Du brauchst dir keine Mühe machen, ich komme zurecht, das wichtigste hast du ja schon gesagt. Vielen Dank!
 

dzim

Top Contributor
Zu spät. Ein Prototyp ist schon fertig. :D

Hier die Komponente selbst (unten ist eine Klasse für Einträge integriert)
Java:
package eu.dzim.tests.fx;

import java.util.ArrayList;
import java.util.List;

import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;

public class StackedHBox extends HBox {
   
    private static final Color[] DEFAULT_COLORS = new Color[] { Color.AQUA, Color.AZURE, Color.YELLOW, Color.LIGHTYELLOW, Color.YELLOWGREEN,
            Color.GREENYELLOW, Color.GREEN, Color.DARKGREEN, Color.ORANGERED, Color.RED };
   
    private ObservableList<Entry> entries = FXCollections.observableArrayList();
    private ObservableList<HBox> panes = FXCollections.observableArrayList();
   
    private ListChangeListener<Entry> entriesChangeListener = this::entriesChanged;
    private ListChangeListener<HBox> panesChangeListener = this::panesChanged;
   
    public StackedHBox() {
        entries.addListener(entriesChangeListener);
        panes.addListener(panesChangeListener);
    }
   
    public ObservableList<Entry> getEntries() {
        return entries;
    }
   
    private void entriesChanged(ListChangeListener.Change<? extends Entry> change) {
        while (change.next()) {
            for (Entry entry : change.getRemoved())
                removeEntry(entry);
            for (Entry entry : change.getAddedSubList())
                addEntry(entry);
        }
    }
   
    private void removeEntry(Entry entry) {
        for (HBox pane : panes) {
            if (pane.getUserData() != entry)
                continue;
            if (entry.customListener != null) {
                entries.removeListener(entry.customListener);
                entry.customListener = null;
            }
            panes.remove(pane);
        }
    }
   
    private void addEntry(final Entry entry) {
        final HBox box = new HBox();
        box.setUserData(entry);
        ListChangeListener<Entry> listener = (ListChangeListener<Entry>) change -> {
            handleListChange(entry, box);
        };
        entry.customListener = listener;
        entries.addListener(listener);
        handleListChange(entry, box);
       
        ChangeListener<Color> colorListener = (obs, o, n) -> {
            BackgroundFill fill = new BackgroundFill(getColor(entry), CornerRadii.EMPTY, new Insets(0.0, 0.0, 0.0, 0.0));
            Background bg = new Background(fill);
            box.setBackground(bg);
        };
        entry.colorListener = colorListener;
        colorListener.changed(entry.color, null, entry.getColor());
       
        Label l = new Label();
        l.textProperty().bind(entry.text);
        box.getChildren().add(l);
       
        panes.add(box);
    }
   
    private void handleListChange(final Entry entry, final HBox box) {
        List<DoubleProperty> values = new ArrayList<>();
        for (Entry e : entries) {
            values.add(e.value);
        }
        List<Observable> bindings = new ArrayList<>();
        bindings.add(widthProperty());
        bindings.addAll(values);
        DoubleBinding widthBinding = Bindings.createDoubleBinding(() -> {
            int sum = 0;
            for (Entry e : entries)
                sum += e.value.get();
            final double percentage;
            if (sum == 0)
                percentage = 0.0;
            else
                percentage = entry.value.get() / sum;
            return getWidth() * percentage;
        }, bindings.toArray(new Observable[values.size()]));
        box.minWidthProperty().bind(widthBinding);
        box.maxWidthProperty().bind(widthBinding);
    }
   
    private Color getColor(Entry entry) {
        int index = entries.indexOf(entry);
        Color color = entry.color.get() == null ? DEFAULT_COLORS[index % entries.size()] : entry.color.get();
        return color;
    }
   
    private void panesChanged(ListChangeListener.Change<? extends HBox> change) {
        while (change.next()) {
            for (HBox pane : change.getRemoved())
                getChildren().remove(pane);
            for (HBox pane : change.getAddedSubList())
                getChildren().add(pane);
        }
    }
   
    public static class Entry {
       
        private DoubleProperty value = new SimpleDoubleProperty(0.0);
        private ObjectProperty<Color> color = new SimpleObjectProperty<>(null);
        private StringProperty text = new SimpleStringProperty(null);
       
        private ListChangeListener<Entry> customListener = null;
        private ChangeListener<Color> colorListener = null;
       
        public Entry(double value) {
            this.value.set(value);
        }
       
        public Entry(double value, Color color) {
            this(value);
            this.color.set(color);
        }
       
        public Entry(double value, Color color, String text) {
            this(value, color);
            this.text.set(text);
        }
       
        public final DoubleProperty valueProperty() {
            return this.value;
        }
       
        public final double getValue() {
            return this.valueProperty().get();
        }
       
        public final void setValue(final double value) {
            this.valueProperty().set(value);
        }
       
        public final ObjectProperty<Color> colorProperty() {
            return this.color;
        }
       
        public final Color getColor() {
            return this.colorProperty().get();
        }
       
        public final void setColor(final Color color) {
            this.colorProperty().set(color);
        }
       
        public final StringProperty textProperty() {
            return this.text;
        }
       
        public final String getText() {
            return this.textProperty().get();
        }
       
        public final void setText(final String text) {
            this.textProperty().set(text);
        }
       
        public ListChangeListener<Entry> getCustomListener() {
            return customListener;
        }
       
        public void setCustomListener(ListChangeListener<Entry> customListener) {
            this.customListener = customListener;
        }
       
        public ChangeListener<Color> getColorListener() {
            return colorListener;
        }
       
        public void setColorListener(ChangeListener<Color> colorListener) {
            this.colorListener = colorListener;
        }
    }
}

Eine Kleine Main-Klasse zum Testen:
Java:
package eu.dzim.tests.fx;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class MainStack extends Application {
    @Override
    public void start(Stage stage) throws Exception {
       
        stage.setTitle("Window");
       
        StackedHBox root = new StackedHBox();
        root.getEntries().add(new StackedHBox.Entry(5.0, Color.RED, "1"));
        root.getEntries().add(new StackedHBox.Entry(20.0, Color.GREEN, "2"));
        root.getEntries().add(new StackedHBox.Entry(75.0, Color.BLUE, "3"));
       
        Scene scene = new Scene(root, 640, 100);
       
        stage.setScene(scene);
        stage.show();
    }
   
    public static void main(String[] args) {
        launch(args);
    }
}

Das Ganze sieht dann etwas so aus:
 

dzim

Top Contributor
Kann's nicht mehr editeren, daher hier ein Nachtrag: Es gibt einen Fehler in der #getColor-Methode. Hier die Angepasste Variante:
Java:
    private Color getColor(Entry entry) {
        int index = entries.indexOf(entry);
        Color color = entry.color.get() == null ? DEFAULT_COLORS[index % DEFAULT_COLORS.length] : entry.color.get();
        return color;
    }
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L JFreeChar Label für StackedBar AWT, Swing, JavaFX & SWT 3
L JFreeChart StackedBar + Line-Chart kombinieren AWT, Swing, JavaFX & SWT 4
R Swing Background Image in JFrame implementieren AWT, Swing, JavaFX & SWT 40
L JavaFX SelectionService selber implementieren AWT, Swing, JavaFX & SWT 7
ralfb1105 JavaFX AreaChart als DB Monitor implementieren AWT, Swing, JavaFX & SWT 11
D JavaFX Google API/OpenStreetMap in GUI implementieren AWT, Swing, JavaFX & SWT 1
Joker4632 JavaFX GridPane richtig implementieren AWT, Swing, JavaFX & SWT 7
Thallius Single Sign On in Java Implementieren AWT, Swing, JavaFX & SWT 6
B GridLayout - wie am besten implementieren AWT, Swing, JavaFX & SWT 3
U Buttons schräg implementieren AWT, Swing, JavaFX & SWT 4
B mouseOnEntered ( Controller richtig implementieren) AWT, Swing, JavaFX & SWT 4
R AWT QuadratListener implementieren AWT, Swing, JavaFX & SWT 17
C In Hauptfenster Programm-Klassen implementieren AWT, Swing, JavaFX & SWT 9
K Action Listener implementieren über Objekt AWT, Swing, JavaFX & SWT 14
E Swing KeyListener implementieren AWT, Swing, JavaFX & SWT 12
M KeyListener richtig implementieren AWT, Swing, JavaFX & SWT 3
E Swing JTextArea in JFrame, wie nun WindowFocusListener implementieren? AWT, Swing, JavaFX & SWT 2
S Swing Spiel Richtig/Falsch implementieren AWT, Swing, JavaFX & SWT 5
S TextArea ausgabe ohne JFrame zu implementieren AWT, Swing, JavaFX & SWT 2
S Swing JTextArea - Bild auf/ab Tasten implementieren AWT, Swing, JavaFX & SWT 4
H shell in view implementieren; menu mit keystroke unterlegen AWT, Swing, JavaFX & SWT 8
L SWT CLabel als Button implementieren? AWT, Swing, JavaFX & SWT 6
3TageBart Ebenen in Zeichen-Programm implementieren AWT, Swing, JavaFX & SWT 9
GilbertGrape ActionListener implementieren oder Eigenen für jede Komponente? AWT, Swing, JavaFX & SWT 9
R setEnabled bei eigenem Widget implementieren? AWT, Swing, JavaFX & SWT 3
S Methoden implementieren AWT, Swing, JavaFX & SWT 7
B KeyListener implementieren AWT, Swing, JavaFX & SWT 3
F Welchen Listener implementieren? AWT, Swing, JavaFX & SWT 4
S Mehrsprachigkeit in GUI implementieren AWT, Swing, JavaFX & SWT 3
F Größenänderung mittels Maus - selbst implementieren? AWT, Swing, JavaFX & SWT 3
M ActionListener implementieren AWT, Swing, JavaFX & SWT 10
J Scrolling implementieren mit JPanels AWT, Swing, JavaFX & SWT 5

Ähnliche Java Themen


Oben