JavaFX&;胶子:当它明显存在时,没有任何方法异常
我试图从实例对象引用一个方法来创建一些按钮。我必须这样做才能获得灵活性(根据上下文向工具栏添加按钮)。我的项目是一个GluonFX项目(JavaFX+,它使用一个Gradle文件进行编译) 下面是负责创建这些按钮的函数JavaFX&;胶子:当它明显存在时,没有任何方法异常,java,gradle,javafx,gluon,Java,Gradle,Javafx,Gluon,我试图从实例对象引用一个方法来创建一些按钮。我必须这样做才能获得灵活性(根据上下文向工具栏添加按钮)。我的项目是一个GluonFX项目(JavaFX+,它使用一个Gradle文件进行编译) 下面是负责创建这些按钮的函数 public void postInit() { ToolbarVerticalCtrl toolbar = getRoot().getToolbarCtrl(); ChronologyViewerCtrl viewer = ((ChronologyViewerC
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
是检索到的类型为chromeoryviewerctrl的实例。实例不为空
当我运行项目时,我从gradle构建中得到以下错误(我只是显示stacktrace中最重要的行,并制作了一个pastebin,只是因为格式很糟糕)
stacktrace=>
我在控制器中提到的功能如下:
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
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,所以如果有什么错误(或过时),请告诉我,谢谢
编辑3
我最终放弃了这些方法引用,并恢复到原来的状态。作为预防措施,我将JDK更新为8u91,并且知道该错误似乎影响到另一个甚至没有方法引用或lambda表达式的类!这门课是我的主课,这是我得到的答案(第738行)
我所了解的是,retrolambda
未能返回我的主类,因为函数checklicense(LicenceBusiness,String)
,该函数不存在
请帮帮我,我真的被卡住了,不知道该怎么办。你能用最新的retrolambda版本试试吗?您可以通过在build.gradle文件中添加以下依赖项来实现这一点:
retrolambdaConfig'net.orfjackal.retrolambda:retrolambda:2.3.0'
非常感谢您的评论@Joeri,我照你说的做了,我得到了一个关于类的后移的错误,原因是:java.lang.RuntimeException:未能后移lambda或方法引用:ch/aardex/viewer/chromeoryviewerCtrl.switchToPlot()V(5)
你能提供更多关于chromeoryviewerCtrl类的信息吗,或者显示整个源代码?它是否可能从包含默认方法的接口继承?@Joeri Sykora请参见编辑,我提供了类和gradle文件OK,我看到您从本地libs文件夹添加JAR。您必须确保这些JAR中的所有类都使用retrolambda进行了后端口,以便能够在JDK 6上使用它们。Retrolambda不会自动应用于依赖库。顺便说一句,你能不能用实际调用替换postInit()方法中的方法引用:toolbar.addnewbuttonoolbar(newimageview(iconPlot),i18n(“title.timeroy”),()->viewer.switchToPlot(),false,true)代码>?另外,当使用retrolambda 2.3.0时,您得到的整个堆栈跟踪是什么?
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')
}
}