I wrote a program which makes use of drag and drop in javafx. In JavaFX8 it works perfectly.
In JavaFX11, the drag and drop is dysfunctional: I don't get a different mouse cursor, I don't get a ghost image of the row I'm dragging, and something's wrong with the drops -- they don't trigger on mouse release, and then the drop is triggered each time I click on the table.
Here is minimum runnable example which demonstrates the issue I'm facing. Run on a Java 8 JVM it works as desired. On Java 11 JVM it does not. I am on Ubuntu 18.04.
I'm fine with changing my code to accommodate Java 11, but I don't have any idea what I'm doing wrong.
Java 11 Version
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
Java 8 Version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
DND11.java
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.stage.Stage;
public class DND11 extends Application {
public TableView<Person> getTable () {
DataFormat DRAGGED_PERSON = new DataFormat ( "application/example-person" );
TableColumn <Person, String> firstNameColumn = new TableColumn <> ( "First Name" );
TableColumn <Person, String> LastNameColumn = new TableColumn <> ( "Last Name" );
firstNameColumn.setCellValueFactory( new PropertyValueFactory <Person, String>( "firstName" ) );
LastNameColumn.setCellValueFactory( new PropertyValueFactory <Person, String>( "lastName" ) );
TableView <Person> tableView = new TableView <> ();
tableView.getColumns().addAll( firstNameColumn, LastNameColumn );
tableView.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY );
tableView.setEditable( false );
tableView.setItems( FXCollections.observableArrayList( Person.generatePersons ( 10 ) ) );
tableView.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE );
tableView.setRowFactory( tv -> {
TableRow <Person> row = new TableRow <>();
row.setOnDragDetected( event -> {
if ( !row.isEmpty() ) {
Dragboard db = row.startDragAndDrop( TransferMode.COPY );
ClipboardContent cc = new ClipboardContent();
cc.put( DRAGGED_PERSON, row.getItem() );
tableView.getItems().remove( row.getItem() );
db.setContent( cc );
}
});
row.setOnDragOver( event -> {
Dragboard db = event.getDragboard();
event.acceptTransferModes( TransferMode.COPY );
});
row.setOnDragDropped( event -> {
Dragboard db = event.getDragboard();
Person person = (Person)event.getDragboard().getContent( DRAGGED_PERSON );
if ( person != null ) {
tableView.getItems().remove( person );
int dropIndex = row.getIndex();
tableView.getItems().add( dropIndex, person );
}
event.setDropCompleted( true );
event.consume();
});
return row;
});
return tableView;
}
#Override
public void start ( Stage stage ) throws Exception {
stage.setScene( new Scene( getTable(), 800, 400 ) );
stage.show();
}
public static void main ( String[] args ) {
launch( args );
}
}
Person.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName, lastName;
public Person ( String firstName, String lastName ) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public static List <Person> generatePersons ( int number ) {
List<Person> retMe = new ArrayList<Person> ( number );
for ( int k = 0; k < number; k++ ) {
retMe.add ( new Person ( randomFirstName(), randomLastName() ) );
}
return retMe;
}
private static Random rand = new Random();
private static String randomFirstName() {
return firstNames [ Math.abs( rand.nextInt() ) % firstNames.length ];
}
private static String randomLastName() {
return lastNames [ Math.abs( rand.nextInt() ) % lastNames.length ];
}
private static String[] firstNames = new String[] {
"ANTON","ANTONE","ANTONIA","NTONIO","ANTONY","ANTWAN","ARCHIE","ARDEN","ARIEL","ARLEN",
"ARMAND","ARMANDO","ARNOLD","ARNOLDO","ARNULF","ARON","ARRON","ART","ARTHUR","ARTURO",
"DARRICK","DARRIN","DARRON","DARRYL","DARWIN","DARYL","DAVE","DAVID","DAVIS","DEAN",
};
private static String[] lastNames = new String[] {
"SMITH","JOHNSON","WILLIAMS","BROWN","JONES","MILLER","DAVIS","GARCIA","RODRIGUEZ",
"WILSON","MARTINEZ","ANDERSON","TAYLOR","THOMAS","HERNANDEZ","MOORE","MARTIN","JACKSON"
};
}
While Drag and Drop in JavaFX has a common API for all the platforms (as the rest of the API, of course), its internal implementation is platform dependent, and it is quite different on Windows, Mac or Linux.
But this shouldn't be an issue when migrating from JavaFX 8 to JavaFX 11, though.
The sample posted by the OP works the same on Windows and Mac with both JavaFX 8 and 11, and if it is not the case on Linux, it might have to do with the changes done in the latest release of JavaFX for Linux.
According to the releases note, under the Important Changes section we can see:
Switch default GTK version to 3
JavaFX will now use GTK 3 by default on Linux platforms where the gtk3 library is present. Prior to JavaFX 11, the GTK 2 library was the default. This matches the default for AWT in JDK 11. See JDK-8198654 for more information.
While this change was basically a two lines diff in the JavaFX code, and nothing changed from the implementation details for DND, the GTK 3 implementation might have changed from GTK 2, and those changes haven't been taken into account.
Similar issues related to GTK have been reported for dialogs, windows or Wayland crashes.
Workaround
So far the only known workaround for all of those issues is to run the app with GTK 2, that can be set with the system property: jdk.gtk.version.
So this option can be added on command line:
java -Djdk.gtk.version=2 ...
to run the application.
As posted in the comments, this seems to solve the drag and drop issue.
Report the issue
Definitely, that confirms that this is an issue, and as such it should be filed at the OpenJFX issue tracker, providing the sample code to reproduce it, system details (OS version, Java version, JavaFX version...).
Related
I have multiple DatePickers in my project and I want to make it so that the user cannot edit the text field and so they can't select a date before todays date on all of them.
I know how to do this to individual DatePickers but I want a way to apply this to all of them.
Here's the code I would use for them individually:
DatePicker datePicker = new DatePicker();
datePicker.getEditor().setDisable(true);
datePicker.getEditor().setOpacity(1);
datePicker.setDayCellFactory(param -> new DateCell() {
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.compareTo(LocalDate.now()) < 0 );
}
});
Edit:
As James_D commented I could just put these commands in a method which is the solution I used. Using a builder for this is also interesting, thanks for the detailed answer.
Use some kind of creational pattern, e.g. a builder pattern.
Create an implementation of Builder<DatePicker>:
import java.time.LocalDate;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.util.Builder;
public class DatePickerBuilder implements Builder<DatePicker>{
public DatePicker build() {
DatePicker datePicker = new DatePicker();
datePicker.getEditor().setDisable(true);
datePicker.getEditor().setOpacity(1);
datePicker.setDayCellFactory(param -> new DateCell() {
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.compareTo(LocalDate.now()) < 0 );
}
});
return datePicker ;
}
}
If you're creating your DatePickers in Java code, you can simply instantiate a DatePickerBuilder and use it:
private final DatePickerBuilder datePickerBuilder = new DatePickerBuilder();
// ...
// any time you need a `DatePicker` do
DatePicker datePicker = datePickerBuilder.build();
If you're using FXML, you can wrap the DatePickerBuilder in a custom BuilderFactory:
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.control.DatePicker;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
public class DatePickerBuilderFactory implements BuilderFactory {
private final BuilderFactory defaultFactory ;
private final DatePickerBuilder builder ;
public DatePickerBuilderFactory() {
defaultFactory = new JavaFXBuilderFactory();
builder = new DatePickerBuilder();
}
#Override
public Builder<?> getBuilder(Class<?> type) {
if (type == DatePicker.class) {
return builder;
} else return defaultFactory.getBuilder(type) ;
}
}
which you can then supply to your FXMLLoader:
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("path/to/fxml"));
fxmlLoader.setBuilderFactory(new DatePickerBuilderFactory());
Parent root = fxmlLoader.load();
Deprecation note:
The individual Builder classes defined in JavaFX version 2.0 were deprecated in version 8.0 due to an implementation error, and removed in version 9 as there was no clean way to fix that error.
However, the BuilderFactory and Builder interfaces are still supported and used by the FXMLLoader, so this code is still supported.
A relative Java newbie question.
I'm cleaning up my code and came across two unchecked warnings ("unchecked method invocation" and "unchecked conversion") while programmatically selecting a cell in a TableView. I was able to resolve the warnings but don't understand what caused them.
This was how I initially coded the select():
TablePosition<?, ?> previousPos;
//...
table.getSelectionModel().select
(previousPos.getRow(), previousPos.getTableColumn());
and I resolved the warnings by changing it to this.
table.getSelectionModel().select
(previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));
I didn't understand the difference so I had a look at the Java source code. If I'm interpreting it correctly, the select() method in TableView.java expects TableColumn<S, ?>. However, getTableColumn() in TablePosition.java returns TableColumn<S,T> while getColumns() in TableView.java returns an ObservableList of type TableColumn(S, ?).
I guess that's why table.getColumns().get(...) compiles clean and previousPos.getTableColumn() generates errors.
But what is the difference, then, between TableColumn<S, ?> and TableColumn<S,T> from the compiler's point of view? Why doesn't it resolve (is that the correct term?) the T to ?.
If it helps, here is the MVCE I was playing with to try and figure it out, but the answer is beyond my current Java knowledge. The select() is in moveToPreviousPos().
I'm using JavaFX8 (JDK1.8.0_181), NetBeans 8.2 and Scene Builder 8.3.
package test27;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Test27 extends Application {
TableView<TestModel> table = new TableView<>();
//Both of these stop the "unchecked conversion" error on line #51 (previousPos = table.getFocusModel().getFocusedCell();)
// TablePosition previousPos;
TablePosition<?, ?> previousPos;
//but using the following generates the "unchecked conversion" error
// TablePosition<TestModel, ?> previousPos;
private Parent createContent() {
ObservableList<TestModel> olTestModel = FXCollections.observableArrayList();
olTestModel.add(new TestModel("A"));
olTestModel.add(new TestModel("B"));
olTestModel.add(new TestModel("C"));
table.setItems(olTestModel);
TableColumn<TestModel, String> colText = new TableColumn<>("text");
colText.setCellValueFactory(cellData -> cellData.getValue().textProperty());
colText.setCellFactory(TextFieldTableCell.forTableColumn());
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
table.getColumns().add(colText);
Button btnGetTablePosition = new Button("get table position");
btnGetTablePosition.setOnAction(event -> {
//TableView.java: getFocusedCell returns TablePosition<S, ?>
previousPos = table.getFocusModel().getFocusedCell(); //Line #51
outputPreviousPos(previousPos);
});
Button btnMoveToPreviousPos = new Button("move to previous pos");
btnMoveToPreviousPos.setOnAction(event -> {
moveToPreviousPos(previousPos);
});
BorderPane content = new BorderPane(table);
HBox hb = new HBox();
hb.getChildren().addAll(btnGetTablePosition, btnMoveToPreviousPos);
content.setTop(hb);
return content;
}
public void outputPreviousPos(TablePosition previousPos){
System.out.println("previousPos = " + previousPos);
}
public void moveToPreviousPos(TablePosition previousPos) {
//select() in TableView.java expects TableColumn<S, ?>
//getTableColumn() in TablePosition.java returns TableColumn<S,T>
//getColumns() in TableView.java returns an ObservableList of type TableColumn(S, ?)
//Is that why the following line generates "unchecked method invocation" and "unchecked conversion" errors
//table.getSelectionModel().select
// (previousPos.getRow(), previousPos.getTableColumn());
//but the following line compiles clean?
table.getSelectionModel().select
(previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));
}
public class TestModel {
private StringProperty text;
public TestModel() {
this("");
}
public TestModel(
String text
) {
this.text = new SimpleStringProperty(text);
}
public String getText() {
return text.get();
}
public void setText(String text) {
this.text.set(text);
}
public StringProperty textProperty() {
return text;
}
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setTitle("Test");
stage.setWidth(500);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
First of all, I would say that it was a design flaw that TableView.getFocusModel().getFocusedCell() (or focusedCellProperty()) uses the raw TablePosition type (raw TablePosition can only be cast to TablePositon<?, ?> without generating warning). The more suitable version could have been TablePosition<S, ?>.
Since TablePosition represents a particular cell anywhere in the TableView, then for TableView.getFocusModel().focusedCellProperty():
The type of S is fixed for TableView<S> (i.e. the type is known).
The type of T refers to the type of a particular TableColumn, which can change depending on which cell has been focused. You cannot determine the type at compile time because you have no idea which TableColumn<S, T> would be selected.
Now to the second point.
But what is the difference, then, between TableColumn<S, ?> and
TableColumn<S,T> from the compiler's point of view? Why doesn't it
resolve (is that the correct term?) the T to ?.
This is because ? in TableColumn<S, ?> is a wildcard. Since TableViewFocusModel<S> does not have the type T and that it does not operate based on a fixed column, so it has to use ? here (see the first point that I explained).
On the other hand, TableView.getSelectionModel().select() expects an int for row and a TableColumn<S, ?> for column. Since you had TablePosition<?, ?> previousPos, so previousPos would return a TableColumn<?, ?> as well. TableColumn<S, ? and TableColumn<?, ?> are very different - you could use the TableColumn from another TableView if TableColumn<?, ?> is allowed.
Finally, if the API for TableView.getFocusModel().getFocusedCell() is fixed, then there would not be a problem when you use select(). Until then, you could manually cast it to TablePosition<TestModel, ?> with a suppression, or use TableView.getColumns().get(index) like what you did.
i trying to use jquery.AreYouSure into JxBrowser(5.2 and/or next version).
jquery.AreYouSure works... but the warning pop up windows is always in english...
This behaviour is wrong and differ from chrome/firox/ie.... these show message in the current language...
this is a demo url
http://www.papercut.com/products/free-software/are-you-sure/demo/are-you-sure-demo.html
By default, JxBrowser displays dialogs configured with English language. At the same time, JxBrowser API provides functionality that allows modifying default behavior and display your own dialogs with required language. To change the language you need to register your own DialogHandler where you can display your own dialog. For example:
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.CloseStatus;
import com.teamdev.jxbrowser.chromium.UnloadDialogParams;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import com.teamdev.jxbrowser.chromium.swing.DefaultDialogHandler;
import javax.swing.*;
import java.awt.*;
/**
* The sample demonstrates how to catch onbeforeunload dialog.
*/
public class BeforeUnloadSample {
public static void main(String[] args) {
Browser browser = new Browser();
final BrowserView view = new BrowserView(browser);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(700, 500);
frame.setVisible(true);
browser.setDialogHandler(new DefaultDialogHandler(view) {
#Override
public CloseStatus onBeforeUnload(UnloadDialogParams params) {
String title = "Confirm Navigation";
String message = params.getMessage();
int returnValue = JOptionPane.showConfirmDialog(view, message, title, JOptionPane.OK_CANCEL_OPTION);
if (returnValue == JOptionPane.OK_OPTION) {
return CloseStatus.OK;
} else {
return CloseStatus.CANCEL;
}
}
});
browser.loadHTML("<html><body onbeforeunload='return myFunction()'>" +
"<a href='http://www.google.com'>Click here to leave</a>" +
"<script>function myFunction() { return 'Leave this web page?'; }" +
"</script></body></html>");
}
}
In a JavaFX dialog, I would like to show a list of files with their icons and file names.
It was easy to find how to get an icon for a file extension:
File file = File.createTempFile("icon", ".doc");
FileSystemView view = FileSystemView.getFileSystemView();
java.swing.Icon icon = view.getSystemIcon(file);
file.delete();
But, how can I draw that Swing Icon in a JavaFX ListView?
private static class AttachmentListCell extends ListCell<String> {
#Override
public void updateItem(String fileName, boolean empty) {
if (item != null) {
// Get file Icon for fileName as shown above.
java.swing.Icon icon =
// Transform Icon to something that can be
// added to the box, maybe an ImageView.
javafx.scene.image.ImageView image = ???
// Label for file name
Label label = new Label(item);
HBox box = new HBox();
box.getChildren().addAll(image, label);
setGraphic(box);
}
}
}
Here is an example for a list view with file icons:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.swing.filechooser.FileSystemView;
public class ListViewCellFactory2 extends Application {
ListView<String> list = new ListView<String>();
ObservableList<String> data = FXCollections.observableArrayList(
"a.msg", "a1.msg", "b.txt", "c.pdf",
"d.html", "e.png", "f.zip",
"g.docx", "h.xlsx", "i.pptx");
#Override
public void start(Stage stage) {
VBox box = new VBox();
Scene scene = new Scene(box, 200, 200);
stage.setScene(scene);
stage.setTitle("ListViewSample");
box.getChildren().addAll(list);
VBox.setVgrow(list, Priority.ALWAYS);
list.setItems(data);
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
return new AttachmentListCell();
}
});
stage.show();
}
private static class AttachmentListCell extends ListCell<String> {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
Image fxImage = getFileIcon(item);
ImageView imageView = new ImageView(fxImage);
setGraphic(imageView);
setText(item);
}
}
}
public static void main(String[] args) {
launch(args);
}
static HashMap<String, Image> mapOfFileExtToSmallIcon = new HashMap<String, Image>();
private static String getFileExt(String fname) {
String ext = ".";
int p = fname.lastIndexOf('.');
if (p >= 0) {
ext = fname.substring(p);
}
return ext.toLowerCase();
}
private static javax.swing.Icon getJSwingIconFromFileSystem(File file) {
// Windows {
FileSystemView view = FileSystemView.getFileSystemView();
javax.swing.Icon icon = view.getSystemIcon(file);
// }
// OS X {
//final javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
//javax.swing.Icon icon = fc.getUI().getFileView(fc).getIcon(file);
// }
return icon;
}
private static Image getFileIcon(String fname) {
final String ext = getFileExt(fname);
Image fileIcon = mapOfFileExtToSmallIcon.get(ext);
if (fileIcon == null) {
javax.swing.Icon jswingIcon = null;
File file = new File(fname);
if (file.exists()) {
jswingIcon = getJSwingIconFromFileSystem(file);
}
else {
File tempFile = null;
try {
tempFile = File.createTempFile("icon", ext);
jswingIcon = getJSwingIconFromFileSystem(tempFile);
}
catch (IOException ignored) {
// Cannot create temporary file.
}
finally {
if (tempFile != null) tempFile.delete();
}
}
if (jswingIcon != null) {
fileIcon = jswingIconToImage(jswingIcon);
mapOfFileExtToSmallIcon.put(ext, fileIcon);
}
}
return fileIcon;
}
private static Image jswingIconToImage(javax.swing.Icon jswingIcon) {
BufferedImage bufferedImage = new BufferedImage(jswingIcon.getIconWidth(), jswingIcon.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
jswingIcon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);
return SwingFXUtils.toFXImage(bufferedImage, null);
}
}
EDIT: On a HDPI monitor, the file icons are clipped.
What has to be done to have the icons entirely displayed in the row?
How can I retrieve the scale factor from Java?
I came up with this code, which seems to work for converting the icon returned by getSystemIcon to a format which JavaFX can understand. It does this by using a combo of SwingUtilities.invokeLater with Platform.runLater to try to mitigate any potential threading issues between the two projects. The javax.swing.Icon is painted to java.awt.BufferedImage which is converted by SwingFXUtils to a JavaFX Image.
So the Swing Icon => JavaFX image portion of the code you were asking about seems to work. The only thing is, when I tested the application on OS X 10.7 running Oracle Java8u20, every file extension type I tried gave the exact same icon. So it would seem that your method for getting an icon from the system via the swing FileSystemView isn't really supported on OS X (as far as I can tell). I guess you could try it on another OS and see if it works for you there (presuming that supporting this icon lookup feature on OS X is not necessary for your task).
So googling around brought up the following question:
Access file type icons Mac OSX
And in that, Sam Barnum recommends a FileView works much better than a FileSystemView - and so it did for me. I switched your code to use a FileView and after that started getting different icons for different file types on OS X. The icons were still really small 16x16 icons (I wouldn't know how to retrieve the hi-res retina icons for instance), but at least the icons which were retrieved appeared correct and file type specific.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class FileIconViewer extends Application {
#Override
public void start(Stage stage) throws IOException {
Runnable fetchIcon = () -> {
File file = null;
try {
file = File.createTempFile("icon", ".png");
// commented code always returns the same icon on OS X...
// FileSystemView view = FileSystemView.getFileSystemView();
// javax.swing.Icon icon = view.getSystemIcon(file);
// following code returns different icons for different types on OS X...
final javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
javax.swing.Icon icon = fc.getUI().getFileView(fc).getIcon(file);
BufferedImage bufferedImage = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_ARGB
);
icon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);
Platform.runLater(() -> {
Image fxImage = SwingFXUtils.toFXImage(
bufferedImage, null
);
ImageView imageView = new ImageView(fxImage);
stage.setScene(
new Scene(
new StackPane(imageView),
200, 200
)
);
stage.show();
});
} catch (IOException e) {
e.printStackTrace();
Platform.exit();
} finally {
if (file != null) {
file.delete();
}
}
};
javax.swing.SwingUtilities.invokeLater(fetchIcon);
}
public static void main(String[] args) { launch(args); }
}
Note: there is an existing request in the JavaFX issue tracker to add this functionality to JavaFX (it is currently not scheduled for implementation, though you could log into the issue tracker and vote for the issue, comment on it, link it back to this StackOverflow question, etc):
RT-19583 Possibility to get native icons, on different sizes.
A couple of weeks ago, i used NetBeans to create one of it's javafx examples
The webview project, and it worked fine.
I am especially interested in using javafx to play youtube videos
in a swinginterop application.
This is part of a bigger project, so i used the SwingInterop example from NetBeans to load the players on a JFrame
I need to load more than one YouTube Video.
And again everything worked great.
I am using Windows XP, NetBeans 7.2, Java 1.7 9
These days i tried the application again but this time on youtube i see
"This Video is currently unavailable".
The first thing that came into my mind was that maybe
i don't have the latest FlashPlayer ...
Needless to say i downloaded everything...
The application just won't play youtube videos anymore
I even reinstalled java and netbeans again but nothing changed.
I also mention that on Firefox, which is the browser i have on my pc
youtube works just fine.
It is pretty annoying to know that ... something was ok and maybe ...
i found a way to mess things in there ...
So right now, i can see web pages in javafx webview but youtube videos are still not playing...
The last time i asked for help i did not put the code ... sorry about that.
So i made another small project with only two classes in it to show what i did
I did not test this on another pc because, if it happened once
chances are it will happen again and since things don't fix themselves
i want to be able to answer this question when it will pop up.
Thank you jewelsea and Gregory for the interest
here is the code :
the frame on which the players are loaded
package stackoverflow;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
public class PlayersFrame extends JFrame
{
public PlayersFrame()
{
// initialize jframe
setLayout(null);
setTitle(" YouTube on JFrame");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CreatePlayersList();
}
// all the players have the same size
Dimension PlayerSize = new Dimension(300, 230);
private void CreatePlayersList()
{
/*
* create an instance of playerclass
* containing the location and the youtube embedded address
* for each of the four players
*/
Point NewPlayerLocation = null;
PlayerClass NewPlayer = null;
NewPlayerLocation = new Point(10, 10);
NewPlayer = new PlayerClass(NewPlayerLocation, PlayerSize, "http://www.youtube.com/embed/SvcDwPlaWgw?rel=0");
// add player1 class to the players list
Players.add(NewPlayer);
NewPlayerLocation = new Point(320, 10);
NewPlayer = new PlayerClass(NewPlayerLocation, PlayerSize, "http://www.youtube.com/embed/L0huXvTeVvU?rel=0");
// add player2 class to the players list
Players.add(NewPlayer);
NewPlayerLocation = new Point(10, 240);
NewPlayer = new PlayerClass(NewPlayerLocation, PlayerSize, "http://www.youtube.com/embed/rHcnsEoSK_c?rel=0");
// add player3 class to the players list
Players.add(NewPlayer);
NewPlayerLocation = new Point(320, 240);
NewPlayer = new PlayerClass(NewPlayerLocation, PlayerSize, "http://www.youtube.com/embed/vaXuK-RsT6E?rel=0");
// add player4 class to the players list
Players.add(NewPlayer);
// stand by
LoadPlayers();
}
// list of players data
List<PlayerClass> Players = new ArrayList<>();
/*
* a class to hold data about a player
*/
public class PlayerClass
{
public PlayerClass(Point playerLocation, Dimension playerSize, String youTubeAddress)
{
PlayerLocation = playerLocation;
PlayerSize = playerSize;
YouTubeAddress = youTubeAddress;
}
public Point PlayerLocation = null;
public Dimension PlayerSize = null;
public String YouTubeAddress = null;
}
/*
* in this swinginterop project i want to display youtube videos on a jframe
* with webview i get more that i ask for
* webview will display an entire web page
* so a web page is created on the fly containing a frame for the player
*/
private String GeneratePlayerPage(Dimension PlayerSize, String EmbeddedAddress)
{
String GeneratedPage = null;
GeneratedPage = "<html>\n";
GeneratedPage += "<body>\n";
GeneratedPage += "<iframe\n";
GeneratedPage += "style=\"position:absolute;\n";
GeneratedPage += "left:0px;top:0px;" +
"width:" + String.valueOf(PlayerSize.width) +
"px;height:" + String.valueOf(PlayerSize.height) + "px;\"\n";
GeneratedPage += "src=\"" + EmbeddedAddress + "\"" + "\n";
GeneratedPage += "frameborder=\"0\" allowfullscreen>\n";
GeneratedPage += "</iframe>\n";
GeneratedPage += "</body>\n";
GeneratedPage += "</html>";
return(GeneratedPage);
}
/*
* why synchronized ? ...
*
* each javafx object runs on it's own thread
* this means that, sooner or later
* you will have to deal with crossthreading issues
*
* in this project it does not throw an error
* but since the playersform will add controls on a locked procedure,
* and i don't use a single player on the jframe,
* some of the players will not appear on the frame.
*
* if only one player is loaded on the jframe
* then all this is not necessary.
*
* i don't know if the players are there but are not rendered
* or the players were just not loaded
*
* with this synchronized void a callback from the javafx object is handled
*/
public synchronized void OkPlayer()
{
try
{
/*
* a player was loaded
* delay before the next player
*/
Thread.sleep(10);
}
catch(Exception Ex)
{}
/*
* if the players list is empty than all the players have been loaded
* but you also get an error, so check the size ...
*/
if(Players.size() > 0)
{
LoadPlayers();
}
}
void LoadPlayers()
{
/*
* get the data from the first playerclass in the players list
* and create a new player
*/
PlayerClass TempPlayer = Players.get(0);
Dimension playerSize = TempPlayer.PlayerSize;
YouTubePlayer player = new YouTubePlayer(this, playerSize,
GeneratePlayerPage(playerSize, TempPlayer.YouTubeAddress));
add(player);
player.setLocation(TempPlayer.PlayerLocation);
player.setSize(TempPlayer.PlayerSize);
player.setVisible(true);
// remove the used playerclass from the players list
Players.remove(0);
}
}
and the player
package stackoverflow;
import java.awt.Dimension;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UnsupportedLookAndFeelException;
public final class YouTubePlayer extends JPanel
{
public YouTubePlayer(PlayersFrame playersFrame, Dimension PlayerSize, String YouTubeAddress)
{
remote = playersFrame;
init(PlayerSize, YouTubeAddress);
}
private static JFXPanel browserFxPanel;
private Pane browser;
public void init(Dimension playerSize, String youTubeAddress)
{
final Dimension PlayerSize = playerSize;
final String YouTubeAddress = youTubeAddress;
browserFxPanel = new JFXPanel();
browserFxPanel.setPreferredSize(new Dimension(PlayerSize.width, PlayerSize.height));
add(browserFxPanel);
Platform.runLater(new Runnable()
{
public void run()
{
// inside the player's thread
createScene(PlayerSize, YouTubeAddress);
}
});
}
/*
* the program will start on the javafx thread
* the main void is placed in the javafx component
*
* maybe there are other ways to launch the program
* but for this one it is good enough ... for now
*/
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
// set windows look and feel
if ("Windows".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException Ex)//ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex)
{}
// create an instance of playersframe
PlayersFrame LoadPlayers = new PlayersFrame();
LoadPlayers.setSize(new Dimension(640, 520));
// make it visible
LoadPlayers.setVisible(true);
}
});
}
PlayersFrame remote = null;
private void createScene(Dimension PlayerSize, String YouTubeAddress)
{
browser = createBrowser(PlayerSize, YouTubeAddress);
browserFxPanel.setScene(new Scene(browser));
/*
* player loaded
* let playersform know that it can proceed
* with the next player, if there still is one
*/
remote.OkPlayer();
}
private Pane createBrowser(Dimension PlayerSize, String YouTubeAddress)
{
WebView view = new WebView();
view.setPrefSize(PlayerSize.width, PlayerSize.height);
final WebEngine eng = view.getEngine();
eng.loadContent(YouTubeAddress);
GridPane grid = new GridPane();
grid.getChildren().addAll(view);
return grid;
}
}
this is what it looks like
http://i.stack.imgur.com/UvhcJ.jpg
and this is the 'thing'
http://i.stack.imgur.com/lB4uY.jpg
the last player acts the same as the others
If i use the example from NetBeans and just paste a YouTube link
i get the same result
I really need to know what is happening
Thank you
Check out the system requirements:
http://docs.oracle.com/javafx/2/system_requirements_2-2/jfxpub-system_requirements_2-2.htm
For Windows XP and Windows Vista, JavaFX Media 2.2 requires that one of the following external modules be installed to play AAC audio and H.264/AVC video:
MainConcept H.264/AVC Pro Decoder Pack
DivX Plus Codec Pack
MainConcept Showcase (includes demo version codecs)
DivX is freely downloadable: http://www.divx.com/
Reference: https://forums.oracle.com/thread/2467376