JXBROWSER : disabling pdf plugin in a popup doesn't allowed to download a pdf - jxbrowser

i'm using jxbrowser 4.9 on windows 7, when a link has a target="_blank" and point to a pdf,
a new popup is coming with the pdf plugin,
as i want to download this pdf, i disabled the pdf plugin in that popup, via
PluginManager pluginManager = browser.getPluginManager();
pluginManager.setPluginFilter(new PluginFilter() {
#Override
public boolean isPluginAllowed(PluginInfo pluginInfo) {
return false;
}
});
the popup shows a black screen with "couldn't load plugin" but not offers me to download the pdf.
If i change the link to suppress the target="_blank", and disabled the pdf plugin, the pdf can be downloaded.
Is there a special thing to do to get a pdf downloaded when target="_blank"?
thanks for your help !
Here is my simple class :
public class TestPopupPDF {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initAndDisplayUI();
}
});
}
private static void initAndDisplayUI() {
Browser browser = BrowserFactory.create();
JFrame frame = new JFrame("JxBrowser - Popup PDF test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(browser.getView().getComponent(), BorderLayout.CENTER);
frame.setSize(500, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
PluginManager pluginManager = browser.getPluginManager();
pluginManager.setPluginFilter(new PluginFilter() {
#Override
public boolean isPluginAllowed(PluginInfo pluginInfo) {
//disable all plugins
return false;
}
});
browser.setPopupHandler(new PopupHandler() {
public PopupContainer handlePopup(PopupParams params) {
return new PopupContainer() {
public void insertBrowser(final Browser browser,
Rectangle initialBounds) {
initialBounds.setBounds(100, 100, 500, 400);
JComponent component = browser.getView().getComponent();
component.setPreferredSize(initialBounds.getSize());
final JFrame frame = new JFrame("Popup");
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.add(component, BorderLayout.CENTER);
frame.pack();
frame.setLocation(initialBounds.getLocation());
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
browser.dispose();
}
});
PluginManager pluginManager = browser.getPluginManager();
pluginManager.setPluginFilter(new PluginFilter() {
#Override
public boolean isPluginAllowed(PluginInfo pluginInfo) {
return false;
}
});
}
};
}
});
browser.loadURL("http://localhost/test.html");
}
}
And this is the test.html page :
<html>
<head></head>
<body>
<H1>PDF</H1>
download/open pdf file new page
<br><br>
download/open pdf file same page
</body>
</html>
use any pdf.

JxBrowser 4.9 is no longer supported. In JxBrowser 6.1 this issue isn't reproducible, so I recommend that you try 6.1.

Related

Switching views/fxml on gluon Application

I am developing a gluon application with JavaFX but i can't understand very well how to switch scene (or view?) by clicking a button.
If i click the button "load from file" in the image below, my code should perform some tasks, and then it should change the view, loading a new fxml, that i've added to the app manager.
Screenshoot
main class that extends Application:
package com.knnapplication;
import com.knnapplication.views.ExampleView;
import com.knnapplication.views.PrimaryView;
import com.knnapplication.views.SecondaryView;
import com.gluonhq.charm.glisten.application.AppManager;
import com.gluonhq.charm.glisten.visual.Swatch;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import static com.gluonhq.charm.glisten.application.AppManager.HOME_VIEW;
public class KNNApplication extends Application {
public static final String PRIMARY_VIEW = HOME_VIEW;
public static final String SECONDARY_VIEW = "Secondary View";
public static final String EXAMPLE_VIEW = "Example View";
private final AppManager appManager = AppManager.initialize(this::postInit);
#Override
public void init() {
appManager.addViewFactory(PRIMARY_VIEW, () -> new PrimaryView().getView());
appManager.addViewFactory(SECONDARY_VIEW, () -> new SecondaryView().getView());
appManager.addViewFactory(EXAMPLE_VIEW, () -> new ExampleView().getView());
DrawerManager.buildDrawer(appManager);
}
#Override
public void start(Stage primaryStage) throws Exception {
appManager.start(primaryStage);
}
private void postInit(Scene scene) {
Swatch.BLUE.assignTo(scene);
scene.getStylesheets().add(KNNApplication.class.getResource("style.css").toExternalForm());
((Stage) scene.getWindow()).getIcons().add(new Image(KNNApplication.class.getResourceAsStream("/icon.png")));
}
public static void main(String args[]) {
launch(args);
}
}
event that handles the button click
#FXML
void LoadFile(ActionEvent event) {
//connection to server
InetAddress addr;
try {
addr = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e) {
System.out.println(e.toString());
return;
}
Client c;
try {
c=new Client("127.0.0.1", 2025, label);
/*
HERE I SHOULD SWITCH VIEW
*/
AppManager.getInstance().switchView("EXAMPLE_VIEW");
} catch (IOException e) {
label.setText(e.toString());
System.out.println(e.toString());
return;
} catch (NumberFormatException e) {
label.setText(e.toString());
System.out.println(e.toString());
return;
} catch (ClassNotFoundException e) {
label.setText(e.toString());
System.out.println(e.toString());
return;
}
//label.setText("KNN caricato da file");
}
Searching on the web i've found this kind of method, using this line of code " AppManager.getInstance().switchView("EXAMPLE_VIEW");", but it still not work and i can't understand very well how does it works.
I hope you can help me. Thank you so much!
To load a new view you should make a view object and load the FXML/ the nodes on it. Then you can switch to that view by calling home.getAppManager().switchView("your view here"). like in the following example:
FloatingActionButton fab = new FloatingActionButton(MaterialDesignIcon.ADD.text,
e -> home.getAppManager().switchView(ADDHUB_VIEW));
fab.showOn(your view);
also you need to add this view to the app manager in init in main
appManager.addViewFactory(YOUR_VIEW, () -> new YourView().getView());

