繁体   English   中英

JavaFX Chart轴标签格式

[英]JavaFX Chart axis label formatting

我写了一个简单的程序来监控我的ping。 我目前正在使用具有自动量程的NumberAxis ,并且在每次ping之后,我在末尾添加新数据,删除第一个并为X轴位置增加totalCount变量。

我想要X轴标签:

  • 显示自开始以来经过的时间。 因此,例如,以0.25s ping间隔进行第1100次ping的标签将是4m 35s
  • 显示自ping以来的时间。 这将要求标签保持静态(不随绘图移动)并且顺序相反。

这两个中的任何一个(最好是第一个)是否可以实现? 我想我必须使用CategoryAxis ,但我不确定如何创建无限数量的类别,并选择只显示完整的分钟。 是否可以保留NumberAxis以便更容易地使用传入数据并只更改标签文本格式? 我已经有一个将秒转换为00h 00m 00s格式的方法。

另外一件事,我认为与自动量程相关,图表在每次输入后都不刷新,但只有一次超过给定范围的10%。 因此对于图片中的1000范围,它将绘制100个新的ping,然后将所有100个位置向左移动。 只需1次ping就能以某种方式改变它吗?

平

不确定是否相关,但我会发布代码:

调节器

public class GuiController implements Initializable {

@FXML
Button startButton, stopButton;
@FXML
TextField sField, nField, ipField;
@FXML
LineChart<Integer, Integer> chart;
@FXML
Label timeLabel, pingLabel;

ScheduledService<Integer> scheduler;
ObservableList<Data<Integer, Integer>> data;
public static int totalCount = 0;

private String getTime(double seconds) {
    int h = (int) (seconds / 3600);
    int m = (int) ((seconds % 3600) / 60);
    int s = (int) (seconds % 60);
    return String.format("%dh %dm %ds", h, m, s);
}

public void start() {
    if (sField.getText().isEmpty() || Double.parseDouble(sField.getText()) == 0)
        sField.setText("0.1");
    data = FXCollections.observableArrayList();
    int size = Integer.parseInt(nField.getText());
    stop = false;
    flip();
    XYChart.Series<Integer, Integer> series = new Series<>();
    for (int i = 0; i < size; i++) {
        series.getData().add(new XYChart.Data<Integer, Integer>(totalCount++, 0));
    }
    chart.getData().clear();
    chart.getData().add(series);
    scheduler.setPeriod(Duration.seconds(Double.parseDouble(sField.getText())));
    scheduler.setOnSucceeded(new EventHandler<WorkerStateEvent>() {

        @Override
        public void handle(WorkerStateEvent event) {
            if (series.getData().size() >= size)
                series.getData().remove(0);
            series.getData().add(new XYChart.Data<>(totalCount++, scheduler.getValue()));
            updatePingLabel(scheduler.getValue());
        }
    });
    scheduler.restart();
}

public void stop() {
    scheduler.cancel();
    stop = true;
    flip();
    totalCount = 0;
}

public static boolean isNumeric(String str) {
    return str.matches("?\\d+(\\.\\d+)?");
}

public void flip() {
    ipField.setDisable(!ipField.isDisabled());
    nField.setDisable(!nField.isDisabled());
    sField.setDisable(!sField.isDisabled());
    startButton.setDisable(!startButton.isDisabled());
    stopButton.setDisable(!stopButton.isDisabled());
}

public void updatePingLabel(int ping) {
    pingLabel.setText(ping + "ms");
    if (ping < 80)
        pingLabel.setTextFill(Color.LAWNGREEN);
    if (ping >= 80 && ping < 150)
        pingLabel.setTextFill(Color.GOLD);
    if (ping >=150 && ping < 400)
        pingLabel.setTextFill(Color.ORANGE);
    if (ping >= 400)
        pingLabel.setTextFill(Color.RED);
}


@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    chart.getXAxis().setVisible(false);
    chart.getXAxis().setAutoRanging(true);
    stopButton.setDisable(true);
    chart.getYAxis().setAutoRanging(true);
    sField.textProperty().addListener(new ParamsChangeListener());
    nField.textProperty().addListener(new ParamsChangeListener());
    scheduler = new ScheduledService<Integer>() {
        @Override
        protected Task<Integer> createTask() {
            return new PingTask(ipField.getText());
        }
    };
}

class ParamsChangeListener implements ChangeListener<String> {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue,
            String newValue) {
        if (isNumeric(newValue))
            timeLabel.setText(getTime(Double.parseDouble(sField.getText())
                    * Integer.parseInt(nField.getText())));
    }
}
}

Ping任务

