2014-12-04 3 views
4

Есть ли способ установить ширину столбца ширины столбца JavaFX?Set Bar Chart column width size

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.chart.BarChart; 
import javafx.scene.chart.CategoryAxis; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart; 
import javafx.stage.Stage; 

public class BarChartSample extends Application { 
    final static String austria = "Austria"; 
    final static String brazil = "Brazil"; 
    final static String france = "France"; 
    final static String italy = "Italy"; 
    final static String usa = "USA"; 

    @Override public void start(Stage stage) { 
     stage.setTitle("Bar Chart Sample"); 
     final CategoryAxis xAxis = new CategoryAxis(); 
     final NumberAxis yAxis = new NumberAxis(); 
     final BarChart<String,Number> bc = 
      new BarChart<String,Number>(xAxis,yAxis); 
     bc.setTitle("Country Summary"); 
     xAxis.setLabel("Country");  
     yAxis.setLabel("Value"); 

     XYChart.Series series1 = new XYChart.Series(); 
     series1.setName("2003");  
     series1.getData().add(new XYChart.Data(austria, 25601.34)); 
     series1.getData().add(new XYChart.Data(brazil, 20148.82)); 
     series1.getData().add(new XYChart.Data(france, 10000)); 
     series1.getData().add(new XYChart.Data(italy, 35407.15)); 
     series1.getData().add(new XYChart.Data(usa, 12000));  

     XYChart.Series series2 = new XYChart.Series(); 
     series2.setName("2004"); 
     series2.getData().add(new XYChart.Data(austria, 57401.85)); 
     series2.getData().add(new XYChart.Data(brazil, 41941.19)); 
     series2.getData().add(new XYChart.Data(france, 45263.37)); 
     series2.getData().add(new XYChart.Data(italy, 117320.16)); 
     series2.getData().add(new XYChart.Data(usa, 14845.27)); 

     XYChart.Series series3 = new XYChart.Series(); 
     series3.setName("2005"); 
     series3.getData().add(new XYChart.Data(austria, 45000.65)); 
     series3.getData().add(new XYChart.Data(brazil, 44835.76)); 
     series3.getData().add(new XYChart.Data(france, 18722.18)); 
     series3.getData().add(new XYChart.Data(italy, 17557.31)); 
     series3.getData().add(new XYChart.Data(usa, 92633.68)); 

     Scene scene = new Scene(bc,800,600); 
     bc.getData().addAll(series1, series2, series3); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Например, есть способ setBarGap размера, но не могу найти способ, чтобы установить максимальную ширину столбца гистограммы.

Есть ли способ решить эту проблему?

+0

Что такое "свет"? –

+0

Я имею в виду ширину. Виноват. –

ответ

4

BarChart работает на том основании, что обе barGap (зазор между решеткой в ​​одной и той же категории) и categoryGap (зазор между решеткой в ​​отдельных категориях), могут быть установлены пользователем, поэтому для данного размера диаграммы, ширина бары рассчитываются внутренне каждый раз, когда запрашивается макет.

Чтобы установить максимальную ширину на каждом баре, мы должны изменить либо barGap, либо categoryGap соответственно. Но мы можем сделать это программно, чтобы реагировать на любое изменение ширины диаграммы.

Давайте сначала вычислим ширину полосы для начальной компоновки. В соответствии с BarChart.layoutPlotChildren():

double catSpace = xAxis.getCategorySpacing(); 
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap()); 
double barWidth = (avilableBarSpace/bc.getData().size()) - bc.getBarGap(); 

В примере, представленной OP, учитывая значения по умолчанию зазор (barGap=4, categoryGap=10), полученный barWidth 37,4.

Давайте предположим, что мы хотим установить предел 40, а минимальный категории зазор 10:

double maxBarWidth=40; 
double minCategoryGap=10; 

Если ширина увеличивается на графике, когда сцена изменяется, мы могли бы ограничить barWidth путем увеличения categoryGap:

double barWidth=0; 
do{ 
    double catSpace = xAxis.getCategorySpacing(); 
    double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap()); 
    barWidth = (avilableBarSpace/bc.getData().size()) - bc.getBarGap(); 
    if(barWidth > maxBarWidth){ 
     avilableBarSpace=(maxBarWidth + bc.getBarGap())* bc.getData().size(); 
     bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap()); 
    } 
} while(barWidth>maxBarWidth); 

Обратите внимание на цикл do-while: по мере изменения categoryGap выполняется новый макет, а некоторые начальные значения изменяются. Для получения желаемого результата обычно требуется две итерации.

Мы можем повторить эту операцию, пока ширина диаграммы продолжает расти.

