首页 > 解决方案 > JAVAFX 应用程序 UI 变得无响应

问题描述

我有一个基于 javafx 的桌面应用程序。唯一的要求是它必须连续运行 5-6 天。我处于测试阶段。

在此使用的 UI 组件:

在 6 个仪表中,3 个仪表和折线图必须在 1 秒内更新。为此,我使用了每秒更新此组件的线程。

我已经测试了这个应用程序近 3 次:

  1. 三天

  2. 26 小时(其中图表工作正常,仪表中的值正在更新,但仪表指针卡在特定值)

  3. 现在 24 小时,仪表指针在移动,但仪表值被卡住,折线图抽屉没有打开,只有汉堡包图标在变化。

日志中没有异常,UI 没有挂起,只是 Ui 组件没有响应。

我做了分析,但一切似乎都很好。我也读过这篇文章,但在他的情况下,ui 挂起,我对此没有任何问题,所有按钮都是可点击的,我可以毫无问题地更改屏幕。

重新加载后,屏幕全部恢复正常。

我用来更新组件的示例代码。

控制器

public class testGaugeController implements Initializable {

// Component
private static final int MAX_DATA_POINTS = 1000;
private int xSeriesData = 0;
private final XYChart.Series<Number, Number> series1 = new XYChart.Series<>();
private ExecutorService executor;
private final ConcurrentLinkedQueue<Number> dataQ1 = new ConcurrentLinkedQueue<>();
private NumberAxis xAxis,yAxis;
LineChart<Number, Number> lineChart;
DatabaseHandler dh = new DatabaseHandler();
Connection connect = dh.MakeConnection();
@FXML
private JFXDrawer drawer;
@FXML
private JFXHamburger burger;
@FXML
private Gauge Gauge;


/**
 * Initializes the controller class.
 *
 * @param url
 * @param rb
 */
public void initialize(URL url, ResourceBundle rb) throws IOException {
    initializeRecorder();
    start_recording();
}

private void initializeRecorder() throws IOException {
    try {
        xAxis = new NumberAxis(0, MAX_DATA_POINTS, MAX_DATA_POINTS / 100);
        xAxis.setForceZeroInRange(false);
        xAxis.setAutoRanging(true);
        xAxis.setTickLabelsVisible(true);
        xAxis.setTickMarkVisible(true);
        xAxis.setMinorTickVisible(true);
        yAxis = new NumberAxis();
        // Create a LineChart
        lineChart = new LineChart<Number, Number>(xAxis, yAxis) {
            // Override to remove symbols on each data point
            @Override
            protected void dataItemAdded(XYChart.Series<Number, Number> series, int itemIndex, XYChart.Data<Number, Number> item) {
            }
        };

        lineChart.setAnimated(false);
        lineChart.setTitle("");
        lineChart.setHorizontalGridLinesVisible(true);

        series1.setName("Test Value");
        lineChart.getData().addAll(series1);

        drawer.setSidePane(lineChart);
        drawer.setOverLayVisible(false);

    } catch (Exception e) {
    }

    HamburgerBackArrowBasicTransition burgermove = new HamburgerBackArrowBasicTransition(burger);
    burgermove.setRate(-1);
    burger.addEventHandler(MouseEvent.MOUSE_PRESSED, (evt) -> {
        burgermove.setRate(burgermove.getRate() * -1);
        burgermove.play();
        if (drawer.isShown()) {
            drawer.close();
        } else {
            drawer.open();
        }

    });
}

int count_executer_status = 0;
boolean initial_start_trend = true;
private void start_recording() {
    if (initial_start_trend) {
        initial_start_trend = false;
    } else {
        xSeriesData = 0;
        System.out.println("Clearing dataQue");
        dataQ1.clear();
        series1.getData().clear();
    }

    xAxis.setLowerBound(0);
    count_executer_status++;
    System.out.println("Cleared dataQue");
    executor = Executors.newCachedThreadPool((Runnable r) -> {
        Thread thread = new Thread(r);
        thread.setDaemon(true);
        return thread;
    });
    count_executer_status = 0;
    AddToQueue addToQueue = new AddToQueue();
    executor.execute(addToQueue);
    //-- Prepare Timeline
    prepareTimeline();
}

private class AddToQueue implements Runnable {

