I have a Swing application, and inside my JFrame there are 2 JFXPanels, containing 2 JavaFx Nodes, a TableView and a WebView. The table contains a list of urls (think of it like a bookmarks list). I want the user to drag a url from the table on the left to the webview on the right. I set up drag-and-drop events according to the JavaFx tutorial and answers to previous drag-and-drop questions here. However, the 2 JFXPanels seem to not be able to communicate with each other.
I can drag URLs from the table to outside of my application (e.g. my web browser) and that works OK.
I can also drop URLs from the outside (e.g. copied from by web browser's address bar) to the web view and it loads them correctly too.
But when I drag URLs from the table, and try to drop them on the WebView, I always get an empty dragboard on the target side (I tried using both the String and the Url data formats, but both come back as null, also the event.getGestureSource() comes back as null), eventhough the source fills it correctly (watched it step-by-step with the debugger).
Could this be a side-effect of the fact that this is between 2 JFXPanels, and there is Swing in between which handles drag-and-drop using a different API? By the way, I do not have any other drag-and-drop code in the remaining Swing part of the application, so not mixing the two event models.
Thanks in advance for any pointers, tips or ideas.
Sample code snippets of my event handlers below:
(using JavaFx2.2, Jdk 1.7.0_40, on Windows 7 64 bit machine)
/* on the source side, the TableView */
// initiate drag
table.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
/* Put the selected file or url on the dragboard */
MyObject tableItem = table.getSelectionModel().getSelectedItem();
String item = tableItem.getUrlString();
if (item != null)
{
Dragboard db = table.startDragAndDrop(TransferMode.COPY);
ClipboardContent content = new ClipboardContent();
content.putString(item);
content.putUrl(item);
db.setContent(content);
}
event.consume();
}
});
table.setOnDragDone(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event)
{
event.consume();
}
});
/* on the target side, the WebView */
webView.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if (event.getGestureSource() != webView && (db.hasUrl() || db.hasString())) {
event.acceptTransferModes(TransferMode.ANY);
} else {
event.consume();
}
}
});
// handle drop
webView.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
String urlDropped = db.getUrl();
if (urlDropped == null)
urlDropped = db.getString();
if (urlDropped != null)
{
webView.getEngine().load(urlDropped);
}
event.setDropCompleted(success);
event.consume();
}
});
Related
I use Vaadin version 8.9.3. I need to show a modal window when I click a button. In this window, the user enters the information, clicks on the button, the information is saved and displayed in a table in the main window.
Main page:
Modal page:
To display the modal window I use BrowserWindowOpener. In order not to overload the question, I will give only a small piece of code. The FormLayout in which there is TextField("uid"), Grid and Button("Создать") - DeviceForm:
private BrowserWindowOpener opener = new BrowserWindowOpener(ButtlonClickUI.class);
private DeviceConfigsService configsService = DeviceConfigsService.getInstance();
private Grid<DeviceConfigs> grid = new Grid<>(DeviceConfigs.class);
public DeviceForm(MyUI myUI, Devices device) {
opener.extend(button);
opener.setFeatures("resizable");
configsService.setDevice(device);
configsService.addSaveEventListener(new OnSaveEventListener() {
#Override
public void SaveEvent() {
updateList();
}
});
grid.setColumns(NAME_COLUMN, VERSION_COLUMN, STATE_COLUMN);
grid.getColumn(NAME_COLUMN).setCaption(NAME_COLUMN_NAME).setExpandRatio(1);
grid.getColumn(STATE_COLUMN).setCaption(STATE_COLUMN_NAME).setExpandRatio(1);
grid.getColumn(VERSION_COLUMN).setCaption(VERSION_COLUMN_NAME).setExpandRatio(1);
updateList();
}
public void updateList() {
List<DeviceConfigs> configs = configsService.findAll();
if(configs.size() == 0) {
delete.setVisible(false);
}
grid.setItems(configs);
}
Here, config service is a service that allows you to save, delete and find the information displayed in the grid (DeviceConfigs), in this case, it does not matter which one. OnSaveEventListener is the listener I created, called when the save method in configsService is called:
public synchronized void save(DeviceConfigs entry) {
if(entry == null) {
LOGGER.log(Level.SEVERE,
"DeviceConfigs is null");
return;
}
if(entry.getName() == null || entry.getName().isEmpty()) {
LOGGER.log(Level.SEVERE,
"DeviceConfigs name is null");
}
try {
entry = (DeviceConfigs) entry.clone();
} catch (Exception e) {
throw new RuntimeException(e);
}
device.putConfig(entry);
if(listener != null) { listener.SaveEvent(); }
}
UI that is called in opener:
public class ButtlonClickUI extends UI {
private DeviceConfigsService configsService = DeviceConfigsService.getInstance();
private Button close = new Button("close", VaadinIcons.CLOSE);
#Override
protected void init(VaadinRequest request) {
VerticalLayout layout = new VerticalLayout();
layout.addComponent(close);
...
close.addClickListener(event ->{
configsService.save(new DeviceConfigs(requestStr.getValue(), true, typeOfClick.getValue()));
closeThis();
});
}
private void closeThis() {
JavaScript.eval("close()");
// Detach the UI from the session
getUI().close();
}
}
The problem is this - I couldn't think of a better way to track the event of writing new data and closing the modal window to update the values of the table until I got to creating a listener.
But now, after clicking the Close button in the modal window, it closes, the data is updated but not displayed until I interact with some element on the main page (by trial and error, I got to the point where the components on the main page will not update their visibility until the modal window closes and the main page returns focus).
But I can't think of any way to automatically update the table values in the main menu when the modal window is closed.
Any possible solution to the problem, please.
I´ve created a TreeView with a ContentProvider and custom tree elements.
I also have a ISelectionChangedListener added to the TreeView.
I want to add an MouseListener, do detect if an element of the tree is right-clicked and show a popup menu.
If the white area around the tree is clicked, i don´t want to display the popup menu.
The menu is added via Extensions in the plugin.xml.
How can I now evaluate if a tree element is right-clicked, so I can show the popup menu (maybe with visibleWhen in the plugin.xml) ?
I also want to clear the selection, if the right-click is detected in the white area of the TreeView.
Ok, i did not realized that i can still use tree.getItem(...).
So here is my full MouseListener:
treeOPCUA.addMouseListener(new MouseListener()
{
#Override
public void mouseUp(MouseEvent e)
{
if(e.button == 3 && rightMouseClicked == true)
rightMouseClicked = false;
}
#Override
public void mouseDown(MouseEvent e)
{
if(e.button == 3 && rightMouseClicked == false)
rightMouseClicked = true;
if(treeOPCUA.getItem(new Point(e.x, e.y)) == null)
viewer.setSelection(null);
}
#Override
public void mouseDoubleClick(MouseEvent e)
{
viewer.setExpandedState(e.getSource(), true);
}
});
With the boolean variable "rightMouseClicked" I detect in my ISelectionChangedListener if the right mouse is clicked:
if(event.getSelection() instanceof IStructuredSelection && !rightMouseClicked)
I hope this answer helps anyone.
Hey there community I was wondering if is possible to create a program that allows for the user to Drag a file from anywhere on there hard drive (the desktop, documents folder, videos folder) and drop it into the window of the program.
I am creating a media player and I want to be able to play a video by dragging and dropping a MP4 into the window. Do I need to store the file in a variable, or just the location of the file into a variable. Also, it is important I keep support for cross platform.
I am using JavaFx with java 7 update 79 jdk.
Thanks in advance.
Here is a simple drag and drop example that just sets the file name and location. Drag files to it and it shows their name and location. Once you know that it should be a completely separate matter to actually play the file. It is primarily taken from Oracle's documentation: https://docs.oracle.com/javafx/2/drag_drop/jfxpub-drag_drop.htm
A minimal implementation needs two EventHandler s set OnDragOver and OnDragDropped.
public class DragAndDropTest extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Drag a file to me.");
Label dropped = new Label("");
VBox dragTarget = new VBox();
dragTarget.getChildren().addAll(label,dropped);
dragTarget.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
if (event.getGestureSource() != dragTarget
&& event.getDragboard().hasFiles()) {
/* allow for both copying and moving, whatever user chooses */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
}
});
dragTarget.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasFiles()) {
dropped.setText(db.getFiles().toString());
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
}
});
StackPane root = new StackPane();
root.getChildren().add(dragTarget);
Scene scene = new Scene(root, 500, 250);
primaryStage.setTitle("Drag Test");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
When working with Drag and Drop events, you could try the following:
Obtain a Dragboard-object of the DragEvent and work with the method getFiles:
private void handleDragDropped(DragEvent event){
Dragboard db = event.getDragboard();
File file = db.getFiles().get(0);
}
I solved this by adding two event handlers. One for DragDropped event and the other for DragOver event.
e.g:
#FXML
void handleFileOverEvent(DragEvent event)
{
Dragboard db = event.getDragboard();
if (db.hasFiles())
{
event.acceptTransferModes(TransferMode.COPY);
}
else
{
event.consume();
}
}
#FXML
void handleFileDroppedEvent(DragEvent event)
{
Dragboard db = event.getDragboard();
File file = db.getFiles().get(0);
handleSelectedFile(file);
}
Else it did not work for me, dragging the file over my pane, didn't trigger anything.
Currently I am developing a program which transfers a list item into another list. It works well with setOnDragExited,if I drag it to another component with the setOnDragExited, it will be dropped. (Which I think the program is rightbecause that is the function of setOnDragExited. But I need the program to only drop the list item when I release the button).
So I have the source which is fieldList and the target which is mainTable
Here is the code for the source, which I have no problem with.
fieldList.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
/* drag was detected, start a drag-and-drop gesture*/
/* allow any transfer mode */
Dragboard db =fieldList.startDragAndDrop(TransferMode.ANY);
/* Put a string on a dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(fieldList.getSelectionModel().getSelectedItem());
db.setContent(content);
event.consume();
}
});
And here is the code which doesn't work with setOnDragDropped but works with setOnDragExited
mainTable.setOnDragDropped(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
/* data dropped */
System.out.println("onDragDropped");
/* if there is a string data on dragboard, read it and use it */
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
ObservableList<String> ls = FXCollections.observableArrayList();
try {
columnLS.add(Resources.getgBCon().getActualName(tableList.getSelectionModel().getSelectedItem())+"."+db.getString());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
success = true;
String base= "";
if(!columnLS.isEmpty()){
for(int i = 0; i<= columnLS.size()-1 ;i++){
if(i == 0){
base = columnLS.get(i);
}else{
base = base + ", " + columnLS.get(i);
}
}
}
columnQuery = base;
me.refreshSQLQuery(columnQuery,getTableQuery(),filterQuery,groupQuery,sortQuery);
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(true);
event.consume();
}
});
So far I didn't find anything that relates to my problem, on those that are remotely related I found, I have tried but to no avail.
Thank you Stack Overflow.
I have added setOnDragEntered. It seems it still didn't work. Is there a difference between setOnDrag and setOnMouseDrag?
mainTable.setOnDragEntered(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
System.out.println("onDragEntered");
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
});
I have also tried TransferMode.ANY but to no avail.
Solution:
Used mainTable.setOnDragOver instead of mainTable.setOnDragEntered
I have an Eclipse RCP application. In a perspective there are four views and I want to highlight respective views whenever I click on them. Is it possible to do it?
i have tried following code:
private void addFocusBackgroundOnSelectingView() {
viewer.getControl().addListener(SWT.MouseEnter, new Listener() {
#Override
public void handleEvent(Event event) {
viewer.getControl().setBackground(
PlatformUI.getWorkbench().getDisplay()
.getSystemColor(SWT.COLOR_GRAY));
}
});
viewer.getControl().addListener(SWT.MouseExit, new Listener() {
#Override
public void handleEvent(Event event) {
viewer.getControl().setBackground(
PlatformUI.getWorkbench().getDisplay()
.getSystemColor(SWT.COLOR_WHITE));
}
});
}
I want to save the selection even i mouse hover out if that view is already had selected.
The Eclipse PartService keeps track of which part (Editors, Views etc...) is currently active. You can add a listener to the service via the PlatfomUI class:
IPartListener partListener = ...;
IPartService partService = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService();
partService.addPartListener(listener);
The IPartListener interface has partActivated and partDeactivated methods where you can do your highlighting.