I'm building an application in JavaFx 2.2 which consist in a splitpane with a panel of component on the left side and a working sheet on the right side. Basically what i would like to do is a simple wysiwyg editor where you drag component from the left to the right, then arrange them on the right side.
I've spent the last couple of days trying to implement the same drag-and-drop feature that has SceneBuilder, without luck..
Following the sample at http://docs.oracle.com/javafx/2/drag_drop/HelloDragAndDrop.java.html i've managed to get a drag-and-drop working but i can't find any way to change the default file icon appearing when you are dragging (and replace it with a snapshot of the component i'm dragging) and how to show the forbidden icon when you are over something you can't dropped on.
Any help (could be advice, code snippet, sample or else) would be greatly appreciated :)
Thanks !
[UPDATE]
Finally managed it myself:
/* The 'sceneRoot' object is the root Node of the scene graph
* stage.setScene(new Scene(sceneRoot, 1280, 1024));
*/
private ImageView dragImageView = new ImageView();
private Node dragItem;
_
rightPane.setOnMouseDragEntered(new EventHandler<MouseDragEvent>() {
public void handle(MouseDragEvent e) {
rightPane.setStyle("-fx-border-color:red;-fx-border-width:2;-fx-border-style:solid;");
e.consume();
}
});
rightPane.setOnMouseDragExited(new EventHandler<MouseDragEvent>() {
public void handle(MouseDragEvent e) {
rightPane.setStyle("-fx-border-style:none;");
e.consume();
}
});
rightPane.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
public void handle(MouseDragEvent e) {
//TODO: add new instance of dragItem to rightPane
e.consume();
}
});
_
private void addGesture(final Node node) {
node.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent e) {
SnapshotParameters snapParams = new SnapshotParameters();
snapParams.setFill(Color.TRANSPARENT);
dragImageView.setImage(node.snapshot(snapParams, null));
sceneRoot.getChildren().add(dragImageView);
dragImageView.startFullDrag();
e.consume();
}
});
node.setOnMouseDragged(new EventHandler<MouseEvent>() {
public void handle(MouseEvent e) {
Point2D localPoint = sceneRoot.sceneToLocal(new Point2D(e.getSceneX(), e.getSceneY()));
dragImageView.relocate(
(int)(localPoint.getX() - dragImageView.getBoundsInLocal().getWidth() / 2),
(int)(localPoint.getY() - dragImageView.getBoundsInLocal().getHeight() / 2)
);
e.consume();
}
});
node.setOnMouseEntered(new EventHandler<MouseEvent>() {
public void handle(MouseEvent e) {
node.setCursor(Cursor.HAND);
}
});
node.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent e) {
dragItem = node;
dragImageView.setMouseTransparent(true);
node.setMouseTransparent(true);
node.setCursor(Cursor.CLOSED_HAND);
}
});
node.setOnMouseReleased(new EventHandler<MouseEvent>() {
public void handle(MouseEvent e) {
dragItem = null;
dragImageView.setMouseTransparent(false);
node.setMouseTransparent(false);
node.setCursor(Cursor.DEFAULT);
sceneRoot.getChildren().remove(dragImageView);
}
});
}
Maybe late, but with the setDragView option, is more simpple by now :)
// Cursor Display for Drag&Drop
source.setOnMouseEntered(e -> source.setCursor(Cursor.OPEN_HAND));
source.setOnMousePressed(e -> source.setCursor(Cursor.CLOSED_HAND));
source.setOnMouseReleased(e -> source.setCursor(Cursor.DEFAULT));
// Manage drag
source.setOnDragDetected(event -> {
/* drag was detected, start a drag-and-drop gesture*/
Dragboard db = source.startDragAndDrop(TransferMode.MOVE);
// Visual during drag
SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setFill(Color.TRANSPARENT);
db.setDragView(source.snapshot(snapshotParameters, null));
/* Put a string on a dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(source.getText());
db.setContent(content);
event.consume();
});
Related
I am using javafx to make a ListView in which add Observable List which contains buttons.
I want to add action on each buttons in this lists.Any help...
ObservableList videoLists = null;
if (listView.getSelectionModel().getSelectedItem().equals("class 8")) {
classTitleID.setText("class 8 video lists");
File physicsFolder = new File("D:\\videos\\physics");
File[] listOfFiles = physicsFolder.listFiles();
videoLists = FXCollections.observableArrayList();
for (File file : listOfFiles) {
if (file.isFile()) {
videoLists.add(new Button(file.getName()));
physicsListview.setItems(videoLists);
}
}
}
simply do
for (File file : listOfFiles) {
if (file.isFile()) {
Button button = new Button(file.getName());
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
//your action
}
});
videoLists.add(button);
physicsListview.setItems(videoLists);
}
}
It's generally a bad idea to have Node subclasses as the data type in ListViews (or TableViews, ComboBoxes, etc): it breaks MVC. Make your ListView a ListView<File> and use a cellFactory to show the button in the ListView cells. You can set the action handler there.
ListView<File> physicsListview = new ListView<>();
ObservableList<File> videoLists = FCollections.observableArrayList();
//...
for (File file : listOfFiles) {
if (file.isFile()) {
videoLists.add(file);
}
}
physicsListview.setItems(videoLists);
physicsListview.setCellFactory(new Callback<ListView<File>, ListCell<File>>() {
#Override
public ListCell<File> call(ListView<File>()) {
final Button button = new Button();
return new ListCell<File>() {
#Override
public void updateItem(final File item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
button.setText(item.getName());
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// handle action.
// You can access the File object item here if needed
}
});
setGraphic(button);
}
}
};
});
});
private void gotoRightClick() {
textArea.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
if(event.isSecondaryButtonDown())
{
System.out.println("right click pressed in text area");
}
}
});
tableView.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent e) {
if(e.isSecondaryButtonDown())
{
System.out.println("right click pressed in table view");
}
}
});
}
None of the event is detecting can any one help me?
Thanks Advance
Try this:
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getButton().equals(MouseButton.SECONDARY)) {
//do something
}
}
});
UPDATE:
My Requirement is to display two Rss files as Tabs on my LWUIT Form
Initially by default first Rss file titles and images should be displayed on first tab
if an end user click on second tab,we should be able to load the second rss file titles and images
I am able to load first Rss File titles,but i am not able to load the second tab if i click on it
How to capture the click event for LWUIT Tab?
Here my code which is not working:
String topNewsurl="TopNews.rss";
String topStoryurl="TopStory.rss";
public class XMLMidlet extends MIDlet{
public void startApp() {
Display.init(this);
Process p;
try {
p = new Process(this);
p.process();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public class Process extends Form {
Process(XMLMidlet midlet) throws IOException {
this.midlet=midlet;
topnews = new Vector();
topstory = new Vector();
tabs = new Tabs();
form1 = new Form();
form2=new Form();
form1.setLayout(new BorderLayout());
form1.setScrollable(false);
image = Image.createImage("/res/Tone.jpg");
Label icon = new Label(image);
form1.setTitleComponent(icon);
form2.setTitleComponent(icon);
form1.setTransitionInAnimator(Transition3D.createRotation(250, true));
try {
newsList = new List(topnews);
newsList.setScrollVisible(false);
newsList.setRenderer(new NewsListCellRenderer());
myNewsList = new List(topstory);
myNewsList.setScrollVisible(false);
myNewsList.setRenderer(new NewsListCellRenderer());
tabs.addTab("Topstory", newsList);
tabs.addTab("TopNews", myNewsList);
tabs.setChangeTabOnFocus(true);
form1.addComponent(BorderLayout.CENTER, tabs);
}
try{
String url = "http:topnews-20.rss";
form1.show();
ParseThread myThread = new ParseThread(this);
myThread.getXMLFeed(url);
} catch (Exception e) {
e.printStackTrace();
}
}
public void addNews(News newsItem) {
//log.debug("addnews");
//System.out.println("addNews");
topnews.addElement(newsItem);
newsList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
List source = (List) ae.getSource();
News selectedNewsItem = (News) source.getSelectedItem();
if (selectedNewsItem != null) {
displayCompleteNewsScreen(selectedNewsItem);
}
}
});
form1.show();
}
public void keyReleased(int keyCode) {
System.out.println("str");
Component p=this.getFocused();
String str= p.getClass().getName();
if(str.toLowerCase().indexOf("radiobutton")!=-1){
process();
}
From the very vague question it seems you want to capture key presses on a LWUIT Form.
jobsForm.addGameKeyListener(Display.GAME_FIRE,
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//do something here
}
});
jobsForm.addPointerPressedListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
pointer_click = true;
}
});
jobsForm.addPointerReleasedListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (pointer_click) {
//
}
pointer_click = false;
}
});
jobsForm.addPointerDraggedListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//System.out.println("POINTER DRAGGED");
pointer_click = false;
}
});
I've been trying to move an undecorated stage around the screen, by using the following mouse listeners:
onPressed
onReleased
onDragged
These events are from a rectangle. My idea is to move the undecorated window clicking on the rectangle and dragging all the window.
#FXML
protected void onRectanglePressed(MouseEvent event) {
X = primaryStage.getX() - event.getScreenX();
Y = primaryStage.getY() - event.getScreenY();
}
#FXML
protected void onRectangleReleased(MouseEvent event) {
primaryStage.setX(event.getScreenX());
primaryStage.setY(event.getScreenY());
}
#FXML
protected void onRectangleDragged(MouseEvent event) {
primaryStage.setX(event.getScreenX() + X);
primaryStage.setY(event.getScreenY() + Y);
}
All that I've got with these events is when I press the rectangle and start to drag the window, it moves a little bit. But, when I release the button, the window is moved to where the rectangle is.
Thanks in advance.
I created a sample of an animated clock in an undecorated window which you can drag around.
Relevant code from the sample is:
// allow the clock background to be used to drag the clock around.
final Delta dragDelta = new Delta();
layout.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = stage.getX() - mouseEvent.getScreenX();
dragDelta.y = stage.getY() - mouseEvent.getScreenY();
}
});
layout.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
stage.setX(mouseEvent.getScreenX() + dragDelta.x);
stage.setY(mouseEvent.getScreenY() + dragDelta.y);
}
});
...
// records relative x and y co-ordinates.
class Delta { double x, y; }
Code looks pretty similar to yours, so not quite sure why your code is not working for you.
I'm using this solution for dragging undecoraqted stages by dragging any contained node.
private void addDraggableNode(final Node node) {
node.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
if (me.getButton() != MouseButton.MIDDLE) {
initialX = me.getSceneX();
initialY = me.getSceneY();
}
}
});
node.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
if (me.getButton() != MouseButton.MIDDLE) {
node.getScene().getWindow().setX(me.getScreenX() - initialX);
node.getScene().getWindow().setY(me.getScreenY() - initialY);
}
}
});
}
Based on jewelsea's reply i made two lamba expressions to set the MouseListeners directly on the scene in my start() method. Works fine :)
private double xOffset;
private double yOffset;
/*
The two following lambda expressions makes it possible to move the application without the standard StageStyle
*/
//Lambda mouse event handler
scene.setOnMousePressed(event -> {
xOffset = primaryStage.getX() - event.getScreenX();
yOffset = primaryStage.getY() - event.getScreenY();
});
//Lambda mouse event handler
scene.setOnMouseDragged(event -> {
primaryStage.setX(event.getScreenX() + xOffset);
primaryStage.setY(event.getScreenY() + yOffset);
});enter code here
My guess is that your:
onRectangleReleased()
is passing the very same coordinates from your
onRectanglePressed()
This happens because as stated in the documentation the getX() method from the MouseEvent class returns
Horizontal position of the event relative to the origin of the
MouseEvent's source.
then, when you release your mouse it actually puts your rectangle in the place it was when you first mouse pressed.
BTW, I use a StackPane with a Rectangle inside and then apply the following code:
private void addDragListeners(final Node n){
n.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
if(me.getButton()!=MouseButton.MIDDLE)
{
initialX = me.getSceneX();
initialY = me.getSceneY();
}
else
{
n.getScene().getWindow().centerOnScreen();
initialX = n.getScene().getWindow().getX();
initialY = n.getScene().getWindow().getY();
}
}
});
n.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
if(me.getButton()!=MouseButton.MIDDLE)
{
n.getScene().getWindow().setX( me.getScreenX() - initialX );
n.getScene().getWindow().setY( me.getScreenY() - initialY);
}
}
});
}
addDragListeners(mainStackPane);
Besides that, I use the Middle Mouse Button to center my Window on the screen. I hoped it helped. Cheers!
double x, y;
private void addDragListeners(final Node n, Stage primaryStage){
n.setOnMousePressed((MouseEvent mouseEvent) -> {
this.x = n.getScene().getWindow().getX() - mouseEvent.getScreenX();
this.y = n.getScene().getWindow().getY() - mouseEvent.getScreenY();
});
n.setOnMouseDragged((MouseEvent mouseEvent) -> {
primaryStage.setX(mouseEvent.getScreenX() + this.x);
primaryStage.setY(mouseEvent.getScreenY() + this.y);
});
}
public void start(Stage primaryStage) {
try {
...
addDragListeners(mainPane, primaryStage);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
I have a problem with a Context menu in JavaFx 2:it never disappers when I left click on the graph of the JFXPanel
Does anybody knows how to solve this problem?
Thanks
Here is my code
final ContextMenu cm = new ContextMenu();
MenuItem chartItem1 = new MenuItem("Chart Settings");
cm.getItems().add(chartItem1);
getScene().setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if(cm.isShowing()){
cm.hide();
}
if(mouseEvent.getButton() == MouseButton.SECONDARY)
{
cm.show(getScene().getRoot(), mouseEvent.getScreenX(), mouseEvent.getScreenY());
}
}
});
chartItem1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
dialogs.ChartFormat cs = new dialogs.ChartFormat(null, true);
cs.setLocationRelativeTo(null);
cs.setVisible(true);
}
});
Reproduced the described behavior. Don't know the reason but you can use ContextMenu#hide():
final ContextMenu cm = new ContextMenu();
MenuItem menuItem = new MenuItem("Item 1");
menuItem.addEventHandler(EventType.ROOT, new EventHandler<Event>() {
#Override
public void handle(Event t) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel messagePane = new JPanel();
messagePane.add(new JLabel("label"));
JDialog jDialog = new JDialog();
jDialog.getContentPane().add(messagePane);
jDialog.pack();
jDialog.setVisible(true);
}
});
}
});
cm.getItems().add(menuItem);
scene.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
// if(cm.isShowing())
cm.hide();
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
cm.show(lineChart, mouseEvent.getScreenX(), mouseEvent.getScreenY());
}
}
});
Also you can check out these links:
http://pixelduke.wordpress.com/2011/12/11/popupmenu-in-javafx/
http://javafx-jira.kenai.com/browse/RT-17853
http://javafx-jira.kenai.com/browse/RT-14899
Adding sample code to your question would be more descriptive.