How to make an overlay on top of JavaFX 2 webview? - webview

Is it possible to to overlay any JavaFx2 widgets or canvas on top of a JavaFX 2 webview?
I want to generate a transparent heatmap by means of JavaFX 2 on top of a webview.

Adding overlay is very easy: just put webview and any pane to StackPane.
Another story is to synchronize overlay and webview data. To achieve that you need to ask webview for object coordinates through javascript. Here is an example which finds stackoverflow question area and marks it on overlay:
public class WebOverlay extends Application {
#Override
public void start(Stage stage) {
StackPane root = new StackPane();
WebView webView = new WebView();
final WebEngine webEngine = webView.getEngine();
Canvas overlay = new Canvas(600,600);
overlay.setOpacity(0.5);
final GraphicsContext gc = overlay.getGraphicsContext2D();
gc.setFill(Color.RED);
root.getChildren().addAll(webView, overlay);
stage.setScene(new Scene(root, 600, 600));
webEngine.getLoadWorker().workDoneProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.intValue() == 100) {
// find coordinates by javascript call
JSObject bounds = (JSObject)webEngine.executeScript("document.getElementsByClassName('question-hyperlink')[0].getBoundingClientRect()");
Number right = (Number)bounds.getMember("right");
Number top = (Number)bounds.getMember("top");
Number bottom = (Number)bounds.getMember("bottom");
Number left = (Number)bounds.getMember("left");
// paint on overlaing canvas
gc.rect(left.doubleValue(), top.doubleValue(), right.doubleValue(), bottom.doubleValue());
gc.fill();
}
});
webEngine.load("http://stackoverflow.com/questions/10894903/how-to-make-an-overlay-on-top-of-javafx-2-webview");
stage.show();
}
public static void main(String[] args) { launch(); }
}

Do you mean something like this:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextBuilder;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Demo extends Application {
#Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
webView.getEngine().load("http://www.google.com");
StackPane root = new StackPane();
root.getChildren().addAll(webView, getOverlay());
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
private Pane getOverlay() {
StackPane p = new StackPane();
Rectangle r = RectangleBuilder.create()
.height(100).width(100)
.arcHeight(40).arcWidth(40)
.stroke(Color.RED)
.fill(Color.web("red", 0.1))
.build();
Text txt=TextBuilder.create().text("Overlay")
.font(Font.font("Arial", FontWeight.BOLD, 18))
.fill(Color.BLUE)
.build();
p.getChildren().addAll(r, txt);
return p;
}
public static void main(String[] args) {
launch(args);
}
}

Related

Vaadin guides - how to add them correctly