public class PingTask extends Task<Integer> {

int time;

String address;

public PingTask(String text) {
    address = text;
}

@Override
protected Integer call() throws Exception {
    try {
        String cmd = "";
        if (System.getProperty("os.name").startsWith("Windows")) {
            cmd = "ping -n 1 " + address;
        } else {
            cmd = "ping -c 1 " + address;
        }
        Process process = Runtime.getRuntime().exec(cmd);
        process.waitFor();
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String inputLine = in.readLine();
        while ((inputLine != null)) {
            if (inputLine.startsWith("Reply from")) {
                String[] parts = inputLine.split("[ =ms]");
                time = Integer.parseInt(parts[9]);
                break;
            }
            inputLine = in.readLine();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return time;
}
}

FXML

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.GuiController">
<center>
  <LineChart fx:id="chart" alternativeRowFillVisible="false" animated="false" createSymbols="false" horizontalZeroLineVisible="false" legendVisible="false" maxHeight="1.7976931348623157E308" verticalGridLinesVisible="false" verticalZeroLineVisible="false" BorderPane.alignment="CENTER">
    <xAxis>
      <NumberAxis animated="false" forceZeroInRange="false" minorTickCount="0" minorTickLength="0.0" minorTickVisible="false" side="BOTTOM" tickMarkVisible="false" tickUnit="1.0" upperBound="200.0" />
    </xAxis>
    <yAxis>
      <NumberAxis animated="false" autoRanging="false" forceZeroInRange="true" minorTickCount="0" minorTickLength="0.0" minorTickVisible="false" side="LEFT" tickLabelGap="5.0" tickUnit="20.0" />
    </yAxis>
  </LineChart>
</center>
<left>
  <VBox alignment="TOP_CENTER" spacing="10.0" BorderPane.alignment="CENTER">
     <children>
        <HBox alignment="CENTER" VBox.vgrow="NEVER">
           <children>
              <Label text="IP " />
              <TextField fx:id="ipField" prefWidth="100.0" text="euw.leagueoflegends.com">
                 <opaqueInsets>
                    <Insets />
                 </opaqueInsets>
              </TextField>
           </children>
           <padding>
              <Insets top="5.0" />
           </padding>
        </HBox>
        <HBox alignment="CENTER" VBox.vgrow="NEVER">
           <children>
              <Label text="Ping co " />
              <TextField fx:id="sField" alignment="TOP_RIGHT" prefWidth="60.0" text="0.25" HBox.hgrow="NEVER">
                 <HBox.margin>
                    <Insets right="5.0" />
                 </HBox.margin>
              </TextField>
              <Label text="s" />
           </children>
           <padding>
              <Insets top="5.0" />
           </padding>
        </HBox>
        <HBox alignment="CENTER">
           <children>
              <Label text="Rysuj " />
              <TextField fx:id="nField" alignment="CENTER_RIGHT" prefWidth="60.0" text="1000" HBox.hgrow="NEVER" />
              <Label text=" próbek" />
           </children>
           <padding>
              <Insets top="5.0" />
           </padding>
        </HBox>
        <HBox alignment="CENTER" VBox.vgrow="NEVER">
           <children>
              <Label text="Pokaż  " />
              <Label fx:id="timeLabel" text="0h 4m 10s" />
           </children>
        </HBox>
        <HBox alignment="CENTER" spacing="10.0" VBox.vgrow="NEVER">
           <children>
              <Button fx:id="startButton" mnemonicParsing="false" onAction="#start" prefWidth="50.0" text="Start" />
              <Button fx:id="stopButton" mnemonicParsing="false" onAction="#stop" prefWidth="50.0" text="Stop" />
           </children>
        </HBox>
        <Label fx:id="pingLabel" text="0ms" textAlignment="CENTER">
           <font>
              <Font name="System Bold" size="40.0" />
           </font>
        </Label>
     </children>
     <padding>
        <Insets left="5.0" right="5.0" />
     </padding>
  </VBox>
 </left>
 </BorderPane>

编辑

我尝试使用格式化程序,但我得到ClassCastException: java.lang.Double cannot be cast to java.lang.Integer在application.GuiController $ XAxisLabelConverter.toString(GuiController.java:1)中强制转换ClassCastException: java.lang.Double cannot be cast to java.lang.Integer而我不知道该怎么做做它。

    class XAxisLabelConverter extends StringConverter<Integer> {

    double interval;
    int n;

    public XAxisLabelConverter(double interval, int n) {
        this.interval = interval;
        this.n = n;
    }

    @Override
    public Integer fromString(String arg0) {

        return null;
    }

    @Override
    public String toString(Integer value) {
        if (value < n) {
            return "";
        } else {
            return getTime(value.intValue() * interval);
        }
    }

}

start()方法中

    ((ValueAxis<Integer>) chart.getXAxis()).setTickLabelFormatter(new XAxisLabelConverter(
            Double.parseDouble(sField.getText()),size));

您可以将格式化程序添加到数字轴

您可能只想删除x轴。 它并没有真正添加任何信息。 如果你只是显示相隔0.25秒的最后100个ping,那么你真的不需要轴知道它们何时发生。

由于轴的范围,图表仅在100次ping后移动。 间隔取决于总范围。 更改此设置的唯一方法是关闭自动范围并自行设置max,min,size。 你可以使用这个构造函数

如果你想格式化,你需要一个专门的转换器,因为你需要修改数字。 Chart <..,Number>需要将Number转换为String,因此请使用StringConverter<Number> ,例如。

    xAxis.setTickLabelFormatter(new StringConverter<Number>() {
        @Override
        public String toString(Number object) {
            return (object.intValue() * 0.25) + "s";
        }

        @Override
        public Number fromString(String string) {
            return 0;
        }
    });

PS。 我只在Windows上使用它,但你可以看到它是否比新进程更好。

http://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#isReachable(int)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM