How to use executeScript called by javascript (bridge) in webview (javaFX) - java

I have this class:
public Palco() {
super();
initComponents();
setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
}
private void initComponents() {
createScene();
progressBar.setPreferredSize(new Dimension(150, 18));
progressBar.setStringPainted(true);
JPanel topBar = new JPanel(new BorderLayout(5, 0));
topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
topBar.add(txtURL, BorderLayout.CENTER);
topBar.add(btnGo, BorderLayout.EAST);
statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
statusBar.add(lblStatus, BorderLayout.CENTER);
statusBar.add(progressBar, BorderLayout.EAST);
//panel.add(topBar, BorderLayout.NORTH);
panel.add(jfxPanel, BorderLayout.CENTER);
panel.add(statusBar, BorderLayout.SOUTH);
getContentPane().add(panel);
setTitle("My App");
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
private void createScene() {
Platform.runLater(new Runnable() {
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.setJavaScriptEnabled(true);
engine.titleProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
String title = null;
public void run() {
if(newValue == null){
title = "Carregando...";
} else {
title = newValue;
}
Palco.this.setTitle(title);
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// lblStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
txtURL.setText(newValue);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if(newValue.intValue() < 100){
statusBar.setVisible(true);
} else {
statusBar.setVisible(false);
}
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.documentProperty().addListener(new ChangeListener<Document>() {
public void changed(ObservableValue<? extends Document> prop, Document oldDoc, Document newDoc) {
MainTiles tiles = new MainTiles(engine);
tiles.ShowCategory(0);
}
});
engine.getLoadWorker()
.exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(
panel,
(value != null) ?
engine.getLocation() + "\n" + value.getMessage() :
engine.getLocation() + "\nUnexpected error.",
"Loading error...",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
});
engine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
#Override
public void changed(ObservableValue<? extends State> ov,
State oldState, State newState) {
JSObject jsobj = (JSObject) engine.executeScript("window");
jsobj.setMember("java", new Bridge());
}
}
);
jfxPanel.setScene(new Scene(view));
}
});
}
public void loadURL(final String url) {
Platform.runLater(new Runnable() {
public void run() {
String tmp = toURL(url);
if (tmp == null) {
tmp = toURL("http://" + url);
}
engine.load(tmp);
}
});
}
private static String toURL(String str) {
try {
return new URL(str).toExternalForm();
} catch (MalformedURLException exception) {
return null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Palco browser = new Palco();
browser.setVisible(true);
String url = getClass().getResource("html/index.html").toExternalForm();
browser.loadURL(url);
}
});
}
public static void changeScene(){
}
And I wanted execute the command executeScript in JavaScript (bridge) callback <a onclick="java.link()">teste</a>, but I dont know how pass the webview (WebView.getEngine) in class Bridge:
public void link(){
executeScript(engine, "document.getElementById('main').innerHTML = 'test';"); // engine is WebView
}
Does anyone know if it is possible or how to do?
Sorry my english is very bad =/, I'm Brazilian!
Thanks

You could it pass it via a constructor, it's a normal Java object which can be shared, i.e.
public class Bridge{
WebEngine engine; // add a new field
public Bridge(WebEngine engine){
this.engine = engine;
}
}
// ...
JSObject jsobj = (JSObject) engine.executeScript("window");
jsobj.setMember("java", new Bridge(engine)); // pass it here

Related

How can I display a JavaFX Browser in a Java JPanel application?