Good afternoon everybody.
I am creating a sales system that looks like this until now.
It shows my grid without any sales, as I am still implementing the system, we can also see the existence of 3 buttons (New, Change, Delete). So far so good.
When I click on the New button, a window opens
With the window open as shown in annex 2, we have 3 tabs (Sales, Delivery and Financial).
Each tab must have its own form and each form must have its own components (ComboBox, TextField, DatePicker ... etc)
From here I have countless problems, all caused by my lack of experience in programming, after all it's only a few months since I started learning.
My first problem:
With the current code, if I click on any of the three tabs, the same form, with the same components are displayed (see annex 3 and annex 4).
How do I ensure that each guide has its form and each form has its components?
See my code:
package br.com.fjsistemas.cadastros.view;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.NumberRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.service.VendaService;
#Route(value = "venda-view", layout = MainView.class)
#PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {
private static final long serialVersionUID = 1L;
private HorizontalLayout hltVenda = new HorizontalLayout();
Grid<Venda> grdVenda = new Grid<>(Venda.class, false);
private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
Button btnNovo = new Button("Novo");
Button btnAlterar = new Button("Alterar");
Button btnExcluir = new Button("Excluir");
private Dialog dlgJanela = new Dialog();
private FormLayout fltCamposVenda = new FormLayout();
HorizontalLayout layoutGuiaVenda = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda2 = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda3 = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda4 = new HorizontalLayout();
VerticalLayout layoutSeparar = new VerticalLayout();
VerticalLayout layoutSeparar2 = new VerticalLayout();
VerticalLayout layoutSeparar3 = new VerticalLayout();
#PropertyId("data")
private DatePicker txtDataVenda = new DatePicker("Data Venda");
#PropertyId("nomeCliente")
private TextField txtNomeCliente = new TextField("Nome Cliente");
#PropertyId("telefone")
private TextField txtTelefone = new TextField("Telefone");
#PropertyId("celular")
private TextField txtCelular = new TextField("Celular");
#PropertyId("produtos")
private ComboBox<String> txtProdutos = new ComboBox<>("Produtos");
#PropertyId("quantidade")
private NumberField txtQuantidade = new NumberField("Quantidade");
#PropertyId("unitario")
private TextField txtValorUnitario = new TextField("Valor Unitário");
#PropertyId("valorTotalVenda")
private NumberField txtValorTotalItem = new NumberField("Valor Total Item");
private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
private Button btnSalvar = new Button("Salvar");
private Button btnFechar = new Button("Fechar");
private Button btnAdicionarItem = new Button("Adicionar Item");
#Autowired
VendaService vendaService;
private List<Venda> listaVendas;
private Venda venda;
Binder<Venda> binderVenda = new Binder<>(Venda.class);
public VendaView() {
}
#PostConstruct
public void init() {
configuraTela();
}
private void configuraTela() {
setMargin(false);
setPadding(false);
configuraHltVenda();
configuraFltBarraBotoes();
configuraDlgJanela();
populaGrdVenda();
configuraBinder();
add(hltVenda, hltBarraBotoes);
}
private void configuraFltBarraBotoes() {
btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnNovo.addClickListener(e -> {
novoClick();
});
btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAlterar.addClickListener(e -> {
alterarClick();
});
btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnExcluir.addClickListener(e -> {
excluirClick();
});
hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
}
private void excluirClick() {
if (venda != null) {
listaVendas.remove(venda);
vendaService.delete(venda);
atualizaGrdVenda();
}
}
private void configuraHltVenda() {
hltVenda.setWidthFull();
configuraGrdVenda();
hltVenda.add(grdVenda);
}
private void configuraGrdVenda() {
grdVenda.setHeight("820px");
grdVenda.setWidthFull();
grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);
grdVenda.addColumn(Venda::getDataVenda).setHeader("Data Venda:").setAutoWidth(true).setKey("dataVenda");
grdVenda.addColumn(Venda::getCliente).setHeader("Cliente:").setAutoWidth(true).setKey("cliente");
grdVenda.addColumn(new NumberRenderer<>(Venda::getValorTotalVenda, "R$ %(,.2f", Locale.getDefault(), "R$ 0.00"))
.setHeader("Valor Total:").setAutoWidth(true).setKey("valorTotalVenda");
grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);
grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));
grdVenda.addItemClickListener(e -> {
venda = e.getItem();
});
}
private void configuraDlgJanela() {
dlgJanela.setHeight("800px");
dlgJanela.setWidth("860px");
Tab vender = new Tab("Vendas");
Div venderDiv = new Div();
Tab entregar = new Tab("Entregas");
Div entregarDiv = new Div();
entregarDiv.setVisible(false);
Tab financeiro = new Tab("Financeiro");
Div financeiroDiv = new Div();
financeiroDiv.setVisible(false);
LocalDate now = LocalDate.now();
txtDataVenda.setValue(now);
txtNomeCliente.setWidth("380px");
new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtTelefone);
new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtCelular);
txtQuantidade.setHasControls(true);
Label valorTotalCompra = new Label("VALOR TOTAL DA COMPRA R$:");
valorTotalCompra.getStyle().set("margin-top", "112px");
TextField campoValorTotal = new TextField("Valor Total da Compra");
campoValorTotal.getStyle().set("margin-top", "100px");
layoutGuiaVenda.add(txtDataVenda);
layoutGuiaVenda2.add(txtNomeCliente, txtTelefone, txtCelular);
layoutGuiaVenda3.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
layoutGuiaVenda4.add(valorTotalCompra, campoValorTotal);
fltCamposVenda.add(layoutGuiaVenda, layoutSeparar, layoutGuiaVenda2, layoutSeparar2, layoutGuiaVenda3,
layoutSeparar3, layoutGuiaVenda4);
vender.add(fltCamposVenda);
Map<Tab, Component> tabsToPages = new HashMap<>();
tabsToPages.put(vender, venderDiv);
tabsToPages.put(entregar, entregarDiv);
tabsToPages.put(financeiro, financeiroDiv);
Tabs tabs = new Tabs(vender, entregar, financeiro);
Div pages = new Div(venderDiv, entregarDiv, financeiroDiv);
tabs.addSelectedChangeListener(event -> {
tabsToPages.values().forEach(page -> page.setVisible(false));
Component selectedPage = tabsToPages.get(tabs.getSelectedTab());
selectedPage.setVisible(true);
});
dlgJanela.add(tabs, pages);
btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnSalvar.getStyle().set("margin-top", "180px");
btnSalvar.getStyle().set("margin-left", "0px");
btnSalvar.addClickListener(e -> {
salvarClick();
});
btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnFechar.getStyle().set("margin-top", "180px");
btnFechar.addClickListener(e -> {
dlgJanela.close();
});
btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAdicionarItem.getStyle().set("margin-top", "180px");
btnAdicionarItem.addClickListener(e -> {
});
htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem);
dlgJanela.add(fltCamposVenda, htlDlgBarraBotoes);
}
private void salvarClick() {
venda = binderVenda.getBean();
boolean adicionarLista = venda.getId() == null ? true : false;
vendaService.create(venda);
if (adicionarLista) {
listaVendas.add(venda);
}
atualizaGrdVenda();
novaVenda();
txtNomeCliente.focus();
binderVenda.setBean(venda);
if (adicionarLista) {
dlgJanela.close();
}
}
private void populaGrdVenda() {
listaVendas = vendaService.read();
atualizaGrdVenda();
}
private void atualizaGrdVenda() {
grdVenda.setItems(listaVendas);
}
private void configuraBinder() {
binderVenda.bindInstanceFields(this);
}
private void novoClick() {
novaVenda();
binderVenda.setBean(venda);
dlgJanela.open();
txtNomeCliente.focus();
}
private void alterarClick() {
if (venda != null) {
binderVenda.setBean(venda);
dlgJanela.open();
}
}
private void novaVenda() {
venda = new Venda();
venda.setCliente(" ");
dlgJanela.close();
}
}
Welcome to the world of programming. You still certainly have a bunch to learn, but it is very good that you are jumping into something new and taking that challenge!
Looking at your tabs code. The tabs and the content seems to be okay. When a tab is clicked, you hide all contents, then you find the one that matches the clicked tab, and you turn visibility on on that one.
If I however read this correctly, vender is the tab button at the top, and you put in (somehow) all the form content into this tab header with vender.add(fltCamposVenda);. I think that row should be `venderDiv.add(fltCamposVenda);.
Now tabs seem to switch content between venderDiv, entregarDiv, and financeiroDiv, but they are all three empty divs, so nothing changes on the screen when you switch their visibilities!
Can I offer you two pieces of advice?
1: Consider coding in English. Even if it is not your native tongue, getting help becomes a bunch easier, and you won't mix two languages like Venda and VerticalLayout.
2: Consider splitting your view into smaller classes. Now you have a view, a grid, a dialog, a tabsheet, multiple forms, and probably more, all mixed up in the same class. Any part of this can access all other parts and cause unexpected errors, and understanding the code becomes harder. E.g. instead of private Dialog dlgJanela = new Dialog();, you could do public class JanelaDialog extends Dialog { in JanelaDialog.java, and then instead initialize it with JanelaDialog dlgJanela = new JanelaDialog(). This way you have the grid view in one class and the dialog component in another, and the code becomes easier to manage.
Good luck :)

How to convert PlanarImage or BufferedImage (JAI) to Image (JavaFX)

I am trying to change the image represented in an ImageView instance, after manipulating it with JAI. JAI can output a PlanarImage, RenderedImage(non-awt), or BufferedImage(non-awt), but these are not valid types for ImageView construction.
import java.awt.image.renderable.ParameterBlock;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.Interpolation;
public class A11 extends Application{
int zoom = 100;
ImageView img = new ImageView();
Image src = new Image("file.bmp");
public static void main(String args[]){
launch(args); // start application
}
#Override
public void start(Stage window){
ParameterBlock pb = new ParameterBlock();
pb.addSource(src); // source Image
pb.add(zoom/100); // xScale
pb.add(zoom/100); // yScale
pb.add(0.0F); // xTranslate
pb.add(0.0F); // yTranslate
pb.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC));
PlanarImage dest = JAI.create("scale", pb, null);
// NEED TO CONVERT 'dest' TO 'destImage' HERE
ImageView frame = new ImageView(destImage);
ScrollPane pane = new ScrollPane(frame);
window.setScene(new Scene(pane,800,600));
window.show();
}
}

JavaFx OnError MediaView Memory leak

I have software that I am working on that uses JavaFx MediaPlayers and MediaViews to create a UI. For this to work the way we want we are reusing the MediaPlayers (after keeping them stored in a static class's hashMap) and then we place the MediaPlayer in new MediaViews when needed. When the MediaView is done we set it to null and move on, but this has lead to a memory leak where the number of players will stay constant but the mediaViews will increase. I made a minimal working version of this code so you can see the memory go up and up without collecting any mediaViews. It seems like the getOnError or the Error property from the MediaPlayer is holding onto an old reference of the MediaView. I would like to remove this, but it seems like you have to dispose of a mediaPlayer if you want to clean up all of it's memory, but I would like to save the Player and delete the View.
Here is some code that recreates the issue. Just hit the stop button a few times which will remove the old mediaView and add a new one, but none ever get cleaned up.
package JavaFx;
import java.io.File;
import java.net.URL;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
public class FxMediaExample1 extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
public MediaView mediaView;
public Scene scene;
public VBox root;
#Override
public void start(Stage stage)
{
// Locate the media content in the CLASSPATH
// Create a Media
File file = new File("file:///C:/Users/Samuel%20Johnston/Downloads/cf86c6a4-271f-4dcb-bb11-fc30f5eb6b45_web.mp4");
if (file.exists()) {
System.out.println("Boobs");
} else {
System.out.println("poop");
}
Media media = new Media("file:///C:/Users/Samuel%20Johnston/Downloads/cf86c6a4-271f-4dcb-bb11-fc30f5eb6b45_web.mp4");
media.setOnError(() -> {
System.out.println("WHAT THE WHAT, " + media.getError().toString());
System.out.println("WHAT THE WHAT, " + media.getError().getMessage());
System.out.println("WHAT THE WHAT, " + media.getError().getStackTrace().toString());
System.out.println("WHAT THE WHAT, " + media.getError().getLocalizedMessage());
});
// Create a Media Player
final MediaPlayer player = new MediaPlayer(media);
player.setOnError(() -> {
System.out.println("WHY THE WHY, " + player.getError().toString());
System.out.println("WHY THE WHY, " + player.getError().getMessage());
System.out.println("WHY THE WHY, " + player.getError().getStackTrace().toString());
System.out.println("WHY THE WHY, " + player.getError().getLocalizedMessage());
});
// Automatically begin the playback
player.setAutoPlay(true);
// Create a 400X300 MediaView
mediaView = new MediaView(player);
mediaView.setFitWidth(700);
mediaView.setFitHeight(700);
mediaView.setSmooth(true);
// Create the Buttons
Button playButton = new Button("Play");
Button stopButton = new Button("Stop");
// Create the Event Handlers for the Button
playButton.setOnAction(new EventHandler <ActionEvent>()
{
public void handle(ActionEvent event)
{
if (player.getStatus() == Status.PLAYING)
{
player.stop();
player.play();
}
else
{
player.play();
}
}
});
stopButton.setOnAction(new EventHandler <ActionEvent>()
{
public void handle(ActionEvent event)
{
player.stop();
root.getChildren().remove(mediaView);
mediaView = new MediaView(player);
mediaView.setFitWidth(700);
mediaView.setFitHeight(700);
mediaView.setSmooth(true);
root.getChildren().add(mediaView);
}
});
// Create the HBox
HBox controlBox = new HBox(5, playButton, stopButton);
// Create the VBox
root = new VBox(5,mediaView,controlBox);
// Set the Style-properties of the HBox
root.setStyle("-fx-padding: 10;" +
"-fx-border-style: solid inside;" +
"-fx-border-width: 2;" +
"-fx-border-insets: 5;" +
"-fx-border-radius: 5;" +
"-fx-border-color: blue;");
// Create the Scene
scene = new Scene(root);
// Add the scene to the Stage
stage.setScene(scene);
// Set the title of the Stage
stage.setTitle("A simple Media Example");
// Display the Stage
stage.show();
}
}

JavaFX WebView loading page in background

I have a problem using the JavaFX WebView. What I want to achieve is pre-fetching a web page in the background and visualiszing it only when the page is totally loaded.
I have made a simple exmaple program to reproduce the problem. After the page is loaded I enable a button. A Click on this button then makes the WebView visible.
The problem I have is, that if I click on the button when it gets enabled, the web page is not visible directly. Instead the following happens: At first there is a totally white panel and then after a short time the web page is visible. I don't understand why the page is not visible directly. How can I achieve it, that the web page is directly visible?
The following link points to an animated gif which shows the behaviour:
http://tinypic.com/view.php?pic=oh66bl&s=5#.Ujmv1RddWKk
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class WebViewTest extends javax.swing.JPanel {
private static JFXPanel browserFxPanel;
private WebView webView;
private WebEngine eng;
/**
* Creates new form WebViewTest
*/
public WebViewTest() {
initComponents();
Platform.setImplicitExit(false);
browserFxPanel = new JFXPanel();
Platform.runLater(new Runnable() {
public void run() {
webView = createBrowser();
Scene scene = new Scene(webView);
scene.setFill(null);
browserFxPanel.setScene(
scene);
}
});
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
* content of this method is always regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
pnlMain = new javax.swing.JPanel();
showWebpageButton = new javax.swing.JButton();
setLayout(new java.awt.GridBagLayout());
pnlMain.setLayout(new java.awt.BorderLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(pnlMain, gridBagConstraints);
showWebpageButton.setText("show web page");
showWebpageButton.setEnabled(false);
showWebpageButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
showWebpageButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10);
add(showWebpageButton, gridBagConstraints);
}// </editor-fold>
private void showWebpageButtonActionPerformed(java.awt.event.ActionEvent evt) {
pnlMain.removeAll();
pnlMain.add(browserFxPanel, BorderLayout.CENTER);
WebViewTest.this.invalidate();
WebViewTest.this.revalidate();
}
// Variables declaration - do not modify
private javax.swing.JPanel pnlMain;
private javax.swing.JButton showWebpageButton;
// End of variables declaration
private WebView createBrowser() {
Double widthDouble = pnlMain.getSize().getWidth();
Double heightDouble = pnlMain.getSize().getHeight();
final WebView view = new WebView();
view.setMinSize(widthDouble, heightDouble);
view.setPrefSize(widthDouble, heightDouble);
eng = view.getEngine();
eng.load("http://todomvc.com/architecture-examples/angularjs/#/");
eng.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
final double workDone = eng.getLoadWorker().getWorkDone();
final double totalWork = eng.getLoadWorker().getTotalWork();
if (workDone == totalWork) {
showWebpageButton.setEnabled(true);
}
}
});
return view;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame f = new JFrame("Navigator Dummy");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setSize(new Dimension(1024, 800));
final WebViewTest navDummy = new WebViewTest();
f.getContentPane().add(navDummy);
f.setVisible(true);
}
});
}
}
JFX needs a "stage" to show up its face. Modify your codes as following and it will work perfectly
/**
* Creates new form WebViewTest
*/
private Stage stage; // insert this line
public WebViewTest() {
initComponents();
Platform.setImplicitExit(false);
browserFxPanel = new JFXPanel();
Platform.runLater(new Runnable() {
public void run() {
webView = createBrowser();
Scene scene = new Scene(webView);
scene.setFill(null);
stage = new Stage(); // <<<
stage.setScene(scene); // <<<
browserFxPanel.setScene(scene);
}
});
}
...
private void showWebpageButtonActionPerformed(java.awt.event.ActionEvent evt) {
pnlMain.removeAll();
pnlMain.add(browserFxPanel, BorderLayout.CENTER);
WebViewTest.this.invalidate();
WebViewTest.this.revalidate();
stage.show(); // <<< afer click Button
}

Put a String on the edge of JUNG graph

I'm trying to put a String text to an edge of a JUNG tree graph. See bellow example.
What I tried is to simply add this line:
graph.addEdge("arrow", "Vmain", "Vsecond");
... but without any results (see bellow screenshot). I need some advices please.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.apache.commons.collections15.Factory;
import edu.uci.ics.jung.algorithms.layout.TreeLayout;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.Forest;
import edu.uci.ics.jung.graph.DelegateForest;
import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.graph.Tree;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
public class TreeVisualiser extends JApplet {
Forest<String, String> graph;
Factory<DirectedGraph<String, String>> graphFactory = new Factory<DirectedGraph<String, String>>() {
public DirectedGraph<String, String> create() {
return new DirectedSparseMultigraph<String, String>();
}
};
Factory<Tree<String, String>> treeFactory = new Factory<Tree<String, String>>() {
public Tree<String, String> create() {
return new DelegateTree<String, String>(graphFactory);
}
};
VisualizationViewer<String, String> vv;
String root;
TreeLayout<String, String> treeLayout;
#SuppressWarnings({"rawtypes", "unchecked"})
public TreeVisualiser() {
// create a simple graph for the demo
graph = new DelegateForest<String, String>();
createTree();
treeLayout = new TreeLayout<String, String>(graph);
vv = new VisualizationViewer<String, String>(treeLayout, new Dimension(600, 600));
vv.setBackground(Color.white);
vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
// add a listener for ToolTips
vv.setVertexToolTipTransformer(new ToStringLabeller());
Container content = getContentPane();
final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
content.add(panel);
final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
vv.setGraphMouse(graphMouse);
JComboBox modeBox = graphMouse.getModeComboBox();
modeBox.addItemListener(graphMouse.getModeListener());
graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
final ScalingControl scaler = new CrossoverScalingControl();
JButton plus = new JButton("+");
plus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scaler.scale(vv, 1.1f, vv.getCenter());
}
});
JButton minus = new JButton("-");
minus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scaler.scale(vv, 1 / 1.1f, vv.getCenter());
}
});
JPanel scaleGrid = new JPanel(new GridLayout(1, 0));
scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
JPanel controls = new JPanel();
scaleGrid.add(plus);
scaleGrid.add(minus);
controls.add(scaleGrid);
controls.add(modeBox);
content.add(controls, BorderLayout.SOUTH);
}
private void createTree() {
graph.addEdge("arrow", "Vmain", "Vsecond");
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Container content = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
content.add(new TreeVisualiser());
frame.pack();
frame.setVisible(true);
}
}
Oh, I missed this line of code. Now it is working as I want.
vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller());

Resources