How to refresh JavaFX screen twice after sleep?

I am using JavaFX to show images on the screen. My FxScreenController code concept is like:
package my.image.concept;
import java.util.function.Consumer;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.springframework.stereotype.Component;
#Component
public class FxScreenController {
private ImageSenderClient imageClient;
#FXML
private ImageView imageView;
private Image image;
public FxScreenController(Image image) {
this.image = image;
}
#FXML
public void initialize(){
final ImageSubscriber imageSubscriber = new ImageSubscriber(image);
imageClient.GetImageFrom().subscribe(imageSubscriber);
}
private static class ImageSubscriber implements Consumer<Image> {
private ImageView imageFile;
public ImageSubscriber(Image newImage) {
this.imageFile.setImage(newImage);
}
#Override
public void accept(Image newImage) {
Platform.runLater(() -> imageFile.setImage(newImage));
}
}
}
I am displaying an image that comes from the Subscriber method.
In order to show image on JavaFX Screen, I am calling Platform.runLater(). The image is shown properly.
I would like to show my previous image back after a 2-seconds pause like this:
#Override
public void accept(Image newImage) {
Platform.runLater(() -> imageFile.setImage(newImage));
try {
Thread.sleep(2000); // Wait for 2 sec before updating back to prev image
} catch (InterruptedException ignored) {
//
}
Platform.runLater(() -> imageFile.setImage(prewImage));
}
However, here it doesn't show my newImage because it doesn't refresh the screen.
How can I can refresh the FX screen before calling Thread.sleep, so that I can show my newImage for 2 seconds on the FX screen?
Creating new Thread solved my problem.
#Override
public void accept(Image newImage) {
Thread timerThread = new Thread(() -> displayImage(newImage));
timerThread.start();
}
private void displayImage(Image newImage) {
Platform.runLater(() ->
imageBg.setImage(newImage)
);
try {
Thread.sleep(2000); // Wait for 2 sec before updating back to main
}
catch (InterruptedException ignored) {
}
imageBg.setImage(prevImage);
}

JavaFX log4j in a textarea with a different thread

I'm trying to redirect log4j output to a textarea but this one get filled at the end of the action since I'm using Platform.runLater
Is there any way I can do it with a different thread ?
AppFX.java
public class AppFX extends Application {
public static void main(String[] args) {
ConfHandler.initConf();
launch(args);
}
#Override
public void start(Stage primaryStage)throws IOException {
primaryStage.getIcons().add(new Image("file:src/main/resources/images/frameIcon.png"));
FXMLLoader loader = new FXMLLoader();
String currentPath = System.getProperty("user.dir");
loader.setLocation(new URL("file:\\"+currentPath+"\\src\\main\\resources\\scenes\\TestsFrame.fxml"));
Parent content = loader.load();
primaryStage.setTitle("IGED Tests");
Scene scene = new Scene(content);
primaryStage.setScene(scene);
primaryStage.show();
TextAreaAppender.setTextArea(((EaaSCleanerController)loader.getController()).getLogTextArea());
}}
TextAreaAppender.java
public class TextAreaAppender extends WriterAppender {
private static volatile TextArea textArea = null;
public static void setTextArea(final TextArea textArea) {
TextAreaAppender.textArea = textArea;
}
#Override
public void append(final LoggingEvent loggingEvent) {
final String message = this.layout.format(loggingEvent);
try {
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
if (textArea != null) {
if (textArea.getText().length() == 0) {
textArea.setText(message);
} else {
textArea.selectEnd();
textArea.insertText(textArea.getText().length(), message);
}
}
} catch (final Throwable t) {
System.out.println("Unable to append log to textarea:" + t.getMessage());
}
}
});
} catch (final IllegalStateException e) {
}
}}
log4j.properties
# Append the logs to the GUI
log4j.appender.gui=com.bp.nest.testauto.gui.TextAreaAppender
log4j.appender.gui.layout=org.apache.log4j.PatternLayout
log4j.appender.gui.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n
You should put your actions on a separate thread. Then the logging can happen in parallel to your actions. You should never block the GUI-thread.

How to create splash screen as a Preloader in JavaFX standalone application?

