2

我正在尝试从实例对象中引用一个方法来创建一些按钮。我必须这样做以获得灵活性(根据上下文向工具栏添加按钮)。我的项目是一个 GluonFX 项目(JavaFX + Gluon 它使用 Gradle 文件进行编译)。

这是负责创建这些按钮的函数。

public void postInit() {
    ToolbarVerticalCtrl toolbar = getRoot().getToolbarCtrl();
    ChronologyViewerCtrl viewer = ((ChronologyViewerCtrl) _tabControllersMap.get(TAB_PATIENT_CHRON_ID).getUserData());

    Image iconPlot = new Image(getClass().getResource("/ch/aardex/images/48px/button_plot.png").toExternalForm());
    toolbar.addNewButtonOnToolbar(new ImageView(iconPlot), i18n("title.chronology"), viewer::switchToPlot, false, true);
    // add calendar view button
    Image iconCalendar = new Image(getClass().getResource("/ch/aardex/images/48px/button_calendar.png").toExternalForm());
    toolbar.addNewButtonOnToolbar(new ImageView(iconCalendar), i18n("title.calendar"), viewer::switchToCalendar, false, false);
    // add patient details button
    Image iconDetails = new Image(getClass().getResource("/ch/aardex/images/48px/button_patient_details.png").toExternalForm());
    toolbar.addNewButtonOnToolbar(new ImageView(iconDetails), i18n("title.patientDetails"), this::openPatientDetailsTab, false, false);
    // add print report button
    Image iconPrint = new Image(getClass().getResource("/ch/aardex/images/48px/button_print.png").toExternalForm());
    toolbar.addNewButtonOnToolbar(new ImageView(iconPrint), i18n("title.printReport"), this::printPatientReport, false, false);
    // add print report button
    Image iconDelete = new Image(getClass().getResource("/ch/aardex/images/48px/button_delete.png").toExternalForm());
    toolbar.addNewButtonOnToolbar(new ImageView(iconDelete), i18n("title.deletePatient"), viewer::deletePatient, true, false);
}

如您所见,viewer检索到的实例是 ChronologyViewerCtrl 类型。该实例不是 null

当我运行该项目时,我从 gradle 构建中得到以下错误(我只显示堆栈跟踪中最重要的行,并制作了一个 pastebin 只是因为格式很糟糕)

堆栈跟踪 => http://paste.ubuntu.com/16888255/

我在控制器中指的功能是:

public void switchToCalendar(){
    String script = "pManager.hotSwitch( aardex.plugin.CalendarAdapter.prototype.type, pManager.plot.getScaleObj() );";
    execute(script);

    getRootTab().openTab(RootTabPaneCtrl.TAB_PATIENT_CHRON_ID);
}

public void switchToPlot(){
    String script = "pManager.hotSwitch( aardex.plugin.ChronologyAdapter.prototype.type, pManager.plot.getScaleObj() );";
    execute(script);

    getRootTab().openTab(RootTabPaneCtrl.TAB_PATIENT_CHRON_ID);
}

我检查了很多帖子,清除了所有.class文件(我猜?),将public范围放在功能上,没有任何改变。想法?我快疯了。

谢谢

我正在使用的工具的编辑版本:

  • 胶子插件:2.2.0
  • 摇篮支持:1.3.8
  • JavaFX:1.8.0_73
  • NetBeans:8.0.2 补丁 2

编辑 2 ChronologyViewerCtrl 类和 Gradle 文件以防万一:

年表查看器Ctrl

package ch.aardex.viewer;

import ch.aardex.business.clean.ConfigBusiness;
import ch.aardex.business.clean.PatientBusiness;
import ch.aardex.business.util.ReportDataHelper;
import ch.aardex.common.DialogFactory;
import ch.aardex.common.GUIUtils;
import static ch.aardex.common.IController.DAY_TO_MILLI;
import ch.aardex.common.ITabController;
import ch.aardex.context.CurrentDataContext;
import ch.aardex.service.persist.model.monitoring.Device;
import ch.aardex.service.persist.model.monitoring.Event;
import ch.aardex.service.persist.model.monitoring.Patient;
import ch.aardex.service.persist.model.monitoring.PatientTimeline;
import ch.aardex.service.persist.model.monitoring.Timeline;
import ch.aardex.tabview.RootTabPaneCtrl;
import ch.aardex.viewer.EmbeddedAdherenceScripting.Scriptable;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.util.Callback;
import netscape.javascript.JSObject;
import org.apache.log4j.Logger;

public class ChronologyViewerCtrl extends ITabController implements Initializable, Scriptable {

    private static final Logger LOG = Logger.getLogger(ChronologyViewerCtrl.class);