    String query = "SELECT test_value FROM test_data_reader ORDER BY test_data_reader_id DESC LIMIT 1";
    ResultSet rs;

    @Override
    public void run() {
        try {
            // add a item of random data to queue.
            rs = dh.getData(query, connect);
            if (rs.next()) {
                double test_value = Double.parseDouble(rs.getString("test_value"));
                dataQ1.add(test_value);
                String Record_data = "INSERT INTO `test_data_record` (`test_value`, `date_time`) VALUES( '" + rs.getString("test_value") + "', NOW());";
                dh.execute(Record_data, connect);
                Platform.runLater(() -> {
                    Gauge.setValue(test_value);
                });

            }
            xaxis_count++;
            Thread.sleep(1000);
            executor.execute(this);
        } catch (Exception ex) {
        }
    }
}}

//-- Timeline gets called in the JavaFX Main thread
private void prepareTimeline() {
    // Every frame to take any data from queue and add to chart
    new AnimationTimer() {
        @Override
        public void handle(long now) {
            addDataToSeries();
        }
    }.start();
}
int xaxis_count = 0;

private void addDataToSeries() {
    try {
        for (int i = 0; i < 20; i++) {
            //-- add 20 numbers to the plot+
            if (dataQ1.isEmpty()) {
                break;
            }
            series1.getData().add(new XYChart.Data<>(xaxis_count, dataQ1.remove()));
        }

        if (series1.getData().size() > MAX_DATA_POINTS) {
            series1.getData().remove(0, series1.getData().size() - MAX_DATA_POINTS);
        }
        // update
        xAxis.setLowerBound(xSeriesData - MAX_DATA_POINTS);
        xAxis.setUpperBound(xSeriesData - 1);
    } catch (Exception e) {
    }
}

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import com.jfoenix.controls.JFXDrawer?>
<?import com.jfoenix.controls.JFXHamburger?>
<?import eu.hansolo.medusa.Gauge?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="e913_300mt.testGaugeController">
   <children>
    <VBox prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <children>
            <HBox fx:id="sectionHeader" minHeight="-Infinity" prefHeight="50.0" prefWidth="600.0" style="-fx-background-color: #2F333E;">
            <children>
                <VBox alignment="CENTER" layoutX="10.0" layoutY="10.0" HBox.hgrow="ALWAYS" />
                <VBox alignment="CENTER" HBox.hgrow="ALWAYS" />
                <VBox alignment="CENTER" HBox.hgrow="ALWAYS" />
                <VBox alignment="CENTER" HBox.hgrow="ALWAYS" />
                <VBox alignment="CENTER" HBox.hgrow="ALWAYS">
                    <children>
                        <JFXHamburger fx:id="burger" />
                    </children>
                </VBox>
            </children>
            </HBox>
            <HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
            <children>
                <Gauge fx:id="gauge" autoScale="false" borderPaint="#0099ff" borderWidth="3.0" decimals="0" foregroundPaint="#0000000b" highlightSections="true" innerShadowEnabled="true" knobType="METAL" lcdDesign="RED" lcdFont="LCD" majorTickMarkType="PILL" majorTickSpace="250.0" markersVisible="true" maxValue="3000.0" mediumTickMarkType="TRAPEZOID" mediumTickMarksVisible="false" minorTickSpace="50.0" needleSize="THIN" needleType="VARIOMETER" shadowsEnabled="true" threshold="300.0" title="Test Gauge" unit="unit" HBox.hgrow="ALWAYS">
                    <HBox.margin>
                        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
                    </HBox.margin>
                </Gauge>
            </children>
            </HBox>
        </children>
    </VBox>
    <JFXDrawer fx:id="drawer" defaultDrawerSize="600.0" direction="RIGHT" layoutY="56.0" prefHeight="344.0" prefWidth="600.0" />
   </children>
</AnchorPane>

图书馆

  1. jfoenix-8.0.1-for-java8.jar Github
  2. fontawesomefx-8.9.jar bitbucket
  3. Medusa-8.0.jar jar- 下载

出于测试目的,我只更新一个仪表。系统配置是:

  1. 操作系统:Ubuntu 18.04 lts
  2. 处理器:英特尔酷睿 i5-8400
  3. 内存:8Gb

对此有任何想法。

标签: javajavafxfxml

解决方案


推荐阅读