Write JavaFX Blob data field image - javafx

In my class, the attribute where the image will be saved is defined like this:
#Lob
#Column(name = "NOTA_FISCAL", nullable = false, columnDefinition = "mediumblob")
public byte[] getNOTA_FISCAL() {
return NOTA_FISCAL;
}
public void setNOTA_FISCAL(byte[] NOTA_FISCAL) {
this.NOTA_FISCAL = NOTA_FISCAL;
}
In a project I made using Swing, I used JFileChooser to read an image from my computer to later insert it into the database, we can see that the file is converted to Bytes before inserting the item.
private void selecionarNF(ActionEvent event) {
JFileChooser fc = new JFileChooser();
int res = fc.showOpenDialog(null);
if (res == JFileChooser.APPROVE_OPTION) {
File arquivo = fc.getSelectedFile();
System.out.println("Arquivo: " + arquivo + "");
textCaminhoNF.setText(String.valueOf(arquivo));
try {
byte[] fotonf = new byte[(int) arquivo.length()];
FileInputStream fileInputfotonf = new FileInputStream(arquivo);
fileInputfotonf.read(fotonf);
fileInputfotonf.close();
fotoNF = fotonf;
} catch (Exception ex) {
// System.out.println(ex.printStackTrace().toString());
}
} else {
JOptionPane.showMessageDialog(null, "Você nao selecionou nenhum arquivo.");
}
I'm implementing it with JavaFX, I could even continue using Swing, but I intend to use the Windows file explorer, this way using FileChooser, however I'm having problems capturing the image and passing it to an object of type File, the . getSelectedFile() doesn't exist for FileChooser, I searched a lot on the internet and couldn't find a way to capture this file. What would be the correct way?
Stage s = new Stage();
FileChooser fc = new FileChooser();
textCaminhoNF.setText(fc.showOpenDialog(s).getAbsolutePath());
File arquivo = fc.getSelectedFile(); //his line shows the error, because there is no .getSelectItem
if (fc != null) {
System.out.println("No is null");
try
{
byte[] fotonf = new byte[(int) fc.length()];
FileInputStream fileInputfotonf = new FileInputStream(fc);
fileInputfotonf.read(fotonf);
fileInputfotonf.close();
fotoNF = fotonf;
} catch (Exception ex) {
// System.out.println(ex.printStackTrace().toString());
}
}

I agree with what #slaw has mentioned. You are not saving the file reference returned from showOpenDialog.
Below is a quick demo [from my archives ;-) ] when I tried to check the behavior of FileChooser:
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ChooseImage_Demo extends Application {
ImageView myImageView;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button button = new Button("Search for Image");
button.setOnAction(e -> {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
try {
BufferedImage bufferedImage = ImageIO.read(file);
Image image = SwingFXUtils.toFXImage(bufferedImage, null);
myImageView.setImage(image);
} catch (IOException ex) {
ex.printStackTrace();
}
});
myImageView = new ImageView();
myImageView.setFitWidth(500);
myImageView.setPreserveRatio(true);
VBox vBox = new VBox(10);
vBox.getChildren().addAll(button, myImageView);
vBox.setAlignment(Pos.TOP_CENTER);
Scene scene = new Scene(vBox, 800, 800);
primaryStage.setTitle("Image Chooser");
primaryStage.setScene(scene);
primaryStage.show();
}
}

Thanks for the help, I did it this way and it worked, it's writing correctly to the database too.
#FXML
private void selecionarNF(ActionEvent event) {
ImageView myImageView = null;
myImageView = new ImageView();
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
try {
BufferedImage bufferedImage = ImageIO.read(file);
Image image = SwingFXUtils.toFXImage(bufferedImage, null);
myImageView.setImage(image);
imageToByte(String.valueOf(file));
} catch (IOException ex) {
ex.printStackTrace();
}
textCaminhoNF.setText(String.valueOf(file));
}

Related

Restarting and pausing and resuming clip hangs the gui of music player, while pressing pause and play resumes playing from stopping point

