With a JavaFX applet :
The javascript object I get with document.getElementById("APPLET_ID") has no Packages attribute under Windows.
I run my tests on Windows XP with IE8, FF and Chrome up to date, but it's the same problem under windows 7.
Under Ubuntu with JRE 7u7 x64, no such problem.
Here is my test code :
package test;
import netscape.javascript.JSObject;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
private JSObject js;
TextField tf;
#Override
public void start(Stage primaryStage) {
js = this.getHostServices().getWebContext();
HBox hb = new HBox();
Scene s = new Scene(hb, 400, 400);
tf = new TextField("MAIN");
primaryStage.setScene(s);
hb.getChildren().add(tf);
primaryStage.show();
runTest();
}
public static void main(String[] args) {
launch(args);
}
void runTest(){
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(
new Runnable() {
#Override
public void run() {
tf.setText("" + js.eval("document.getElementById('applet_id').Packages == null"));
}
}
);
}
}).start();
}
}
Displays "false" under Ubuntu JRE7u7x64 and "true" under Windows and Ubuntu JRE7u21 with all browsers.
As the JavaFX2 deployment doc page tells I'm doing it the right way, it looks like a JRE bug. What do you think about it ?
http://docs.oracle.com/javafx/2/deployment/javafx_javascript.htm .
Filed on Jira : https://javafx-jira.kenai.com/browse/RT-30732
Looks it's an expected change since 7u21 : http://www.oracle.com/technetwork/java/javase/7u21-relnotes-1932873.html
This Packages attribute no more works.
So if you need callbacks from your JS to your applet, you must access directly it's methods.
And use the Trusted-Library manifest attribute to avoid warnings.
But you can't do what you want when using Trusted-Library. For example, if you use Axis2 webservices.
So you'll have to do it with Trusted-Only manifest attribute. But this forbids you to call methods from JS.
Simple workaround :
Have a thread periodically checking a JS callback queue and treat them. It's painful, horrible POJO but it works.
So to Oracle :
THANKS
for updating online doc
for announcing major changes made in minor releases
for making web integration so easy.
for adding other security checks in u25 that result in 20 seconds gray screen latency
Do you know Adobe ? Heard they have pretty good stuff... I'm pissed.
Related
Reproduced in OpenJFX 11.0.2 & 12.0.1 SDK (Windows 10, x64), not reproducible in JavaFX 8
Right-click on a table-column, then try to resize the column. No resize cursor is shown and column can't be resized until you manually click on the column again.
Any ideas for a workaround? I need to usecontextMenu for TableColumns, so potential workarounds that make the header ignore right mouse click aren't possible.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class Foo extends Application {
#Override
public void start(Stage stage) throws Exception {
TableView<Object> testView = new TableView<>();
testView.getColumns().addAll(new TableColumn<Object, Object>("C1"), new TableColumn<Object, Object>("C2"), new TableColumn<Object, Object>("C3"));
stage.setScene(new Scene(testView));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Ok I found the following (very, very dirty) workaround. I never tried this before because I assumend it would prevent the context menu from showing (as I noted in my original question), but apprently simply consuming the mouse event of every TableColumnHeader works and the context menu is still shown correctly (also works with TableColumns without context menus).
Not sure if anything internal could go wrong with this, but as the right click doesn't seem to be doing anything useful by default, I hope not.
Of course lookupAll needs to be called after it has been rendered.
Note 1: If you have TableMenuButtonVisible set to true, you need to do this every time a column is set to visible.
Note 2: Its getting dirtier and dirtier. Simply calling this again after a column has been set to visible (see note 1) doesn't always suffice (also not with a Platform.runLater call). I assume that's because the column header hasn't been rendered at that point. You either
need to wait until the Set<Node> is fully filled, i.e. the size of
it must be amountOfVisibleColumns + 1. If its equal to the amount
of visible columns, it won't work for the newly shown column.
or call layout() on the TableView before lookupAll
or if you have a class that extends TableView, override layoutChildren and execute the lookup if the amount of visible columns has changed
Note 3: You need to keep track of the old onMousePressed and execute it if the button isn't SECONDARY, otherwise the reordering of columns won't work.
Please let me know if you can think of any cleaner way.
import java.util.Set;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.skin.TableColumnHeader;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;
public class Foo extends Application {
#Override
public void start(Stage stage) throws Exception {
TableView<Object> testView = new TableView<>();
testView.getColumns().addAll(createColumn("C1"), createColumn("C2"), createColumn("C3"));
stage.setOnShown(ev -> {
Set<Node> headers = testView.lookupAll("TableColumnHeader");
for (Node header : headers) {
if (header != null) {
((TableColumnHeader) header).setOnMousePressed(e -> {
if (e.getButton() == MouseButton.SECONDARY) {
e.consume();
}
});
}
}
});
stage.setScene(new Scene(testView));
stage.show();
}
private TableColumn<Object, Object> createColumn(String text) {
MenuItem item = new MenuItem("Context");
item.setOnAction(e -> {
System.out.println("Action");
});
ContextMenu contextMenu = new ContextMenu();
contextMenu.getItems().add(item);
TableColumn<Object, Object> column = new TableColumn<>(text);
column.setContextMenu(contextMenu);
return column;
}
public static void main(String[] args) {
launch(args);
}
}
EDIT: Found the described bug in the Java bug tracker and filed a PR with the fix:
https://github.com/openjdk/jfx/pull/483
EDIT 2: My PR was accepted and merged back. The bug is fixed now, you can test it by using 17-ea+11. :-)
I have the same problem. This bug is caused by the mousePressedHandler added in TableColumnHeader. This class has even more problems, for example if I close a PopupControl with setConsumeAutoHidingEvents(true) by a click on a column, the sorting will be triggered. Those methods needs to be changed, maybe the addEventHandler methods should be used instead of the convenience setOn... methods.
I fixed it by consuming the event when I'm about to show my PopupControl:
public class MyTableColumnHeader extends TableColumnHeader {
public MyTableColumnHeader(TableColumnBase tc) {
super(tc);
addEventHandler(MouseEvent.MOUSE_PRESSED, this::onMousePressed);
}
private void onMousePressed(MouseEvent mouseEvent) {
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
showPopup();
// Consume here, so the column won't get 'stuck'.
mouseEvent.consume();
}
}
private void showPopup() {
...
}
}
Eventually, someone should open at least a bug. I may will also have a look in the not too distant future.
This is a regression in Java 10, refer to the bug report for further updates: JDK-8204949
Consider the following Java FX code, where b starts invisible:
a.disableProperty().bind(b.visibleProperty())
If an application utilizing such code is run on Java 10 VM, then from the first time b becomes visible, a will always be rendered as if it was disabled.
Of course, during the time while a is not really disabled (despite being rendered with a gray overlay), you can still interact with that element. E.g. you can edit text in input controls, click buttons/links and so on, the events get propagated correctly and so on.
If the application is run on Java 8 VM, it works as expected.
I currently do not have the EOS Java 9, so I have only tested on:
Windows 10 x64 Pro 1709 & 1803
Java 8u172 x64 (both on JDK and JRE explicitly targeting executables)
Java 10u1 x64 (both on JDK and JRE explicitly targeting executables)
Example of how it looks like with Java 10:
How it looks on first start, before b had a chance to become visible:
A SSCCE (mandatory for a somewhat obscure problem; a would be propertyProvider, b would be invalidRenderField and invalidRenderButton):
package application;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
System.out.println("Executing start(Stage) in " + Thread.currentThread().getName());
try {
TextField invalidRenderField = new TextField();
Button invalidRenderButton = new Button("Click to reproduce");
Label propertyProvider = new Label();
propertyProvider.setVisible(false);
VBox invalidRenderParent = new VBox(invalidRenderField, invalidRenderButton, propertyProvider);
TitledPane invalidRenderPane = new TitledPane("Incorrectly rendered elements", invalidRenderParent);
Accordion root = new Accordion(invalidRenderPane);
root.setExpandedPane(invalidRenderPane);
invalidRenderField.disableProperty().bind(propertyProvider.visibleProperty());
invalidRenderButton.disableProperty().bind(propertyProvider.visibleProperty());
invalidRenderButton.setOnAction(e -> {
System.out.println("Executing 1st onAction(ActionEvent) in " + Thread.currentThread().getName());
propertyProvider.setVisible(true);
propertyProvider.setText("At this point of time you cannot modify the field or click the button");
Task<Void> task = new Task<>() {
#Override
protected Void call() throws Exception {
System.out.println("Executing non-JFX code in " + Thread.currentThread().getName());
Thread.sleep(3_000L);
return null;
}
};
task.setOnSucceeded(e2 -> {
System.out.println("Executing onSuccess(WorkerStateEvent) in " + Thread.currentThread().getName());
propertyProvider.setVisible(false);
Label infoLabel = new Label("Either click the button below or just select the previous pane within the accordion");
Button closePlaceholderButton = new Button("View failure");
VBox placeholder = new VBox(infoLabel, closePlaceholderButton);
TitledPane placeholderPane = new TitledPane("Placeholder", placeholder);
closePlaceholderButton.setOnAction(e3 -> {
System.out.println("Executing 2nd onAction(ActionEvent) in " + Thread.currentThread().getName());
root.getPanes().remove(placeholderPane);
root.setExpandedPane(invalidRenderPane);
});
root.getPanes().add(1, placeholderPane);
root.setExpandedPane(placeholderPane);
});
new Thread(task, "WhateverThread").start();
});
Scene scene = new Scene(root, 800, 450);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("Executing main(String[]) in " + Thread.currentThread().getName());
launch(args);
}
}
SSCCE output after clicking 'Click to reproduce' once:
Executing main(String[]) in main
Executing start(Stage) in JavaFX Application Thread
Executing 1st onAction(ActionEvent) in JavaFX Application Thread
Executing non-JFX code in WhateverThread
Executing onSuccess(WorkerStateEvent) in JavaFX Application Thread
Which is exactly as expected, JavaFX code executes on the designated thread.
The question is, am I doing something wrong and/or missing something obvious? I can't seem to find anything "wrong" with this code, it seems sound, yet it malfunctions. Is this a bug (and I need to lrn2search)?
All in all, any suggestions for a workaround are welcome. I need this code (or equivalent via a workaround) to work on Java 10, no excuses.
First, I'd just like to confirm that I am observing the same behavior as you.
Windows 10 x64 Home
Java 1.8.0_172 x64 -- Works as expected
Java 10.0.1 x64 -- Fails (shows as disabled but is not actually disabled)
This appears to be a bug and you should report it as such.
Possible Workaround
I found that the nodes in question will be rendered correctly if you add to following code to all affected nodes:
node.disableProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) { // if no longer disabled
node.applyCss();
}
});
This could become tedious if you have a lot of nodes that can be disabled and are subject to the same sequence of events as described in your question. It may be prudent to create some type of utility method to handle this.
Edit
I found that the order of when you make propertyProvider invisible affects the workaround I provided. If you make propertyProvider invisible after you display the new TitledPane then, when you go back to the other TitledPane, the TextField and Button still render as disabled when they are not. Haven't found a way around that yet.
I am trying to integrate the mozilla viewer in a JavaFx WebView by using the following code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TestStrict extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
WebView webView = new WebView();
String url = TestStrict.class.getClassLoader().getResource("pdfjs-1.1.366-dist/web/viewer.html").toExternalForm();
webView.getEngine().load(url);
Scene scene = new Scene(webView);
primaryStage.setScene(scene);
primaryStage.setWidth(800);
primaryStage.setHeight(600);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The pdfjs-1.1.366-dist folder is downloaded from pdfjs GitHub
I also changed the viewer.html just to add firebug-lite inside:
<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
Now when I run the application I get the viewer frame but without the default pdf loaded and the following error is inside firebug console:
"TypeError: undefined is not an object (evaluating 'globalScope.PDFJS') (pdf.worker.js,103)"
I removed all the 'use strict' directives in the javascript files and everything is working fine.
I don't know if this is a bug in JavaFX or internal WebKit but it happens with version 1.8.0_60.
So is there any way that I can disable strict mode since there will be other web pages that will be loaded where I can't control the scripts and remove 'use strict' directives?
import javafx.application.*;
import javafx.scene.*;
import javafx.stage.*;
import javafx.scene.layout.*;
public class LoanCalculator extends Application
{
public void start(Stage myStage)
{
myStage.setTitle("Loan Calculator");
FlowPlane rootNode = new FlowPane();
Scene myScene = new Scene( rootNode, 300, 200 );
myStage.setScene( myScene);
myStage.show();
}
public static void main( String [] args)
{
launch(args);
}
}
This code pops up with multiply errors when I try running it with Eclipse. I apologize if it is an obvious error. I am new to coding, I found this piece of code in my book and I wanted to test it out.
Thanks Guys
Maybe is ir just a typo? In your code it reads: FlowPlane instead of FlowPane.
Java FX is supported by JDK starting from JDK 7 update 6.
Updated my JDK 7 update 5 to JDK 8, executed your code, it worked like a magic.
Also correct the FlowPlane to FlowPane as suggested below by Kornel.
As stated in the answer to this question, one can setup a Timeline to check whether there is a change in the system clipboard:
Set and use variables outside timeline in javafx 8
But is there a better way? For example, an event listener? I have searched JavaFx 8 doc and didn't find anything obviously helpful.
Solutions using JavaFx is preferred, but all answers are welcome.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.Clipboard;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Clipboard systemClipboard = Clipboard.getSystemClipboard();
new com.sun.glass.ui.ClipboardAssistance(com.sun.glass.ui.Clipboard.SYSTEM) {
#Override
public void contentChanged() {
System.out.print("System clipboard content changed: ");
if ( systemClipboard.hasImage() ) {
System.out.println("image");
} else if ( systemClipboard.hasString() ) {
System.out.println("string");
} else if ( systemClipboard.hasFiles() ) {
System.out.println("files");
}
}
};
primaryStage.setScene(new Scene(new StackPane()));
primaryStage.show();
}
}
Test:
Press key Print Screen
Ctrl+C for selected string
Ctrl+c for selected files
No, there isn't a better way. There are no events sent round when the clipboard contents change (especially if it's from outside of the Java application) and so only a polling approach is appropriate.