Good Community I am making an app and I am working with a java browser googlemap and I want to show it in a panel or in another element where it is displayed (JLabel, JPanel, etc).
I made a project in java-> javaAplication-> a form -> with a button. This is the method I am calling on the button.
locate ();
I want to display it in a JPanel not in an FXPanel like this now:
private void locate() {
String a = txtMapaBuscador.getText().replace(" ", "+");
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(1280, 720);
frame.setVisible(true);
final JFXPanel fxpanel = new JFXPanel();
frame.add(fxpanel);
Platform.runLater(new Runnable() {
#Override
public void run() {
WebEngine engine;
WebView wv = new WebView();
engine = wv.getEngine();
fxpanel.setScene(new Scene(wv));
engine.load("https://www.google.com/maps/place/" + a);
}
});
}
This is my friend's code but I can't understand it.
package simpleswingbrowser;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import static javafx.concurrent.Worker.State.FAILED;
public class SimpleSwingBrowser extends JFrame {
private final JFXPanel jfxPanel = new JFXPanel();
private WebEngine engine;
private final JPanel panel = new JPanel(new BorderLayout());
private final JLabel lblStatus = new JLabel();
private final JButton btnGo = new JButton("Go");
private final JTextField txtURL = new JTextField();
private final JProgressBar progressBar = new JProgressBar();
public SimpleSwingBrowser() {
super();
initComponents();
}
private void initComponents() {
createScene();
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
loadURL(txtURL.getText());
}
};
btnGo.addActionListener(al);
txtURL.addActionListener(al);
progressBar.setPreferredSize(new Dimension(150, 18));
progressBar.setStringPainted(true);
JPanel topBar = new JPanel(new BorderLayout(5, 0));
topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
topBar.add(txtURL, BorderLayout.CENTER);
topBar.add(btnGo, BorderLayout.EAST);
JPanel statusBar = new JPanel(new BorderLayout(5, 0));
statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
statusBar.add(lblStatus, BorderLayout.CENTER);
statusBar.add(progressBar, BorderLayout.EAST);
panel.add(topBar, BorderLayout.NORTH);
panel.add(jfxPanel, BorderLayout.CENTER);
panel.add(statusBar, BorderLayout.SOUTH);
getContentPane().add(panel);
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
private void createScene() {
Platform.runLater(new Runnable() {
#Override
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.titleProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SimpleSwingBrowser.this.setTitle(newValue);
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
#Override
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
lblStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtURL.setText(newValue);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.getLoadWorker()
.exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
#Override
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(
panel,
(value != null)
? engine.getLocation() + "\n" + value.getMessage()
: engine.getLocation() + "\nUnexpected error.",
"Loading error...",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
});
jfxPanel.setScene(new Scene(view));
}
});
}
public void loadURL(final String url) {
Platform.runLater(new Runnable() {
#Override
public void run() {
String tmp = toURL(url);
if (tmp == null) {
tmp = toURL("http://" + url);
}
engine.load(tmp);
}
});
}
private static String toURL(String str) {
try {
return new URL(str).toExternalForm();
} catch (MalformedURLException exception) {
return null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SimpleSwingBrowser browser = new SimpleSwingBrowser();
browser.setVisible(true);
browser.loadURL("http://oracle.com");
}
});
}
}
Add a JPanel pnlViewMap in my frame and put BorderLayout and the map appeared
pnlViewMapa.add(fxpanel,BorderLayout.CENTER);
Platform.runLater(new Runnable() {
#Override
public void run() {
WebEngine engine;
WebView wv = new WebView();
engine = wv.getEngine();
fxpanel.setScene(new Scene(wv));
engine.load("https://www.google.com/maps/place/" + a);
}
});

Simple JavaFX Browser Only Works The First Time Its Opened

