Upcalls from JavaScript to JavaFX works fine. But if I add a variable containing the VLCJ player implementation then everything stops working.
Main.java:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import netscape.javascript.JSObject;
public class Main extends Application {
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
VLC player = new VLC(); // It doesn't work because of it. But if you remove that, then everything works.
#Override
public void start(final Stage stage) {
webEngine.setJavaScriptEnabled(true);
String HTML_STRING = //
"<html>"//
+ "<head> " //
+ " <script language='javascript'> " //
+ " function callToJavaFX() { "//
+ " myJavaMember.log('text'); " //
+ " } " //
+ " </script> "//
+ "</head> "//
+ "<body> "//
+ " <h2>This is Html content</h2> "//
+ " <button onclick='callToJavaFX();'>Call To JavaFX</button> "//
+ "</body> "//
+ "</html> "//
;
webEngine.loadContent(HTML_STRING);
Worker<Void> worker = webEngine.getLoadWorker();
worker.stateProperty().addListener(new ChangeListener<State>() {
#Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("myJavaMember", new JSBridge());
}
}
});
StackPane stack_pane = new StackPane(browser);
stage.setScene(new Scene(stack_pane,700, 400, Color.BLACK));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
JSBridge.java:
public class JSBridge {
public void log(String text) {
System.out.println(text);
}
}
VLC.java:
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
public class VLC{
private final MediaPlayerFactory mediaPlayerFactory;
private final EmbeddedMediaPlayer mediaPlayer;
public VLC() {
this.mediaPlayerFactory = new MediaPlayerFactory();
this.mediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer(); // It doesn't work because of it. But if you remove that, then everything works.
}
}
My modules:
So far, I have only been able to figure out that upcalls is not working due to the declaration of the variable 'player' in Main.java. But it will work if you change this.mediaPlayer = mediaPlayerFactory.mediaPlayers (). NewEmbeddedMediaPlayer () in VLC.java; on this.mediaPlayer = null
If you remove the line 'VLC player = new VLC ();' then everything works. If it is not deleted, then the method 'myJavaMember.log (' text ')' will not work and there will be an error: 'TypeError: myJavaMember.log is not a function (In' myJavaMember.log ('text') ',' myJavaMember.log ' is undefined). Why is that?
Please tell me how to fix this and what could be the reason?
P.S.: I know how to implement VLCJ. It works for me. Here is only the code that can repeat the error that worries me.
The problem is that upcalls doesn't work. I repeat how to implement the VLCJ player I know.
Solved the problem thanks to this answer: https://stackoverflow.com/a/53618875/10946427
It turns out my JSBridge was being destroyed by the garbage collector and because of VLCJ it was faster.
If you create a JSBridge variable inside the class, then the garbage collector will not destroy it and everything will work.
Related
I'm attempting to have two transparent WebViews displayed one on top of the other.
They display alright, however, hyperlinks can only clicked for the WebView at the top.
My understanding is that by setting setPickOnBounds(false), clicks on transparent pixels of the top WebView should go through to the bottom WebView. However, it does appear to be work this way, with the top WebView blocking all clicks.
Is there a way to have overlapping WebView with hyperlinks working for both?
Example:
import java.lang.reflect.Field;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.w3c.dom.Document;
public class DoubleWebViews extends Application {
#Override
public void start(Stage primaryStage) {
new WebPage(primaryStage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
static class WebPage{
WebView webViewBack = new WebView();
WebView webViewFront = new WebView();
public WebPage(Stage mainstage){
setupWebView(webViewBack, "<a href='https://www.google.com'>URL 1</a> can't be clicked!");
setupWebView(webViewFront, "<br><br><br><a href='https://www.google.com'>URL 2</a>");
StackPane root = new StackPane(webViewBack, webViewFront);
root.setPickOnBounds(false);
Scene scene = new Scene(root);
mainstage.setScene(scene);
mainstage.initStyle(StageStyle.TRANSPARENT);
}
void setupWebView(WebView webView, String html){
webView.setPickOnBounds(false); // doesn't work?
WebEngine webEngine = webView.getEngine();
webEngine.documentProperty().addListener(new DocListener(webEngine));
webEngine.loadContent("<body style='background : rgba(0,0,0,0);font-size: 70px;text-align:center;'>" + html + "</body>");
}
static class DocListener implements ChangeListener<Document>{
private final WebEngine webEngine;
public DocListener(WebEngine webEngine) { this.webEngine = webEngine;}
#Override
public void changed(ObservableValue<? extends Document> observable, Document oldValue, Document newValue) {
try {
// Use reflection to retrieve the WebEngine's private 'page' field.
Field f = this.webEngine.getClass().getDeclaredField("page");
f.setAccessible(true);
com.sun.webkit.WebPage page = (com.sun.webkit.WebPage) f.get(this.webEngine);
page.setBackgroundColor((new java.awt.Color(0, 0, 0, 0)).getRGB());
} catch (Exception ignored) {}
}
}
}
}
I've not found an elegant solution yet, but this works.
First, the mouse events received by the front WebView webViewFront need to be forwarded to webViewBack:
webViewFront.addEventFilter(MouseEvent.ANY, event -> webViewBack.fireEvent(event));
This will enable clicks, drags, etc to work on both frames.
As for using the correct cursor, that is a little tricky. Only the cursor of the front WebView is displayed. Therefore, our back WebView must be allowed to modify the front cursor:
webViewBack.cursorProperty().addListener((obs, oldCursor, newCursor) -> webViewFront.setCursor(newCursor));
The problem is now that webViewFront constantly resets its cursor to default if a mouse event occurs and there is no hyperlinks at that location in webViewFront. Therefore, we prevent this reset:
webViewFront.cursorProperty().addListener((obs, oldCursor, newCursor) -> {
if (newCursor != null && "DEFAULT".equals(newCursor.toString())) {
webViewFront.setCursor(webViewBack.getCursor());
}
});
Together, these three changes allow two overlapping WebView with hyperlinks working for both.
My java program doesn't compile and I am simply looking to get to the point where my java program runs the FXML file and simply displays the GUI. I don't know how to get to that point.
I used Scenebuilder to writes the code for the GUI but I am not sure how attach the design code to the code so that it displays.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javax.swing.*;
public class Main extends Application {
private JTextField guess_space; // text field for user's guess
private JLabel bottom_Lab; // label for too high/too low output
private int theNumber; // The number we are trying to find
public void checkGuess() { // Method that checks Hi-Lo of guess
String guessText = guess_space.getText();
String message;
// Check the guess for too high/too low
int guess = Integer.parseInt(guessText);
// if the guess is too high
if (guess > theNumber) {
message = guess + " was too high. Guess again!";
bottom_Lab.setText(message);
}
// if the guess is too low
else if (guess < theNumber) {
message = guess + " was too low. Guess again!";
bottom_Lab.setText(message);
}
else {
message = guess + " was the correct guess. You Win!!!";
}
}
public void newGame() {
theNumber = (int)(Math.random()* 100 + 1);
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("GuessingGame.fxml"));
primaryStage.setTitle("Guessing Game");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
Main theGame = new Main();
theGame.newGame();
}
public static void main(String[] args) {
launch(args);
}
Controller.java
package sample;
import xxx
public class Controller {
}
Swing and JavaFX are two different java based frameworks tailored to building desktop UIs; and they do not naturally interoperate. Even when you are mostly using JavaFX, you are including JTextField and JLabel swing components in your application.
I'd like to know if it is possible to make a progress bar displayed on the taskbar like Windows Explorer does when there's a file operation going on?
I saw many examples, but they all involved C#.
SWT won't cut it.
I found out that this feature is included in Java 9. It is part of AWT and it is quity simple too use.
Here is short example:
import java.awt.Taskbar;
import java.awt.Taskbar.State;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
/**
* #author fxl
*/
public class TaskbarSample {
public static void main(String[] args) {
// JavaDoc:
// https://docs.oracle.com/javase/9/docs/api/java/awt/Taskbar.html
// MSDNDoc:
// https://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx
if (Taskbar.isTaskbarSupported() == false) {
return;
}
JFrame dialog = new JFrame("Test - 50%");
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
Taskbar taskbar = Taskbar.getTaskbar();
taskbar.setWindowProgressState(dialog, State.ERROR);
taskbar.setWindowProgressValue(dialog, 50);
}
}
this is now possible using SWT please review the code example:
org.eclipse.swt.snippets.Snippet336
This example will do the job:
Task bar:
Code:
import org.bridj.Platform;
import org.bridj.Pointer;
import org.bridj.cpp.com.COMRuntime;
import org.bridj.cpp.com.shell.ITaskbarList3;
import org.bridj.jawt.JAWTUtils;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TaskBarListDemo extends JFrame implements ActionListener, ChangeListener
{
private ITaskbarList3 list;
private JSlider slider;
private Pointer<?> hwnd;
private TaskBarListDemo() throws ClassNotFoundException
{
super("TaskbarList Demo (" + (Platform.is64Bits() ? "64 bits" : "32 bits") + ")");
list = COMRuntime.newInstance(ITaskbarList3.class);
getContentPane().add("Center", new JLabel("Hello Native Windows 7 World !"));
Box box = Box.createVerticalBox();
int min = 0;
int max = 300;
int val = (min + max / 2);
slider = new JSlider(min, max, val);
slider.addChangeListener(this);
box.add(slider);
ButtonGroup group = new ButtonGroup();
for (ITaskbarList3.TbpFlag state : ITaskbarList3.TbpFlag.values())
{
JRadioButton cb = new JRadioButton(state.name());
group.add(cb);
cb.putClientProperty(ITaskbarList3.TbpFlag.class, state);
cb.setSelected(state == ITaskbarList3.TbpFlag.TBPF_NORMAL);
cb.addActionListener(this);
box.add(cb);
}
getContentPane().add("South", box);
}
#Override
protected void finalize() throws Throwable
{
super.finalize();
list.Release();
}
public void setVisible(boolean visible)
{
super.setVisible(visible);
long hwndVal = JAWTUtils.getNativePeerHandle(this);
hwnd = Pointer.pointerToAddress(hwndVal);
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
}
#Override
public void stateChanged(ChangeEvent actionEvent)
{
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
}
#Override
public void actionPerformed(ActionEvent actionEvent)
{
JRadioButton button = ((JRadioButton) actionEvent.getSource());
if (button.isSelected())
{
ITaskbarList3.TbpFlag flag = (ITaskbarList3.TbpFlag) button.getClientProperty(ITaskbarList3.TbpFlag.class);
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
list.SetProgressState((Pointer) hwnd, flag);
}
}
public static void main(String[] arguments) throws Exception
{
TaskBarListDemo f = new TaskBarListDemo();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
Maven dependencies:
<dependencies>
<dependency>
<groupId>com.nativelibs4java</groupId>
<artifactId>bridj</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>
There is no standard facility in Java for doing so, yet.
Hence you need to talk to Windows directly to do that. So you need to locate the correct Windows routine, and use JNA (probably the easiest) to invoke that routine. I do not know of a vendor or a project who has done this already.
Edit: It appears that the http://code.google.com/p/nativelibs4java/ project may do what you want.
As Java9's java.awt.Taskbar only works for old swing frames (they somehow forgot to implement this for javafx.stage.Stage) and com.nativelibs4java bridj isn't working (anymore) (see https://github.com/nativelibs4java/BridJ/issues/94) I implemented a solution using JNA 4.1.0.
Please note:
Relies on calling internal javafx api (com.sun.javafx.stage.WindowHelper) - so it might break with the next java update
It only sets the "indeterminate" progress state - but normal progress state should be possible too with some adjustments
Hope this helps.
ITaskbarList3.java
package example;
import com.sun.jna.platform.win32.Guid.IID;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
public interface ITaskbarList3 {
IID IID_ITASKBARLIST3 = new IID("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf"); // from ShObjIdl.h
int TBPF_NOPROGRESS = 0;
int TBPF_INDETERMINATE = 0x1;
int TBPF_NORMAL = 0x2;
int TBPF_ERROR = 0x4;
int TBPF_PAUSED = 0x8;
HRESULT SetProgressState(HWND hwnd, int tbpFlags);
}
TaskbarList3.java
package example;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.COM.COMInvoker;
public final class TaskbarList3 extends COMInvoker implements ITaskbarList3 {
public TaskbarList3(Pointer pointer) {
setPointer(pointer);
}
#Override
public HRESULT SetProgressState(HWND hwnd, int tbpFlags) {
return (HRESULT) this._invokeNativeObject(
10, // magic number (gathered by trial and error)
new Object[] { this.getPointer(), hwnd, tbpFlags },
HRESULT.class);
}
}
TaskbarPeer.java
package example;
import com.sun.javafx.stage.WindowHelper;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.CLSID;
import com.sun.jna.platform.win32.Ole32;
import com.sun.jna.platform.win32.W32Errors;
import com.sun.jna.platform.win32.WTypes;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.ptr.PointerByReference;
import javafx.stage.Stage;
public final class TaskbarPeer {
public static void setIndeterminateProgress(Stage stage, boolean indeterminate) {
final var peer = WindowHelper.getPeer(stage);
final long windowHandle = peer.getRawHandle();
final var clsid = new CLSID("56FDF344-FD6D-11d0-958A-006097C9A090"); // from ShObjIdl.h
final var taskbarListPointerRef = new PointerByReference();
var hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, WTypes.CLSCTX_SERVER,
ITaskbarList3.IID_ITASKBARLIST3, taskbarListPointerRef);
if (W32Errors.FAILED(hr)) {
throw new RuntimeException("failed with code: " + hr.intValue());
}
final TaskbarList3 taskbarList = new TaskbarList3(taskbarListPointerRef.getValue());
final var hwnd = new HWND(new Pointer(windowHandle));
final int progressState = indeterminate ? ITaskbarList3.TBPF_INDETERMINATE : ITaskbarList3.TBPF_NOPROGRESS;
hr = taskbarList.SetProgressState(hwnd, progressState);
if (W32Errors.FAILED(hr)) {
throw new RuntimeException("failed with code: " + hr.intValue());
}
}
}
Sample.java
package example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public final class Sample extends Application {
private boolean indeterminateProgressState = false;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
final Button btn = new Button("Click me!");
primaryStage.setScene(new Scene(btn));
primaryStage.sizeToScene();
primaryStage.show();
btn.setOnAction(evt -> {
indeterminateProgressState = !indeterminateProgressState;
TaskbarPeer.setIndeterminateProgress(primaryStage, indeterminateProgressState);
});
}
}
Windows exposes this through COM. I am sure a "flat DLL" call would be easier for you, but if you can get to COM you can do this. The COM interface is ITaskbarList3 (there is also an ITaskbarList4 you can use that inherits from it.) http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx documents it. SetProgressState and SetProgressValue are the methods you will want to invoke. State is normal (green), paused (yellow), error (red), indeterminate (swooshing green) and none. On the MSDN page some community people have added details of calling this COM component from VB and C# - that might help you figure out the setup and tear down required from Java.
I noticed a really strange behaviour with menu accelerators on the JavaFX (system) menu. Some key combinations don't work at all and others are interpreted as the wrong key.
For instance, when you use the CMD+CLEAR key as accelerator, it gets changed as the CMD+Page Down down key (both in the menu text and in the actual response to a keyboard event). The '-' (MINUS) key doesn't work well at all and while, CMD + - shows up well in the menu, it never gets triggered when you press the keys. When on the other hand you add the ALT key (i.e., you press CMD+ALT+-), the CMD- events does get triggered (but not the CMD+ALT+- one).
Any idea what's going on, or is this a (know) bug?
I have created below sample program to illustrate this.
Note: I'm on a Mac.
package menuaccelerator;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MenuAccelerator extends Application {
// Counter for the event number
int eventNr = 0;
#Override
public void start(Stage primaryStage) {
// Text Area for displaying the events
TextArea events = new TextArea();
events.setEditable(false);
events.setOnKeyPressed((e) -> {
System.out.println("Key Event(" + ++eventNr + "): " + e);
events.appendText((eventNr == 1 ? "" : "\n") + "KeyCode(" + eventNr + "): " + e.getCode());
e.consume();
});
// Menu Bar & Menu
MenuBar menuBar = new MenuBar();
menuBar.setUseSystemMenuBar(true);
Menu menu = new Menu("Accelerator Test");
menuBar.getMenus().add(menu);
// Build menu
for (String item : new String[]{"Shortcut+PLUS", "Shortcut+Alt+PLUS",
"Shortcut+MINUS", "Shortcut+Alt+MINUS",
"Shortcut+PAGE__UP", "Shortcut+Alt+PAGE__UP",
"Shortcut+PAGE__DOWN", "Shortcut+Alt+PAGE__DOWN",
"Shortcut+CLEAR"}) {
MenuItem menuItem = new MenuItem(item);
menuItem.setAccelerator(KeyCombination.keyCombination(item));
menuItem.setOnAction((ActionEvent e) -> {
System.out.println("Menu Event(" + ++eventNr + "): " + e);
events.appendText((eventNr == 1 ? "" : "\n") + "Menu Event(" + eventNr + "): " + ((MenuItem) e.getSource()).getText());
e.consume();
});
menu.getItems().add(menuItem);
}
// Create scene
StackPane root = new StackPane();
VBox vbox = new VBox(10);
vbox.setAlignment(Pos.CENTER);
vbox.getChildren().add(events);
root.getChildren().add(vbox);
root.getChildren().add(menuBar);
Scene scene = new Scene(root, 300, 200);
// Display scene
primaryStage.setTitle("Accelerator Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I'm doing an interface to show the progress of my simulation (elevators simulating job on a building).
The thing is, I already did this on the console with System.out.println()s and I wanted to show the exact same thing on a javaFX window. Is there any way where I can set the text of a TextArea or a Label or something to match the output of the console? Just printing the same thing but instead of printing on the console I wanted to print on a window.
I was dumb enough to try and set the Text of a TextAreato the toString() of my simulator but ofc if it is System.out.println(), it shows on the console and not in the ThextArea.
EDIT: This is what I want to print:
#Override
public String toString() {
for (int y = 0; y < 50; y++) {
System.out.println("");
}
for (int i = pisos.size() - 1; i >= 0; i--) {
System.out.print(pisos.get(i).getPiso());
System.out.print(pisos.get(i).pQueue().toString());
System.out.print(" " + percorrerElevadores2(i));
System.out.print(" " + pisos.get(i).pessoasServidas() + "\n");
}
System.out.println("Numero total de passageiros à espera:" + " " + Predio.getPredio().getNPessoasEmEspera());
System.out.println("Numero total de pessageiros servidos:" + " " + Predio.getPredio().getNPessoasServidas());
for (int z = 0; z < getElevadores().size(); z++) {
System.out.println("Distancia percorrida pelo elevador" + " " + z + ":" + " " + Predio.getPredio().getElevadores().get(z).getDistanciaPercorrida() + " " + "Pisos");
System.out.println("Piso destino do elevador" + " " + z + ":" + " " + Predio.getPredio().getElevadores().get(z).getPisoDestino());
}
return "";
}
It is better to use the MessageDialogBox to print the message on window with reference of the panel on which you are working.
I don't really understand your question but it would be easier to rename the println calls than to redirect them. Use some code like this in your main class (the one that extends Application) or really in any class, but you need to add the textArea to the scene graph somewhere.
private static final TextArea textArea = new TextArea();
//add textArea to your scene somewhere in the start method
public static void println(String s){
Platform.runLater(new Runnable() {//in case you call from other thread
#Override
public void run() {
textArea.setText(textArea.getText()+s+"\n");
System.out.println(s);//for echo if you want
}
});
}
Then just use the IDE's search and replace to rename System.out.println to MainClassName.println.
From what I understand, you just want to print text in a location to investigate things, ie the results. Everything you want is just like you print a text on the console, you also want to print this text somewhere in a JavaFX application. Despite its formatting done in their toString method, you can catch the return of the method and print to a JavaFX application (within a control node, for example), right?
If this is the case ...
I created a simple application that works with two text areas. In the middle of application, you will find buttons that manipulate both areas. Basically, the buttons sends the contents of a text area to another. Note:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class AreaTextual extends Application
{
// #########################################################################################################
// MAIN
// #########################################################################################################
public static void main(String[] args)
{
Application.launch(args);
}
// #########################################################################################################
// INSTÂNCIAS
// #########################################################################################################
// Controles.
private Label lab_receptor;
private Label lab_emissor;
private TextArea tArea_receptor;
private TextArea tArea_emissor;
private Button bot_enviar;
private Button bot_enviarLinha;
private Button bot_substituir;
private Button bot_apagar;
// Layout.
private HBox hbox_raiz;
private VBox vbox_oeste;
private VBox vbox_centro;
private VBox vbox_leste;
// #########################################################################################################
// INÍCIO FX
// #########################################################################################################
#Override public void start(Stage estagio) throws Exception
{
this.iniFX();
this.confFX();
this.adFX();
this.evFX();
Scene cenario = new Scene(this.hbox_raiz , 640 , 480);
estagio.setScene(cenario);
estagio.setTitle("Programa JavaFX");
estagio.show();
}
/** Inicia nós FX.*/
protected void iniFX()
{
// Controles.
this.lab_receptor = new Label();
this.lab_emissor = new Label();
this.tArea_receptor = new TextArea();
this.tArea_emissor = new TextArea();
this.bot_enviar = new Button();
this.bot_enviarLinha = new Button();
this.bot_substituir = new Button();
this.bot_apagar = new Button();
// Layout.
this.hbox_raiz = new HBox();
this.vbox_oeste = new VBox();
this.vbox_centro = new VBox();
this.vbox_leste = new VBox();
}
/** Configura nós FX.*/
protected void confFX()
{
// Controles.
this.lab_receptor.setText("RECEPTOR");
this.lab_receptor.setFont(new Font(32));
this.lab_emissor.setText("EMISSOR");
this.lab_emissor.setFont(new Font(32));
this.bot_enviar.setText("<- ENVIAR");
this.bot_enviar.setPrefSize(150 , 60);
this.bot_enviarLinha.setText("<- ENVIAR+");
this.bot_enviarLinha.setPrefSize(150 , 60);
this.bot_substituir.setText("<- SUBSTITUIR");
this.bot_substituir.setPrefSize(150 , 60);
this.bot_apagar.setText("<- APAGAR TUDO ->");
this.bot_apagar.setPrefSize(150 , 60);
// Layout.
this.hbox_raiz.setSpacing(20);
this.hbox_raiz.setPadding(new Insets(30 , 30 , 30 , 30));
this.hbox_raiz.setAlignment(Pos.CENTER);
this.vbox_oeste.setSpacing(10);
this.vbox_oeste.setAlignment(Pos.CENTER);
this.vbox_centro.setSpacing(10);
this.vbox_centro.setAlignment(Pos.CENTER);
this.vbox_centro.setPrefSize(400 , 200);
this.vbox_leste.setSpacing(10);
this.vbox_leste.setAlignment(Pos.CENTER);
}
/** Adiciona e organiza em layout os nós FX.*/
protected void adFX()
{
this.vbox_leste.getChildren().addAll(this.lab_emissor , this.tArea_emissor);
this.vbox_centro.getChildren().addAll(this.bot_enviar , this.bot_enviarLinha , this.bot_substituir , this.bot_apagar);
this.vbox_oeste.getChildren().addAll(this.lab_receptor , this.tArea_receptor);
this.hbox_raiz.getChildren().addAll(this.vbox_oeste , this.vbox_centro , this.vbox_leste);
}
/** Configura eventos de nós FX.*/
protected void evFX()
{
this.bot_enviar.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
tArea_receptor.appendText(tArea_emissor.getText());
}
});
this.bot_enviarLinha.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
tArea_receptor.appendText(String.format("%n%s" , tArea_emissor.getText()));
}
});
this.bot_substituir.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
tArea_receptor.replaceText(0 , tArea_receptor.getLength() , tArea_emissor.getText());
}
});
this.bot_apagar.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
tArea_receptor.setText("");
tArea_emissor.setText("");
}
});
}
}
OBS (PT-BR): Eu notei que você fala português, portanto deixei o código na linguagem para que você entenda-o melhor.
This class has nothing exceptional. It just shows you how you can manipulate the text of a TextArea. You can find other types of handlers of a TextArea right here, and also here.
Regarding your problem seen where you call the JavaFX methods from another thread, this can be happening just because you're not using the JavaFX Application Thread. Like the Swing library has the Event Dispatch Thread (EDT), JavaFX also has its own thread responsible for handling the JavaFX elements. Whenever you need to manipulate any JavaFX element, be to setup something or to obtain some data, you need to do this using the JavaFX Application Thread, and not another.
For you to call methods of the JavaFX Application Thread, use the Platform runLater method. For more information about the JavaFX threads system, visit the following links:
http://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
In the first link, read the part that talks about threads. If you have any more questions, come back here and ask.
Good luck.