我正在尝试从实例对象中引用一个方法来创建一些按钮。我必须这样做以获得灵活性(根据上下文向工具栏添加按钮)。我的项目是一个 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)
请帮忙,我真的卡住了,不知道该怎么办。