I created a Preloader (based on the following tutorial) that should display a splash screen for the main application.
9.3.4 Using a Preloader to Display the Application Initialization Progress
http://docs.oracle.com/javafx/2/deployment/preloaders.htm
public class SplashScreenLoader extends Preloader {
private Stage splashScreen;
#Override
public void start(Stage stage) throws Exception {
splashScreen = stage;
splashScreen.setScene(createScene());
splashScreen.show();
}
public Scene createScene() {
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 200);
return scene;
}
#Override
public void handleApplicationNotification(PreloaderNotification notification) {
if (notification instanceof StateChangeNotification) {
splashScreen.hide();
}
}
}
I'd like to run preloader each time I run the main application in my IDE (IntelliJ IDEA).
I also followed the packaging rules for preloaders in IntelliJ:
https://www.jetbrains.com/idea/help/applications-with-a-preloader-project-organization-and-packaging.html
When I run the main application the preloader doesn't start, so I suppose I'm missing something. I'm new to Preloaders and I don't understand what is the mechanism to connect the main app with the preloader in standalone application.
You can run using LauncherImpl like this . . .
public class Main {
public static void main(String[] args) {
LauncherImpl.launchApplication(MyApplication.class, SplashScreenLoader.class, args);
}
}
And the class MyApplication would be like this . . .
public class MyApplication extends Application {
#Override
public void start(Stage primaryStage) {
....
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The IDEs aren't great at adding preloaders yet. Take a look at the Manifest in your program's jar file and make sure this line is present:
JavaFX-Preloader-Class: SplashScreenLoader
May be too late, this can also help somebody.
For me, i used JavaFX service and task to create splash screen as a Preloader in JavaFX standalone application. This, because the contexte of my project.
Create the AnchorPane and the progress Pane
#FXML
private AnchorPane anchorPane;
private MaskerPane progressPane;
public static void main(String[] args) {
launch(args);
}
#Override
public void init() throws Exception {
progressPane = new MaskerPane();
progressPane.setText(bundle.getString("root.pleaseWait"));
progressPane.setVisible(false);
AnchorPane.setLeftAnchor(progressPane, 0.0);
AnchorPane.setTopAnchor(progressPane, 0.0);
AnchorPane.setRightAnchor(progressPane, 0.0);
AnchorPane.setBottomAnchor(progressPane, 0.0);
anchorPane.getChildren().add(progressPane);
}
#Override
public void start(Stage initStage) {
//.....
initRoot();
//.....
}
Create the splash screen service as this:
private final Service<Void> splashService = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
public Void call() throws Exception {
//main code, the code who take time
//or
//Thread.sleep(10000);
return null;
}
};
}
};
Start service and show/hide the progressPane on initRoot when loading the main screen:
public void initRoot() {
try {
//....
splashService.restart();
//On succeeded, do this
splashService.setOnRunning(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
//Show mask on succeed
showMask(Boolean.TRUE);
}
});
splashService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
splashService.cancel();
//Hide mask on succeed
showMask(Boolean.FALSE);
}
});
//.....
primaryStage.show();
} catch (IOException ex) {
ex.printStackTrace();
}
}
To show/hide the progress...
showMask(boolean value){
progressPane.setVisible(value);
};

JavaFX preloader not updating progress

I'm having trouble with the JavaFX Preloader. During the start phase the application will have to connect to a DB and read many so I thought it would be nice to display a splash screen during this time. The problem is the ProgressBar automaticly goes to 100% and I don't understand why.
Application class. Thread sleep will be replaced by real code later (DB connection etc)
public void init() throws InterruptedException
{
notifyPreloader(new Preloader.ProgressNotification(0.0));
Thread.sleep(5000);
notifyPreloader(new Preloader.ProgressNotification(0.1));
Thread.sleep(5000);
notifyPreloader(new Preloader.ProgressNotification(0.2));
}
Preloader
public class PreloaderDemo extends Preloader {
ProgressBar bar;
Stage stage;
private Scene createPreloaderScene() {
bar = new ProgressBar();
bar.getProgress();
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
#Override
public void handleStateChangeNotification(StateChangeNotification scn) {
if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
stage.hide();
}
}
#Override
public void handleProgressNotification(ProgressNotification pn) {
bar.setProgress(pn.getProgress());
System.out.println("Progress " + bar.getProgress());
}
For some reason I get the following output:
Progress 0.0
Progress 1.0
I had same problem and I found solution after two hours of searching and 5 minutes of carefully reading of JavaDoc.:)
Notifications send by notifyPreloader() method can be handled only by Preloader.handleApplicationNotification() method and it doesn't matter which type of notification are you sending.
So change you code like this:
public class PreloaderDemo extends Preloader {
.... everything like it was and add this ...
#Override
public void handleApplicationNotification(PreloaderNotification arg0) {
if (arg0 instanceof ProgressNotification) {
ProgressNotification pn= (ProgressNotification) arg0;
bar.setProgress(pn.getProgress());
System.out.println("Progress " + bar.getProgress());
}
}
}

Resources