I have this code to open a custom Java browser:
private void openNavigator(){
Navigator browser = new Navigator();
SwingUtilities.invokeLater(() -> {
browser.initComponents();
browser.setVisible(true);
browser.loadURL("http://XXXXXXXX:8888/YYYYYY/ZZZZ");
});
}
In the other hand i have the code of the navigator:
public class Navigator extends JFrame {
private static final Logger LOG = Logger.getLogger(Navegador.class.getName());
private static final long serialVersionUID = -1951385676682823399L;
private WebView view;
private JFXPanel javaFxPanel;
private WebEngine engine;
private JLabel labelStatus;
private JTextField direction;
private JProgressBar progressBar;
private java.net.CookieManager cookiesManager;
public void initComponents() {
if (cookiesManager != null) {
cookiesManager = new java.net.CookieManager();
java.net.CookieHandler.setDefault(cookiesManager);
}
javaFxPanel = new JFXPanel();
labelStatus = new JLabel();
JPanel panelTodo = new JPanel(new BorderLayout());
JButton botonBuscar = new JButton("Search");
direction = new JTextField();
progressBar = new JProgressBar();
createScene();
ActionListener direcctionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
loadURL(direction.getText());
}
};
botonBuscar.addActionListener(direcctionListener);
direction.addActionListener(direcctionListener);
progressBar.setPreferredSize(new Dimension(150, 18));
progressBar.setStringPainted(true);
JPanel topBar = new JPanel(new BorderLayout(5, 0));
topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
topBar.add(direction, BorderLayout.CENTER);
topBar.add(botonBuscar, BorderLayout.EAST);
JPanel statusBar = new JPanel(new BorderLayout(5, 0));
statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
statusBar.add(labelStatus, BorderLayout.CENTER);
statusBar.add(progressBar, BorderLayout.EAST);
panelTodo.add(topBar, BorderLayout.NORTH);
panelTodo.add(javaFxPanel, BorderLayout.CENTER);
panelTodo.add(statusBar, BorderLayout.SOUTH);
getContentPane().add(panelTodo);
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
}
private void createScene() {
Platform.runLater(() -> {
view = new WebView();
engine = view.getEngine();
engine.setOnAlert((WebEvent<String> wEvent) -> {
System.out.println("JS alert() message: " + wEvent.getData());
});
engine.titleProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Navegador.this.setTitle(newValue);
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
#Override
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
labelStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> ov, String viejoValor, final String nuevoValor) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
direction.setText(nuevoValor);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.getLoadWorker().exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
#Override
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//TODO Handling Exception
}
});
}
}
});
javaFxPanel.setScene(new Scene(view));
});
}
public void loadURL(String url) {
Platform.runLater(new Runnable() {
#Override
public void run() {
String urlTemporal = toURL(url);
if (urlTemporal == null) {
urlTemporal = toURL("http://" + url);
}
engine.load(urlTemporal);
}
});
}
private static String toURL(String str) {
try {
return new URL(str).toExternalForm();
} catch (MalformedURLException exception) {
return null;
}
}
}
My problem is that when i open the navigator for the first time it works , but when i close it and then open again it only shows the TextField and the Button
Notes:
I use a javaswing button to open the navigator whit the
openNavigator() method
When i left one Navigator without closing and at the same time i
open one or more Navigators it works perfectly
First time I open the Navigator:
Second time I open the Navigator:
The JavaFX thread/toolkit must be running. Apparently, creating a JFXPanel is enough to initialize it, but once it is closed the thread is terminated automatically.
To stop it from automatically closing call
Platform.setImplicitExit(false);
so the JavaFX toolkit only closes when the Platform#exit method is called, or the entire application terminates.

JxBrowser view is gone when stage is hidden