    @FXML private WebView webView;
    @FXML private Label labelFrom, labelTo;
    @FXML private ComboBox<TimelineItem> cbTimelines;
    @FXML private DatePicker datePeriodBegin, datePeriodEnd;
    @FXML private Button btEditMode;

    private final CurrentDataContext _dataContext = CurrentDataContext.getInstance();
    private final ReportDataHelper _reportHelper = ReportDataHelper.getInstance();
    private final Device _device;
    private final JSBridge _jsBridge;

    private LocalTime _startOfDay;
    private String _json;
    private boolean isPlotEditable = false;

    public ChronologyViewerCtrl() {
        _device = _dataContext.getCurrentDevice();
        _json   = _dataContext.getCurrentJsonData();

        PatientTimeline pt = PatientTimeline.findPatientTimeline(_dataContext.getCurrentPatient());

        _reportHelper.setStartingPeriod(Event.Finder.getMonitoringBegin(pt).getEventDate().getEpochDate());

        _jsBridge = new JSBridge(this);
    }

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        //checkIfManyTimelines();

        initDatePickers();

        _startOfDay = LocalTime.ofSecondOfDay(ConfigBusiness.getInstance().getStartOfDay() / 1000);

        labelFrom.setText(_startOfDay.format(DateTimeFormatter.ofPattern("HH:mm")));
        labelTo.setText(_startOfDay.minusMinutes(1).format(DateTimeFormatter.ofPattern("HH:mm")));

        try {
            initWebView();
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * init the date pickers by disabling some days (cells) for example :
     * - Those before the monitoring begin
     * - Those adter the monitoring end
     * 
     * also adds a listener on the cells to display the plot following the selected
     * dates
     */
    private void initDatePickers(){
        datePeriodBegin.setDayCellFactory(new Callback<DatePicker, DateCell>() {

            @Override
            public DateCell call(DatePicker param) {
                DateCell cell = new DateCell() {

                    @Override
                    public void updateItem(LocalDate item, boolean empty) {
                        super.updateItem(item, empty);

                        if(item.isBefore(LocalDate.ofEpochDay(_reportHelper.getStartingPeriod() / DAY_TO_MILLI)) ||
                                item.isAfter(datePeriodEnd.getValue().minusDays(1))){
                            setDisable(true);
                            setStyle("-fx-background-color: #ffc0cb");
                        }
                    }
                };

                cell.setOnMouseClicked(new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent event) {
                        _reportHelper.setBeginPeriod(cell.getItem().toEpochDay() * DAY_TO_MILLI);

                        setDatesToJsPlot(_reportHelper.getRelativeBeginPeriod(), _reportHelper.getRelativeEndPeriod());
                    }
                });

                return cell;
            }
        });

        GUIUtils.setDatePickerFormat(datePeriodBegin);