This program is a music player that allows user to pick a .wav file, play, pause, resume, and restart a the music file from a clip object and audioinput stream. The audio input stream loads a file that is determined by user via FileChooser. The program can play, pause, and resume by selecting a file, pressing play, pause, then play again, but does not play using the restart method or the resume method invoked via the respective buttons. Instead, the program hangs until the X button is clicked. I think it has something to do with the resetaudiostream method, but I am unsure what. Maybe something to do with ending the old clip and creating a new clip instance. Please review the logic and let me know what is making it hang and how that could be remedied.
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class Main extends Application {
static File musicfile;
static Long currentFrame;
static Clip clip;
static String status = "play";
static AudioInputStream audioInputStream;
static String filePath;
public void SimpleAudioPlayer()
throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
// create AudioInputStream object
audioInputStream =
AudioSystem.getAudioInputStream(new File(filePath).getAbsoluteFile());
// create clip reference
clip = AudioSystem.getClip();
// open audioInputStream to the clip
clip.open(audioInputStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Music Player");
GridPane gp = new GridPane();
Button selectFile = new Button("Select File");
GridPane.setConstraints(selectFile, 0,0);
selectFile.setOnAction(event->{
FileChooser filechooser = new FileChooser();
// create AudioInputStream object
try {
musicfile = filechooser.showOpenDialog(null);
audioInputStream = AudioSystem.getAudioInputStream(musicfile);
clip = AudioSystem.getClip();
// open audioInputStream to the clip
clip.open(audioInputStream);
}catch(IOException | UnsupportedAudioFileException | LineUnavailableException e){
e.printStackTrace();
}
});
Button play = new Button("Play");
GridPane.setConstraints(play, 1,0);
play.setOnAction(event->{
if(status == "play") {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
play();
});
Button pause = new Button("Pause");
GridPane.setConstraints(pause, 2,0);
pause.setOnAction(event -> pause());
Button restart = new Button("Restart");
GridPane.setConstraints(restart, 0,1);
restart.setOnAction(event -> {
try{
restart();
}
catch(IOException | UnsupportedAudioFileException | LineUnavailableException e){
e.printStackTrace();}
});
Button resume = new Button("Resume");
GridPane.setConstraints(resume, 1,1);
resume.setOnAction(event -> {
try {
resumeAudio();
}catch(IOException | LineUnavailableException | UnsupportedAudioFileException e){
e.printStackTrace();
}
});
gp.getChildren().addAll(play,selectFile, pause, restart, resume);
primaryStage.setScene(new Scene(gp, 300, 275));
primaryStage.show();
}
public void play()
{
//start the clip
clip.start();
status = "play";
}
// Method to pause the audio
public void pause()
{
if (status.equals("paused"))
{
System.out.println("audio is already paused");
return;
}
currentFrame =
clip.getMicrosecondPosition();
clip.stop();
status = "paused";
}
// Method to resume the audio
public void resumeAudio() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
if (status.equals("play"))
{
System.out.println("Audio is already "+
"being played");
return;
}
clip.close();
resetAudioStream();
clip.setMicrosecondPosition(currentFrame);
status = "play";
play();
}
// Method to restart the audio
public void restart() throws IOException, LineUnavailableException,
UnsupportedAudioFileException
{
clip.stop();
clip.close();
resetAudioStream();
currentFrame = 0L;
clip.setMicrosecondPosition(0);
status = "play";
play();
}
// Method to stop the audio
public void stop() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
currentFrame = 0L;
clip.stop();
clip.close();
}
// Method to jump over a specific part
public void jump(long c) throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
if (c > 0 && c < clip.getMicrosecondLength())
{
clip.stop();
clip.close();
resetAudioStream();
currentFrame = c;
clip.setMicrosecondPosition(c);
this.play();
}
}
// Method to reset audio stream
public void resetAudioStream() throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
audioInputStream = AudioSystem.getAudioInputStream(musicfile);
clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public static void main(String[] args) {
launch(args);
}
}
It is quiet simple to get the required functionality with a MediaPlayer:
import java.net.URI;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.stage.Stage;
import javafx.util.Duration;
/*
* If you get "cannot access class com.sun.glass.utils.NativeLibLoader" exception you may need to
* add a VM argument: --add-modules javafx.controls,javafx.media as explained here:
* https://stackoverflow.com/questions/53237287/module-error-when-running-javafx-media-application
*/
public class Main extends Application {
private MediaPlayer player;
private static final long JUMP_BY = 5000;//millis
#Override
public void start(Stage primaryStage) throws Exception{
URI uri = new URI("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3");
Media media = new Media(uri.toString());
//OR Media media = new Media("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3");
player = new MediaPlayer(media);
player.setOnError(() -> System.out.println(media.getError().toString()));
GridPane gp = new GridPane();
gp.setHgap(10);
Button play = new Button("Play");
GridPane.setConstraints(play, 0,0);
play.setOnAction(event-> playAudio());
Button pause = new Button("Pause");
GridPane.setConstraints(pause, 1,0);
pause.setOnAction(event -> pauseAudio());
Button resume = new Button("Resume");
GridPane.setConstraints(resume, 2,0);
resume.setOnAction(event -> resumeAudio());
Button stop = new Button("Stop");
GridPane.setConstraints(stop, 3,0);
stop.setOnAction(event -> stopAudio());
Button restart = new Button("Restart");
GridPane.setConstraints(restart, 4,0);
restart.setOnAction(event -> restartAudio());
Button jump = new Button("Jump >");
GridPane.setConstraints(jump, 5,0);
jump.setOnAction(event -> jump(JUMP_BY));
Label time = new Label();
GridPane.setConstraints(time, 6,0);
time.textProperty().bind( player.currentTimeProperty().asString("%.4s") );
gp.getChildren().addAll(play, pause, resume, stop, restart, jump, time);
primaryStage.setScene(new Scene(gp, 400, 45));
primaryStage.show();
}
//play audio
public void playAudio()
{
player.play();
}
//pause audio
public void pauseAudio()
{
if (player.getStatus().equals(Status.PAUSED))
{
System.out.println("audio is already paused");
return;
}
player.pause();
}
//resume audio
public void resumeAudio()
{
if (player.getStatus().equals(Status.PLAYING))
{
System.out.println("Audio is already playing");
return;
}
playAudio();
}
//restart audio
public void restartAudio()
{
player.seek(Duration.ZERO);
playAudio();
}
// stop audio
public void stopAudio()
{
player.stop();
}
//jump by c millis
public void jump(long c)
{
player.seek(player.getCurrentTime().add(Duration.millis(c)));
}
public static void main(String[] args) {
launch(args);
}
}