I have used jxbrowser in my javafx app as this :
public class Main extends Application {
private Stage primaryStage;
private Browser browser;
private boolean firstMinimize;
private TrayIcon trayIcon;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
firstMinimize = true;
Platform.setImplicitExit(false);
createTrayIcon();
browser = new Browser();
BrowserView browserView = new BrowserView(browser);
StackPane pane = new StackPane();
pane.getChildren().add(browserView);
Scene scene = new Scene(pane, 380, 500);
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setScene(scene);
primaryStage.show();
browser.addRenderListener(new RenderAdapter() {
#Override
public void onRenderGone(RenderEvent event) {
System.out.println("here called...");
Browser browser = event.getBrowser();
// Restore Browser instance by loading the same URL
browser.loadURL(browser.getURL());
}
});
initialize();
// if not logged in
showLogin();
}
public void initialize() {
initCloseButton(primaryStage);
initMinimizeButton(primaryStage);
}
public void initCloseButton(Stage primaryStage) {
browser.registerFunction("Close", new BrowserFunction() {
#Override
public JSValue invoke(JSValue... args) {
Platform.runLater(new Runnable() {
#Override
public void run() {
closeToTray(primaryStage);
}
});
return null;
}
});
}
public void initMinimizeButton(Stage primaryStage) {
browser.registerFunction("Minimize", new BrowserFunction() {
#Override
public JSValue invoke(JSValue... args) {
Platform.runLater(new Runnable() {
#Override
public void run() {
primaryStage.setIconified(true);
}
});
return null;
}
});
}
public void createTrayIcon() {
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
java.awt.Image image = null;
try {
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
image = ImageIO.read(url);
} catch (IOException ex) {
System.out.println(ex);
}
final ActionListener closeListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
};
final ActionListener showListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
// primaryStage.setOpacity(0);
primaryStage.show();
}
});
}
};
PopupMenu popup = new PopupMenu();
MenuItem showItem = new MenuItem("Show");
showItem.addActionListener(showListener);
popup.add(showItem);
MenuItem closeItem = new MenuItem("Close");
closeItem.addActionListener(closeListener);
popup.add(closeItem);
trayIcon = new TrayIcon(image, "RezRem", popup);
trayIcon.addActionListener(showListener);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(e);
}
}
}
public void showMinimizeMessage() {
if (firstMinimize) {
trayIcon.displayMessage("some message",
"Some other message.",
TrayIcon.MessageType.INFO);
firstMinimize = false;
}
}
private void closeToTray(Stage primaryStage) {
Platform.runLater(new Runnable() {
#Override
public void run() {
if (SystemTray.isSupported()) {
// primaryStage.setOpacity(0);
primaryStage.hide();
showMinimizeMessage();
}
else {
System.exit(0);
}
}
});
}
public void showLogin() {
browser.loadURL(Main.class.getResource("templates/login.html").toExternalForm());
browser.registerFunction("Login", new BrowserFunction() {
#Override
public JSValue invoke(JSValue... args) {
for (JSValue arg : args) {
System.out.println("arg = " + arg.getString());
}
return JSValue.create("Hello!");
}
});
}
}
I have set close button to hide stage when clicked in function "closeToTray".(In order to minimize it to system tray) But then calling stage.show() brings up the browser but browser view is just a overall white, in other words, rendered page is gone this way. Here is a screenshot of before and after minimizing to system tray :
Before clicking close btn, after clicking show from system tray
any idea?
Thanks in advance
This is a known issue in JxBrowser 6.0.2. The fix will be available in next update that will be released in a week.

Overriding the process() Method in SwingWorker

I'm trying to dynamically update the GUI with a String. Can anyone see why the process method is not overriding correctly? I've looked at other questions and still cannot see how I am not overriding this correctly.
public class WorkerDemo extends JFrame {
private JLabel counterLabel = new JLabel("Not started");
private Worker worker = new Worker();
private JButton startButton = new JButton(new AbstractAction("Start") {
#Override
public void actionPerformed(ActionEvent arg0) {
worker = new Worker();
worker.execute();
}
});
private JButton stopButton = new JButton(new AbstractAction("Stop") {
#Override
public void actionPerformed(ActionEvent arg0) {
worker.cancel(true);
}
});
public WorkerDemo() {
add(startButton, BorderLayout.WEST);
add(counterLabel, BorderLayout.CENTER);
add(stopButton, BorderLayout.EAST);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
class Worker extends SwingWorker<Void, Integer> {
int counter = 0;
String abc = "abc";
#Override
protected Void doInBackground() throws Exception {
while(true) {
abc += abc;
publish(abc);
Thread.sleep(60);
}
}
#Override
protected void process(List<Object> chunk) {
// get last result
String to_return = (String) chunk.get(chunk.size()-1);
counterLabel.setText(to_return);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new WorkerDemo();
}
});
}
}
Since you have SwingWorker<Void, Integer>, you have defined Integer as a type to carry out intermediate results by publish and process methods. That means proper publish() and process() methods should use Integer:
#Override
protected Void doInBackground() throws Exception {
int someResult = 0;
...
publish(someResult);
...
}
#Override
protected void process(List<Integer> chunk) {
}
See SwingWorker for more details.