        datePeriodEnd.setDayCellFactory(new Callback<DatePicker, DateCell>() {

            @Override
            public DateCell call(DatePicker param) {
                DateCell cell = new DateCell() {

                    @Override
                    public void updateItem(LocalDate item, boolean empty) {
                        super.updateItem(item, empty);

                        if(item.isBefore(datePeriodBegin.getValue().plusDays(1)) ||
                                item.isAfter(LocalDate.now())){
                            setDisable(true);
                            setStyle("-fx-background-color: #ffc0cb");
                        }
                    }
                };

                cell.setOnMouseClicked(new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent event) {
                        _reportHelper.setEndPeriod(cell.getItem().toEpochDay() * DAY_TO_MILLI);

                        setDatesToJsPlot(_reportHelper.getRelativeBeginPeriod(), _reportHelper.getRelativeEndPeriod());
                    }
                });

                return cell;
            }
        });

        GUIUtils.setDatePickerFormat(datePeriodEnd);
    }

    /**
     * Checks if the patient has many timelines (parallel monitoring) or only
     * one, and deactivates or not controls following the number of timelines.
     */
    private void checkIfManyTimelines(){
        // timelines management to be checked ...
        List<PatientTimeline> patientTimelines = new ArrayList<>();

        for(PatientTimeline pt : (List<PatientTimeline>) _dataContext.getCurrentPatient().getTimelines()){
            if(pt.getTimeline() != null && pt.getTimeline().getId() != -1)
                patientTimelines.add(pt);
        }

        /*
        if(patientTimelines.size() > 1){
            for(PatientTimeline t : patientTimelines){
                cbTimelines.getItems().add(new TimelineItem(t.getTimeline()));
            }
            cbTimelines.getSelectionModel().selectFirst();
        }else{
            cbTimelines.setVisible(false);
            cbTimelines.setManaged(false);
        }
        */
    }

    /**
     * init the date pickers with listeners and un-selectable dates following 
     * some rules
     */ 
    public void setDatePickersValuesFromJS(long start, long stop){
        LocalDate begin = LocalDate.ofEpochDay(start / DAY_TO_MILLI);
        LocalDate end = LocalDate.ofEpochDay(stop / DAY_TO_MILLI);

        if(begin.isAfter(end))
            end = begin.plusDays(1);

        datePeriodBegin.setValue(begin);
        datePeriodEnd.setValue(end);
    }

    /**
     * sets the period begin / end for the chronology plot, relative to the
     * origin which is the begin of the monitoring.
     * 
     * Origin + x days = begin, where x > Origin
     * Origin + y days = end, where y > x
     * @param relativeBegin The beginning of the period relative to the origin
     * @param relativeEnd The end of the period relative to the origin
     */
    private void setDatesToJsPlot(long relativeBegin, long relativeEnd){
        execute("window.pManager.plot.updateXScale(" + relativeBegin + "," + relativeEnd + ");"
              + "window.pManager.plot.update();");
    }

    /**
     * Sets the beginning and the end of a period to be calculated
     *
     * @param start The beginning of the period
     * @param stop The end of the period
     */
    protected void setPeriod(long start, long stop) {
        LOG.debug("Period: " + start + " " + stop);

        _reportHelper.setBeginPeriod(start);
        _reportHelper.setEndPeriod(stop);
    }

    /**
     *
     */
    private void initWebView() throws URISyntaxException {
        final URI[] jsRes = {
            getClass().getResource(JSConfig.JS_RES.jq).toURI(),
            getClass().getResource(JSConfig.JS_RES.jqui).toURI(),
            getClass().getResource(JSConfig.JS_RES.modernizr).toURI(),
            getClass().getResource(JSConfig.JS_RES.date).toURI(),
            getClass().getResource(JSConfig.JS_RES.adx).toURI()
        };
        final URI[] cssRes = {
            getClass().getResource(JSConfig.CSS_RES.style).toURI(),
            getClass().getResource(JSConfig.CSS_RES.control).toURI()
        };
        webView.setContextMenuEnabled(false);
        final WebEngine engine = webView.getEngine();
        // create the callback
        engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
                @Override
                public void changed(ObservableValue ov, State oldState, State newState) {
                    if (newState == State.SUCCEEDED) {
                        JSObject jsobj = (JSObject) engine.executeScript("window");
                        if (jsobj.getMember("loadRes").equals("undefined")) {
                            execute(JSConfig.JS_TRIGGER);
                            for (URI js : jsRes) {
                                execute("loadRes('" + js + "', 'js')");
                            }
                            for (URI css : cssRes) {
                                execute("loadRes('" + css + "', 'css')");
                            }
                        }
                        if (jsobj.getMember("javafx").equals("undefined")) {
                            jsobj.setMember("javafx", _jsBridge);
                        }
                    }
                }
            }
        );

        engine.load(getClass().getResource("/ch/aardex/viewer/viewer.html").toExternalForm());
    }

    /**
     * Executes the web engine to display the plot
     *
     * @param script The script to be executed by the web engine
     */
    public void execute(String script) {
        webView.getEngine().executeScript(script);
    }

    protected void defineAdherenceComputation() {
        IAdherenceScripting script = new EmbeddedAdherenceScripting( this );
        script.generalAdherence();
        script.contextAdherence();
        script.keyFeatures();
    }

    /**
     * Displays the plot by executing a script on the web engine and by
     * providing the JSON data
     */
    public void displayPlot() {
        JSConfig.saveJson(_json, "data.txt");
        try {
            final String SN = _device.getSerialnumber();
            LOG.debug("SN: " + SN);
            //snLabel.setText(SN);

            LOG.debug("JSON: " + _json);
            defineAdherenceComputation();
            webView.getEngine().executeScript("window.runPlot(" + _json + ")");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public void closePopup(){
        getRootTab().closePopup();
    }

    public void switchToCalendar(){
        String script = "pManager.hotSwitch( aardex.plugin.CalendarAdapter.prototype.type, pManager.plot.getScaleObj() );";
        execute(script);

        getRootTab().openTab(RootTabPaneCtrl.TAB_PATIENT_CHRON_ID);
    }

    public void switchToPlot(){
        String script = "pManager.hotSwitch( aardex.plugin.ChronologyAdapter.prototype.type, pManager.plot.getScaleObj() );";
        execute(script);

        getRootTab().openTab(RootTabPaneCtrl.TAB_PATIENT_CHRON_ID);
    }

    /**
     * Handles the request to generate a new report from the reading
     *
     * @param event The event
     */
    /*
    private void printPatientReport() {
        Optional<Pair<String, String>> result = DialogFactory.getInstance(
                                                    getRootTab().getRoot().getPrimaryStage()
                                                ).createPatientFormDialog().showAndWait();

        if (result.isPresent()) {
            _reportHelper.setPatientNumber(result.get().getKey());
            _reportHelper.setPatientComment(result.get().getValue());

            getRootTab().snapshot(_json, getRootTab()::openPatientReportTab);
        }
    }
    */
    /*
    private void viewPatientDetails() {
        getRootTab().openTab(RootTabPaneCtrl.TAB_PATIENT_DETAILS_ID);
    }
    */

    public void deletePatient(){
        // init a variable for readability
        DialogFactory dialogFactory = DialogFactory.getInstance(getRootTab().getRoot().getPrimaryStage());

        ButtonType result = dialogFactory.showConfirmDialog(i18n("title.deletePatient"), 
                                         i18n("label.deletePatientDesc", _device.getSerialnumber()),
                                         i18n("label.deletePatientConfirm"));

        if(result == ButtonType.OK){
            PatientBusiness.getInstance().deletePatient(_dataContext.getCurrentPatient().getId());
            getRootTab().getRoot().initView(RootTabPaneCtrl.HOME_VIEW);
        }
    }

    @FXML
    private void onEditModePressed(){
        isPlotEditable = !isPlotEditable;

        if(isPlotEditable){
            System.err.println("The plot is now editable, logic in ChronologyViewerCtrl line 389");
            btEditMode.setGraphic(new ImageView(new Image(getClass().getResource("/ch/aardex/images/24px/button_check.png").toExternalForm())));
        }else{
            System.err.println("The plot is now not editable, logic in ChronologyViewerCtrl line 389");
            btEditMode.setGraphic(new ImageView(new Image(getClass().getResource("/ch/aardex/images/24px/button_edit.png").toExternalForm())));
        }
    }

    @FXML
    private void handleSwitchTimeline(ActionEvent event) {
        // take the timeline selected
        // take the device
        // setDevice
        // setJson => PatientBusiness.viewerData(Patient, RegimenEvent)

        /*
        AdhTimeline adh = (AdhTimeline) ((ComboBox<AdhTimelineItem>) event.getSource()).getSelectionModel().getSelectedItem().getItem();
        CurrentDataContext.getInstance().setSelectedTimeline(adh);

        PatientTimeline slot = PatientHelper.getPatientTimeline(CurrentDataContext.getInstance().getCurrentPatient(), adh);
        Device device = TimelineHelper.getDeviceFromTimeline(slot, adh);

        setDevice(device);
        setJson(PatientBusiness.getInstance().viewerData(CurrentDataContext.getInstance().getCurrentPatient(), (int) adh.getId()));
        */
    }

    @Override
    public void refreshTab() {
        Patient currentPatient = _dataContext.getCurrentPatient();
        int timelineIndex = currentPatient.getTimelines().size() - 1;

        _json = PatientBusiness.getInstance().viewerData(currentPatient, timelineIndex);
        _dataContext.setCurrentJsonData(_json);

        try {
            initWebView();
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
    }

    class Delta {

        double x, y;
    }

    class TimelineItem {

        private final Timeline _timeline;

        public TimelineItem(Timeline timeline) {
            _timeline = timeline;
        }

        public Timeline getItem() {
            return _timeline;
        }

        @Override
        public String toString() {
            return _timeline.getDesc().getName();
        }
    }
}

我目前正在学习这门课,所以请不要考虑代码的正确性。据我所知,没有使用默认方法,即使是通过继承。

构建.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*/*.jar', '*.jar'])
    retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.3.0'
    // desktopCompile fileTree(dir: 'libs', include: ['*.jar'])
}

jar {
  manifest {
    attributes("Class-Path": configurations.compile.collect { /*'libs/' +*/ it.getName() }.join(' '))
  }
}

task copyLibs(type: Copy) {
   from configurations.compile
   into 'build/libs'//libs'
}

if (!hasProperty('mainClass')) {
    ext.mainClass = 'ch.aardex.main.Main'
}

task generateData(type: JavaExec){
    classpath = sourceSets.main.runtimeClasspath
    main = 'ch.aardex.main.DataGenerator'
}

mainClassName = 'ch.aardex.main.Main'

jfxmobile {
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
    }
}

我对 gradle 不是很熟悉,所以如果有什么错误(或过时)请告诉我,谢谢!

编辑 3

我最终放弃了这些方法引用并恢复到原来的状态。作为预防措施,我将 JDK 更新为 8u91,并且知道该错误似乎影响了另一个甚至没有方法引用或 lambda 表达式的类!该课程是我的主课程,这是我得到的错误(第 738 行)。

我的理解是,由于函数不存在而retrolambda无法向后移植我的 Main 类!checkLicence(LicenceBusiness, String)

请帮忙,我真的卡住了,不知道该怎么办。

4

0 回答 0