How can i convert a JAVAFX Webvie to Parsing JSOUP?

I want to convert a Webseite loaded by javaFX to JSOUP.
p
ublic class database {
public static ArrayList<String> database = new ArrayList<String>();
public static ArrayList<Integer> laenge = new ArrayList<Integer>();
public static ArrayList<Integer> tiefe = new ArrayList<Integer>();
public static void main(String[] args) throws IOException, JSONException {
// TODO Auto-generated method stub
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
String url = "http://www.google.com";
webEngine.load(url);
//get w3c document from webEngine
org.w3c.dom.Document w3cDocument = webEngine.getDocument();
// use jsoup helper methods to convert it to string
String htm = new org.jsoup.helper.W3CDom().asString(webEngine.getDocument());
// create jsoup document by parsing html
Document doc = Jsoup.parse(url, htm);
//Document doc = Jsoup.connect("http://ttp-schreiber.de/Mathematik/index2.html").get();
Element title = doc.body();
/*WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.load("http://ttp-schreiber.de/Mathematik/index2.html");
*/
Elements html = doc.select("html");
Controller(html);
// System.out.println("+--+"+deeper(next(html,html.last()))[0][0]);
databasesafe();
}
I get these Error Message:
Exception in thread "main" java.lang.ExceptionInInitializerError
How is the misttage?
ETC I have the example from here:
How to parse html from javafx webview and transfer this data to Jsoup Document?
In these line ist .get wrong: String html = new org.jsoup.helper.W3CDom().asString(webEngine.get);
This duplicate is probably your best bet. After a page is loaded in WebView, use a Transformer to get its HTML. Then use that HTML string in Jsoup. I am not sure if you will get your expected outcome.
import java.io.File;
import java.nio.file.Files;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.jsoup.Jsoup;
import org.w3c.dom.Document;
//import org.jsoup.nodes.Document;
public class App extends Application
{
org.jsoup.nodes.Document jsoupDocument;
#Override
public void start(Stage stage)
{
String url = "http://www.google.com";
WebView webview = new WebView();
final WebEngine webengine = webview.getEngine();
webengine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) ->
{
if (newState == Worker.State.SUCCEEDED) {
Document doc = webengine.getDocument();
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
File file = new File("results.txt");
file.createNewFile();
StreamResult results = new StreamResult(file);
transformer.transform(new DOMSource(doc), results);
String fileContent = Files.readString(file.toPath());
jsoupDocument = Jsoup.parse(fileContent);
System.out.println(jsoupDocument.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
webengine.load("http://stackoverflow.com");
StackPane root = new StackPane(webview);
stage.setTitle("Hello Drag And Drop");
Scene scene = new Scene(root, 400, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}

I can't make jar file that is using RXTX

I made the following source code and succeed in communicating via RS232.
Then, I attempted to make jar file the source code.I can make the runnable jar file. But it couldn't execute the program when I execute double click in another PC(In case that I used my PC, The jar file executes properly.).
What should I do to resolve the problem.
I read some involved question, but I do't know what I should do.
So, please let me know the detail procedure how to make jar file.
[I have made jar file of other program before but then it didn't include external jar file. In this time, I used a jar file(RxTxcomm.jar) and two dll file to make the program . so I don't know the way of linking one another.]
My source code
[MyRxTx.java]
package sample;
import javafx.application.Platform;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
public class MyRxTx implements SerialPortEventListener {
SerialPort serialPort;
Main sample_serial;
public byte[] SendBuffer;
/**
* The port we're normally going to use.
*/
private final String PORT_NAMES[] = {
"COM29",
"COM30",
"COM31",
};
private InputStream inputStream;
private OutputStream outputStream;
private static final int TIME_OUT = 2000;
private static final int Baud_Rate = 115200;
public void initialize() throws InterruptedException {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId
= (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
} else {
System.out.println("Port Name: " + portId.getName() + "\n"
+ "Current Owner: " + portId.getCurrentOwner() + "\n"
+ "Port Type: " + portId.getPortType());
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(
Baud_Rate,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
SendBuffer=new byte[]{(byte)0x41,(byte)0x54};
write(SendBuffer);
}
#Override
public void serialEvent(SerialPortEvent Serial_event){
int received_data = 0;
StringBuffer buffer = new StringBuffer();
if(Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE){
while(true){
try{
received_data = inputStream.read();
if(received_data == -1) break;
if((char)received_data != '\r'){
buffer.append((char)received_data);
}
else{
buffer.append('\n');
break;
}
}
catch(IOException ex){}
}//while()文ここまで。
System.out.println("Receive Data:"+buffer);
Platform.runLater( () ->{
sample_serial.label_receive.setText("Receive Data:"+buffer);
});
}
}
protected void write(byte[] buffer) throws InterruptedException{
try {
outputStream.write(buffer);
outputStream.flush();
} catch (IOException e) {
System.err.println("Cannot write:" + e.getMessage());
}
}
/**
* This should be called when you stop using the port. This will prevent
* port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
}
[Main.java]
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBox;
import javafx.scene.layout.VBoxBuilder;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.stage.Stage;
import javafx.stage.StageBuilder;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main extends Application {
MyRxTx myRxTx;
private TextField text_Send;
public static Label label_receive;
#Override
public void start(Stage primaryStage) throws InterruptedException {
Button btn_send = ButtonBuilder.create().text("Send")
.prefWidth(100).alignment(Pos.CENTER)
.id("Send").build();
text_Send = TextFieldBuilder.create().text("Sending message").alignment(Pos.CENTER)
.prefWidth(150).build();
Font Font_receive = Font.font("Arial", FontPosture.REGULAR,20);
label_receive = LabelBuilder.create().text("Recieved message")
.alignment(Pos.TOP_CENTER).prefWidth(400).font(Font_receive).build();
HBox root1 = HBoxBuilder.create().spacing(100).children(text_Send,btn_send).build();
HBox root2 = HBoxBuilder.create().spacing(100).children(label_receive).build();
VBox root3 = VBoxBuilder.create().spacing(15).children(root1,root2).build();
Scene scene = new Scene(root3);
myRxTx = new MyRxTx();
myRxTx.initialize();
scene.addEventHandler(ActionEvent.ACTION,actionHandler);
primaryStage = StageBuilder.create().width(410).height(340).scene(scene).title("Serial Communication Test Tool").build();
primaryStage.show();
}
EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>(){
public void handle (ActionEvent e){
Button src =(Button)e.getTarget();
String text = src.getId();
System.out.println("Select Button:"+text);
String text_send = text_Send.getText();
if(text.equals("Send")){
try {
myRxTx.write(text_send.getBytes());
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
/* main*/
public static void main(String[] args) {
launch(args);
}
}

JavaFX file listview with icon and file name

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.

Java "Could Not Serialize the Data"

I'm trying to get my clipboard to receive some custom data in a drag and drop. The custom data is another java type. This other type does implement serializable, so I'm really not sure why this isn't working. Any ideas are appreciated!
imgView.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
ClipboardContent content = new ClipboardContent();
content.put(dataFormat, RHSIconizedToken.this);
Dragboard db = imgView.startDragAndDrop(TransferMode.ANY);
db.setContent(content);
event.consume();
}
});
To retrieve this object later I'm using:
RHSIconizedToken replacementRHSiToken = (RHSIconizedToken) db.getContent(RHSIconizedToken.getDataFormat());
I'm getting the following error, but the RHSIconizedToken does implement Serializable
java.lang.IllegalArgumentException: Could not serialize the data
GetDataFormat returns the DataFormat Object that is used in the put argument in the first code example.
That's because your object is not serializable.
Indeed, it's not because it implements Serializable that it is Serializable.
Look deeper inside the exception, you might find something like this
Caused by: java.io.NotSerializableException: javafx.beans.property.SimpleObjectProperty
Maybe making some fields transient will help.
If your drag object isn't serializable, save it in a global variable during the drag. Here's a JavaFx (Java8 with lambdas) example with draggable tabs that go bewteen panes within the same JVM.
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class DraggingTabPane extends Application {
private static final DataFormat TAB_TYPE = new DataFormat("nonserializableObject/tab");
private static Tab dndTab;// global for drag-n-drop of non-serializable type
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TabPane tabPane1 = createDndTabPane();
TabPane tabPane2 = createDndTabPane();
VBox root = new VBox(10);
root.getChildren().addAll(tabPane1, tabPane2);
final Random rng = new Random();
for (int i=1; i<=8; i++) {
final Tab tab = createDraggableTab("Tab "+i);
final StackPane pane = new StackPane();
int red = rng.nextInt(256);
int green = rng.nextInt(256);
int blue = rng.nextInt(256);
String style = String.format("-fx-background-color: rgb(%d, %d, %d);", red, green, blue);
pane.setStyle(style);
final Label label = new Label("This is tab "+i);
label.setStyle(String.format("-fx-text-fill: rgb(%d, %d, %d);", 256-red, 256-green, 256-blue));
pane.getChildren().add(label);
pane.setMinWidth(600);
pane.setMinHeight(250);
tab.setContent(pane);
if (i<=4) {
tabPane1.getTabs().add(tab);
} else {
tabPane2.getTabs().add(tab);
}
}
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
public TabPane createDndTabPane() {
final TabPane tabPane = new TabPane();
tabPane.setOnDragOver(event -> {
if (event.getDragboard().hasContent(TAB_TYPE)
&& dndTab.getTabPane() != tabPane) {// && different from source location
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
});
tabPane.setOnDragDropped(event -> {
if (event.getDragboard().hasContent(TAB_TYPE)
&& dndTab.getTabPane() != tabPane) {// && different from source location
dndTab.getTabPane().getTabs().remove(dndTab);
tabPane.getTabs().add(dndTab);
event.setDropCompleted(true);
event.consume();
}
});
return tabPane;
}
private Tab createDraggableTab(String text) {
final Tab tab = new Tab();
final Label label = new Label(text);
tab.setGraphic(label);
label.setOnDragDetected(event -> {
Dragboard dragboard = label.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.put(TAB_TYPE, 1);
dndTab = tab;
dragboard.setContent(clipboardContent);
event.consume();
});
return tab ;
}
}

Resources