Can you use publish from a method called in run in background?

I am using swingworker to run a method in the background and periodically update the gui with information, but from what I've found publish can't be called from another class. Here's where my Swingworker is called:
private void start() {
worker = new SwingWorker <Void, String>() {
#Override
protected Void doInBackground() throws Exception {
navigator.navigator();
return null;
}
#Override
protected void process(List<String> chunks) {
for (String line : chunks) {
txtrHello.append(line);
txtrHello.append("\n");
}
}
#Override
protected void done() {
}
};
worker.execute();
}
And now from the navigator method I want to call publish(String);, how would I do this? Moving all of my methods into doInBackground() would be impossible.
Possible solution is to add an observer to your Navigator object, the key being to somehow allow the Navigator to communicate with any listener (here the SwingWorker) that its state has changed:
Give Navigator a PropertyChangeSupport object as well as an addPropertyChangeListener(PropertyChangeListener listener) method that adds the passed in listener to the support object.
Give Navigator some type of "bound" property, a field that when its state is changed, often in a setXxxx(...) type method, notifies the support object of this change.
Then in your SwingWorker constructor, add a PropertyChangeListener to your Navigator object.
In this listener, call the publish method with the new data from your Navigator object.
For example:
import java.awt.event.ActionEvent;
import java.beans.*;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class PropChangeSupportEg extends JPanel {
private MyNavigator myNavigator = new MyNavigator();
private JTextField textField = new JTextField(10);
public PropChangeSupportEg() {
textField.setFocusable(false);
add(textField);
add(new JButton(new StartAction("Start")));
add(new JButton(new StopAction("Stop")));
}
private class StartAction extends AbstractAction {
public StartAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
if (myNavigator.isUpdatingText()) {
return; // it's already running
}
MyWorker worker = new MyWorker();
worker.execute();
}
}
private class StopAction extends AbstractAction {
public StopAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
myNavigator.stop();
}
}
private class MyWorker extends SwingWorker<Void, String> {
#Override
protected Void doInBackground() throws Exception {
if (myNavigator.isUpdatingText()) {
return null;
}
myNavigator.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (MyNavigator.BOUND_PROPERTY_TEXT.equals(evt.getPropertyName())) {
publish(evt.getNewValue().toString());
}
}
});
myNavigator.start();
return null;
}
#Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textField.setText(chunk);
}
}
}
private static void createAndShowGui() {
PropChangeSupportEg mainPanel = new PropChangeSupportEg();
JFrame frame = new JFrame("Prop Change Eg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyNavigator {
public static final String BOUND_PROPERTY_TEXT = "bound property text";
public static final String UPDATING_TEXT = "updating text";
private static final long SLEEP_TIME = 1000;
private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
private String boundPropertyText = "";
private String[] textArray = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
private int textArrayIndex = 0;
private volatile boolean updatingText = false;
public void start() {
if (updatingText) {
return;
}
updatingText = true;
while (updatingText) {
textArrayIndex++;
textArrayIndex %= textArray.length;
setBoundPropertyText(textArray[textArrayIndex]);
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
}
public void stop() {
setUpdatingText(false);
}
public String getBoundPropertyText() {
return boundPropertyText;
}
public boolean isUpdatingText() {
return updatingText;
}
public void setUpdatingText(boolean updatingText) {
boolean oldValue = this.updatingText;
boolean newValue = updatingText;
this.updatingText = updatingText;
pcSupport.firePropertyChange(UPDATING_TEXT, oldValue, newValue);
}
public void setBoundPropertyText(String boundPropertyText) {
String oldValue = this.boundPropertyText;
String newValue = boundPropertyText;
this.boundPropertyText = boundPropertyText;
pcSupport.firePropertyChange(BOUND_PROPERTY_TEXT, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
}

Categories