Но если ширина Картографическая начинает уменьшаться, разрыв между категориями должна быть уменьшена также, в то время как ширина захвата жатки остается близко к своему максимуму:

double barWidth=0; 
do{ 
    double catSpace = xAxis.getCategorySpacing(); 
    double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap()); 
    barWidth = Math.min(maxBarWidth, (avilableBarSpace/bc.getData().size()) - bc.getBarGap()); 
    avilableBarSpace=(barWidth + bc.getBarGap())* bc.getData().size(); 
    bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap()); 
} while(barWidth < maxBarWidth && bc.getCategoryGap()>minCategoryGap); 

Сложив все вместе, и слушать изменения ширины сцены:

... 
    Scene scene = new Scene(bc,800,600); 
    bc.getData().addAll(series1, series2, series3); 
    stage.setScene(scene); 
    stage.show(); 

    double maxBarWidth=40; 
    double minCategoryGap=10; 

    scene.widthProperty().addListener((obs,n,n1)->{ 
     if(bc.getData().size()==0) return; 

     if(n!=null && (n1.doubleValue()>n.doubleValue())){ 
      double barWidth=0; 
      do{ 
       double catSpace = xAxis.getCategorySpacing(); 
       double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap()); 
       barWidth = (avilableBarSpace/bc.getData().size()) - bc.getBarGap(); 
       if (barWidth >maxBarWidth){ 
        avilableBarSpace=(maxBarWidth + bc.getBarGap())* bc.getData().size(); 
        bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap()); 
       } 
      } while(barWidth>maxBarWidth); 
     } 

     if(n!=null && (n1.doubleValue()<n.doubleValue()) && bc.getCategoryGap()>minCategoryGap){ 
      double barWidth=0; 
      do{ 
       double catSpace = xAxis.getCategorySpacing(); 
       double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap()); 
       barWidth = Math.min(maxBarWidth, (avilableBarSpace/bc.getData().size()) - bc.getBarGap()); 
       avilableBarSpace=(barWidth + bc.getBarGap())* bc.getData().size(); 
       bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap()); 
      } while(barWidth < maxBarWidth && bc.getCategoryGap()>minCategoryGap); 
     } 
    }); 

Обратите внимание, что в остальных случаях barWidth будет рассчитываться внутренне.

+0

Знаете ли вы, что в Java 8u60 или 9 будет установлен режим для ширины столбца? –

+0

Я не знаю об этом, и об JIRA нет никаких проблем. –

+0

Это не работает для меня. Barchart не отображается. После вызова метода setMaxBarWidth() barchart.setCategoryGap устанавливается в NaN. – mistletoe

0

В дополнение к ответу Жозе Переды. Вы можете установить ширину диаграммы в соответствии с вашим набором данных. Вместе с настройками BarGap и CategoryGap вы можете точно настроить ширину баров путем вычисления или проб и ошибок. Например, я сделал следующее, чтобы получить более тонкие бары. Я установил ширину пустого графа на 30 (для оси и метки?), А затем добавил ширину от 100 пикселей до максимальной и минимальной для каждого раунда в игре cribbage (до максимальной ширины сетки), тем самым ограничивая свободную пробел в графе для заполнения баров.

Pane barchart1 = new Pane; 
CategoryAxis xAxis = new CategoryAxis(); 
NumberAxis yAxis = new NumberAxis(0,25,1); 
BarChart<String, Number> bc1 = 
     new BarChart<String, Number>(xAxis, yAxis); 
    // create Player chart 
    bc1.setTitle(G.getPlayerName(0)); 
    bc1.setTitle(null); 
    xAxis1.setLabel("Round"); 
    yAxis1.setLabel("Points"); 
    XYChart.Series series1 = new XYChart.Series(); 
    series1.setName("Pegging"); 
    XYChart.Series series3 = new XYChart.Series(); 
    series3.setName("Hand"); 
    XYChart.Series series5 = new XYChart.Series(); 
    series5.setName("Box"); 

    for (int i = 0; i < G.getRoundsSize(); i++) { 
     series1.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getPegPoints())); 
     series3.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getHandPoints())); 
     series5.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getBoxPoints())); 
    } 
    bc1.getData(). addAll(series1, series3, series5); 
    bc1.setBarGap(0); 
    bc1.setCategoryGap(1.0); 
    bc1.setMaxHeight(180); 
    bc1.setMinHeight(180); 
    if(G.getRoundsSize() < 8){ 
     int wid = ((G.getRoundsSize() * 100) + 30); 
     bc1.setMaxWidth(wid); 
     bc1.setMinWidth(wid); 
    } else { 
     bc1.setMaxWidth(830); 
     bc1.setMinWidth(830); 
    } 
    barchart1.getChildren().add(bc1);