I am implementing Drag and Drop functionality in SWT.
Here is my code snippet
For Drag
private class MyDragSourceAdapter extends DragSourceAdapter {
/** The m tree viewer. */
private final TreeViewer treeViewer;
/**
* Instantiates a new my drag source adapter.
*
* #param treeViewer the tree viewer
*/
public MyDragSourceAdapter(TreeViewer treeViewer) {
this.treeViewer = treeViewer;
}
/**
* {#inheritDoc}
*/
#Override
public void dragFinished(DragSourceEvent event) {
// clean buffer
// k = null;
}
/**
* {#inheritDoc}
*/
#Override
public void dragSetData(DragSourceEvent event) {
event.data = "test";
}
/**
* {#inheritDoc}
*/
#Override
public void dragStart(DragSourceEvent event) {
if (some condition) {
// do something
return;
}
event.doit = false;
}
}
For drop
private class MyDropTargetAdapter extends DropTargetAdapter {
#Override
public void dragEnter(DropTargetEvent event) {
event.detail = DND.DROP_LINK;
}
/**
* {#inheritDoc}
*/
#Override
public void dragOver(DropTargetEvent event) {
// Do some functionality
}
/**
* {#inheritDoc}
*/
#Override
public void drop(DropTargetEvent event) {
event.detail = DND.DROP_NONE;
}
}
Some times "dragOver()" method called more than one time? So dragging is happening as many times as dragOver() method called.
I want drop operation to stop after first time.
Please help
dragOver() happens when the mouse is still hovering over the control, before the actual drop happens. You probably mean to override drop(). But if you want the drop from stop happening altogether, set the field detail on the DropTargetEvent to DND.DROP_NONE.
Related
Scenario. I have a graph on which i can perform panning using right click. This works perfectly. Then I added menus on right click perfectly.
Problem. Now right click menus are shown even on mouse release after drag operation completions.
Is there a way to differentiate mouse release and mouse release after mouse drag in Java Swing or JavaFX?
Mouse events are generated independently of one another.
I assume you panning code works with a combination of mousePressed/mouseMoved.
So you need to add some logic to indicate that you are in "panning mode". So if you have a mousePressed followed by a mouseMoved you set a Boolean variable to indicate "panning" mode.
Then in the mouseReleased code you need to check the variable. If "panning mode" then set "panning mode" off and return. Otherwise you are in "popup mode" so you can display the popup.
Since event.isDragDetect() is always true, so I was not able to differentiate events. I created a java class to store a boolean value. This was needed to modify final object state in inner class and was not possible using Boolean wrapper class. Later I am modifying final objects states based on mouse clicked and mouse dragged. I am also checking if mouse release is after drag or without drag as below:-
private void addRightClickMenu() {
final SubMarineBooleanUtilityClass showMenu = new SubMarineBooleanUtilityClass(true);
final MenuItem graphButton1 = new MenuItem("Save Graph as..");
graphButton1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
saveGraphAs();
}
});
final MenuItem graphButton2 = new MenuItem("Reset Graph");
graphButton2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
resetGraph(controlGraph1.getLineChart(), controlGraph2.getLineChart());
}
});
final ContextMenu menu = new ContextMenu(graphButton1, graphButton2);
//Mouse Drag operation cycle=Mouse click+Mouse dragged+Mouse release
getAnchorPaneGraphView().setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
showMenu.setValueBoolean(true);
}
}
});
getAnchorPaneGraphView().setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton()) && showMenu.isValueBoolean()) {
menu.show(getAnchorPaneGraphView(), event.getScreenX(), event.getScreenY());
}
}
});
getAnchorPaneGraphView().setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
showMenu.setValueBoolean(false);
}
}
});
}
public class SubMarineBooleanUtilityClass {
boolean valueBoolean=false;
/**
* #return boolean
*/
public boolean isValueBoolean() {
return valueBoolean;
}
/**
* Constructor passing a boolean values
* #param value
*/
public SubMarineBooleanUtilityClass(boolean value){
this.valueBoolean=value;
}
/**set boolean value
* #param value
*/
public void setValueBoolean(boolean valueBoolean) {
this.valueBoolean = valueBoolean;
}
}
I have the following problem:
I am trying to implement a menu with submenus in libgdx, using the table layout. When a submenu is clicked, a listener is fired, which should setVisible(false) the previous menu, and setVisible(true) the new one. But, although I successfully display the new one, the previous one is still here! Could someone help me?
Here is my code:
The Menu.java:
public class Menu extends Table {
private Stage stage;
public void attachToStage(Stage s) {
if (s != null) {
stage = s;
s.addActor(this);
}
}
public Menu() {
this(null);
}
public Menu(final Stage s) {
attachToStage(s);
setFillParent(true);
top();
left();
}
private void addButtonWithListener(String label, ClickListener listener) {
add().width(10);
Label l = new Label(label, SkinManager.get());
add(l).width(100);
row();
if (listener != null)
l.addListener(listener);
}
/**
* #param label
* #return The menu, for chaining
*/
public Menu addButton(String label) {
addButtonWithListener(label, null);
return this;
}
/**
*
* #param label
* #param m
* the menu to add
* #return The main menu, for chaining
*/
public Menu addMenu(String label, final Menu m) {
addButtonWithListener(label, new ClickListener() {
#Override public void clicked(InputEvent e, float x, float y) {
System.out.println(getChildren());
setVisible(false);
m.setVisible(true);
}
});
m.attachToStage(stage);
m.setVisible(false);
return this;
}
}
My Application:
public class TestApplication implements ApplicationListener {
private Stage stage;
#Override public void create() {
stage = new Stage();
Menu m = new Menu(stage).addButton("Move").addButton("Stay");
m.addMenu("Attack", new Menu().addButton("Sword").addButton("Bow"));
Gdx.input.setInputProcessor(stage);
}
#Override public void render() {
stage.draw();
}
// Other empty methods
}
Thanks a lot!
EDIT: Problem was unrelated, see my answer
Ok, found the problem: not related at all to the Table, just forgott to clear the screen in the Application.
I just added
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
in the render function.
I've created a custom TreeModel by extending DefaultTreeModel, so the user can rename nodes in my JTree. This works fine if my user inputs a new name and then hits enter. If instead of hitting enter, the user clicks away from the node then my valueForPathChanged method doesn't fire and I can't get the new String. How can I get the new user String without the user hitting enter and instead clicking somewhere else in the Tree/Panel/Frame?
To improve the situation slightly you can set the invokesStopCellEditing property of the JTree: being true the ui will commit a pending edit on some internal changes, like expansion or selection change.
final JTree tree = new JTree();
tree.setEditable(true);
// this will often help (see its api doc), but no guarantee
tree.setInvokesStopCellEditing(true);
// a focusListener is **not** helping
FocusListener l = new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
}
#Override
public void focusLost(FocusEvent e) {
// this would prevent editing at all
// tree.stopEditing();
}
};
tree.addFocusListener(l);
JComponent panel = new JPanel(new BorderLayout());
panel.add(new JScrollPane(tree));
panel.add(new JButton("just something to focus"), BorderLayout.SOUTH);
The snippet (to play with) also demonstrates that a focusListener is not working.
CellEditorRemover and its usage in JXTree (as you see, there's slightly more to add than the bare remover (which basically is-a listener to KeyboardFocusManager's focusOwner property):
/**
* {#inheritDoc} <p>
* Overridden to fix focus issues with editors.
* This method installs and updates the internal CellEditorRemover which
* terminates ongoing edits if appropriate. Additionally, it
* registers a CellEditorListener with the cell editor to grab the
* focus back to tree, if appropriate.
*
* #see #updateEditorRemover()
*/
#Override
public void startEditingAtPath(TreePath path) {
super.startEditingAtPath(path);
if (isEditing()) {
updateEditorListener();
updateEditorRemover();
}
}
/**
* Hack to grab focus after editing.
*/
private void updateEditorListener() {
if (editorListener == null) {
editorListener = new CellEditorListener() {
#Override
public void editingCanceled(ChangeEvent e) {
terminated(e);
}
/**
* #param e
*/
private void terminated(ChangeEvent e) {
analyseFocus();
((CellEditor) e.getSource()).removeCellEditorListener(editorListener);
}
#Override
public void editingStopped(ChangeEvent e) {
terminated(e);
}
};
}
getCellEditor().addCellEditorListener(editorListener);
}
/**
* This is called from cell editor listener if edit terminated.
* Trying to analyse if we should grab the focus back to the
* tree after. Brittle ... we assume we are the first to
* get the event, so we can analyse the hierarchy before the
* editing component is removed.
*/
protected void analyseFocus() {
if (isFocusOwnerDescending()) {
requestFocusInWindow();
}
}
/**
* Returns a boolean to indicate if the current focus owner
* is descending from this table.
* Returns false if not editing, otherwise walks the focusOwner
* hierarchy, taking popups into account. <p>
*
* PENDING: copied from JXTable ... should be somewhere in a utility
* class?
*
* #return a boolean to indicate if the current focus
* owner is contained.
*/
private boolean isFocusOwnerDescending() {
if (!isEditing()) return false;
Component focusOwner =
KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
// PENDING JW: special casing to not fall through ... really wanted?
if (focusOwner == null) return false;
if (SwingXUtilities.isDescendingFrom(focusOwner, this)) return true;
// same with permanent focus owner
Component permanent =
KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
return SwingXUtilities.isDescendingFrom(permanent, this);
}
/**
* Overridden to release the CellEditorRemover, if any.
*/
#Override
public void removeNotify() {
if (editorRemover != null) {
editorRemover.release();
editorRemover = null;
}
super.removeNotify();
}
/**
* Lazily creates and updates the internal CellEditorRemover.
*
*
*/
private void updateEditorRemover() {
if (editorRemover == null) {
editorRemover = new CellEditorRemover();
}
editorRemover.updateKeyboardFocusManager();
}
/** This class tracks changes in the keyboard focus state. It is used
* when the JXTree is editing to determine when to terminate the edit.
* If focus switches to a component outside of the JXTree, but in the
* same window, this will terminate editing. The exact terminate
* behaviour is controlled by the invokeStopEditing property.
*
* #see javax.swing.JTree#setInvokesStopCellEditing(boolean)
*
*/
public class CellEditorRemover implements PropertyChangeListener {
/** the focusManager this is listening to. */
KeyboardFocusManager focusManager;
public CellEditorRemover() {
updateKeyboardFocusManager();
}
/**
* Updates itself to listen to the current KeyboardFocusManager.
*
*/
public void updateKeyboardFocusManager() {
KeyboardFocusManager current = KeyboardFocusManager.getCurrentKeyboardFocusManager();
setKeyboardFocusManager(current);
}
/**
* stops listening.
*
*/
public void release() {
setKeyboardFocusManager(null);
}
/**
* Sets the focusManager this is listening to.
* Unregisters/registers itself from/to the old/new manager,
* respectively.
*
* #param current the KeyboardFocusManager to listen too.
*/
private void setKeyboardFocusManager(KeyboardFocusManager current) {
if (focusManager == current)
return;
KeyboardFocusManager old = focusManager;
if (old != null) {
old.removePropertyChangeListener("permanentFocusOwner", this);
}
focusManager = current;
if (focusManager != null) {
focusManager.addPropertyChangeListener("permanentFocusOwner",
this);
}
}
#Override
public void propertyChange(PropertyChangeEvent ev) {
if (!isEditing()) {
return;
}
Component c = focusManager.getPermanentFocusOwner();
JXTree tree = JXTree.this;
while (c != null) {
if (c instanceof JPopupMenu) {
c = ((JPopupMenu) c).getInvoker();
} else {
if (c == tree) {
// focus remains inside the table
return;
} else if ((c instanceof Window) ||
(c instanceof Applet && c.getParent() == null)) {
if (c == SwingUtilities.getRoot(tree)) {
if (tree.getInvokesStopCellEditing()) {
tree.stopEditing();
}
if (tree.isEditing()) {
tree.cancelEditing();
}
}
break;
}
c = c.getParent();
}
}
}
}
you can add an anonymous instance of FocusListener
and implement
void focusLost(FocusEvent e)
this gets triggered before the value is saved so will be not help you in getting the last value. Instead you should set
myTree.setInvokesStopCellEditing(true);
that fires a property change for the INVOKES_STOP_CELL_EDITING_PROPERTY, which
means that you need to have in your tree model something like
public void valueForPathChanged(TreePath path, Object newValue)
{
AdapterNode node = (AdapterNode)
path.getLastPathComponent();
node.getDomNode().setNodeValue((String)newValue);
fireTreeNodesChanged(new TreeModelEvent(this,
path));
}
Regards
I am working on a game using JME3 and Nifty GUI. I have an outer class that has a Nifty member variable. And the inner class should be able to access that variable regardless of access modifier. In the constructor I assign a new Nifty object to it. However when I access that variable in the inner class I run into problems. I did a little debugging and found out it's because the inner class thinks the Nifty member variable is null and I cant figure out why. Its not null in the outer class. Since this is a JME3 game I tried to have the inner class implement the AppState interface but it still shows the Nifty member variable as null. Here is the code:
public class MenuScreen extends SimpleApplication {
/** Used to configure Nifty GUI. */
private Nifty mNifty;
private NiftyJmeDisplay mNiftyDisplay;
private Element popup;
//*******************
// Overridden medhods
//*******************
/** This method is used to initialize everything needed to display the game screen. */
#Override
public void simpleInitApp() {
guiNode.detachAllChildren();
initNifty();
flyCam.setDragToRotate(true);
}
/**
* The game's main update loop.
*
* #param tpf Time Per Fram, the time it takes each loop to run.
*/
#Override
public void simpleUpdate(float tpf) {
// not used
}
#Override
public void simpleRender(RenderManager rm) {
// not used
}
public static void main(String[] args) {
MenuScreen app = new MenuScreen();
app.start();
}
/**
* Helper method to initialize and configure Nifty GUI.
*/
private void initNifty() {
mNiftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
mNifty = mNiftyDisplay.getNifty();
guiViewPort.addProcessor(mNiftyDisplay);
// If this is being run on a desktop then load the desktop main menu.
if (Strings.OS_NAME.contains("windows") || Strings.OS_NAME.contains("mac") || Strings.OS_NAME.contains("linux")) {
mNifty.fromXml("Interface/XML/DesktopMenuScreenGui.xml", "start", new MenuScreen().new MenuScreenGui());
}
// If its an Android device load the mobile main menu.
else if (Strings.OS_NAME.contains("android")) {
mNifty.fromXml("Interface/XML/MobileMenuScreenGui.xml", "mobile", new MenuScreen().new MenuScreenGui());
}
}
//**************
// Inner Classes
//**************
/**
* © Jason Crosby 2012 <p>
*
* This class handles all the GUI interactions like button clicks.
*
* #author Jason Crosby
*/
public class MenuScreenGui implements ScreenController, EventTopicSubscriber<MenuItemActivatedEvent>,
AppState {
#Override
public void initialize(AppStateManager stateManager, Application app) {
}
#Override
public void cleanup() {
}
#Override
public boolean isEnabled() {
return false;
}
#Override
public boolean isInitialized() {
return false;
}
#Override
public void postRender() {
}
#Override
public void setEnabled(boolean active) {
}
#Override
public void stateAttached(AppStateManager stateManager) {
}
#Override
public void stateDetached(AppStateManager stateManager) {
}
#Override
public void render(RenderManager rm) {
}
#Override
public void update(float tpf) {
}
#Override
public void bind(Nifty nifty, Screen screen) {
// not used
}
#Override
public void onEndScreen() {
// not used
}
#Override
public void onStartScreen() {
// not used
}
#Override
public void onEvent(String string, MenuItemActivatedEvent t) {
}
//**************
// Class methods
//**************
/**
* Called when the play button is clicked.
*/
public void playButton() {
}
/**
* Called when the high scores button is clicked.
*/
public void highScoresButton() {
}
/**
* Called when the settings button is clicked.
*/
public void settingsButton() {
}
public void quitButton() {
showDialog();
}
/**
* Called when the rate button is clicked. Only Available on mobile.
*/
public void rateButton() {
}
/**
* Called when the feedback button is clicked. Only on mobile devices.
*/
public void feedbackButton() {
}
/**
* Called when the help button is clicked.
*/
public void helpButton() {
}
/**
* Called when the dialog needs to be shown.
*/
public void showDialog() {
System.out.println("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
popup = new Nifty().createPopup("popup");
System.out.println("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
//Menu myMenu = popup.findNiftyControl("#menu", Menu.class);
//myMenu.setWidth(new SizeValue("100px")); // must be set
//myMenu.addMenuItem("Click me!", new menuItem("menuItemid", "blah blah")); // menuItem is a custom class
//mNifty.subscribe(mNifty.getCurrentScreen(), myMenu.getId(), MenuItemActivatedEvent.class, this);
mNifty.showPopup(mNifty.getCurrentScreen(), popup.getId(), null);
}
public void clsoseDialog() {
}
/**
* Used to return a String to the Nifty xml file.
*
* #param name The name key associated with the String.
* #return The String associated with the key.
*/
public String getString(String name) {
if (name.equals("play")) {
return Strings.PLAY_BUTTON;
}
else if (name.equals("high_score")) {
return Strings.HIGH_SCORES_BUTTON;
}
else if (name.equals("settings")) {
return Strings.SETTINGS_BUTTON;
}
else if (name.equals("quit")) {
return Strings.QUIT_BUTTON;
}
else if (name.equals("rate")) {
return Strings.RATE_BUTTON;
}
else if (name.equals("feedback")) {
return Strings.FEEDBACK_BUTTON;
}
else if (name.equals("rules")) {
return Strings.RULES_BUTTON;
}
return null;
}
}
}
What happens is I click on the quit button which calls the quitButton() method. That works fine. That in turn invokes showDialog() which is where the problem is. In the showDialog() method is this line popup = new Nifty().createPopup("popup"); and it is at that line which mNifty is null when it shouldn't be. Any assistance is appreciated.
The line
popup = new Nifty().createPopup("popup");
does not use mNifty. It creates a new instance of Nifty and then calls creatPopup() on this new instance. Since earlier you initialized mNifty by calling what looks like a factory method
mNifty = mNiftyDisplay.getNifty();
it is quite possible that obtaining a Nifty via new does not return a completely initialized instance. Since you haven't posted the code for Nifty it is unclear what is happening.
I would double-check to make sure that creating a Nifty via new will return a fully initialized instance, and that you really wanted a new instance here.
I have a problem with ClickHandler in my project using GWT.
In the title of dialog box I want to insert a new button.
I created a new insert method: addToTitle(...).
I added ClickHandler to the button
Problem: click event by button doesn't fire. Why?
Here is my code:
DialogBox dialog = new DialogBox();
Button button = new Button("A new Button");
button.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
Window.alert("yuhuhuhu");
}
});
dialog.addToTitle(button);
code (extracted from the comments section) :
public class PlentyDialogWindow extends DialogBox {
private FlowPanel captionPanel = new FlowPanel();
public Widget closeWidget = null;
private boolean closeOnEscKey = false;
private FlowPanel titleContentWrapper = new FlowPanel();
public PlentyDialogWindow(boolean isModal) {
super( false, isModal);
this.addStyleName("DialogBox");
this.getElement().setId("DialogBoxId");
this.setAnimationEnabled(true);
this.closeWidget = generateCloseButton();
}
public void setCaption( String txt,Widget w) {
captionPanel.setWidth("100%");
this.addCaption(txt);
this.titleContentWrapper.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
captionPanel.add(this.titleContentWrapper);
FlowPanel widgetWrapper = new FlowPanel();
widgetWrapper.add(w);
widgetWrapper.addStyleName("PlentyPopupCloseIconWrapper");
captionPanel.add(widgetWrapper);
captionPanel.addStyleName("Caption");
Element td = getCellElement(0,1);
td.setInnerHTML("");
td.appendChild(captionPanel.getElement());
}
/** * * #param w */ public void addToTitle(Widget w) {
this.titleContentWrapper.add(w);
}
}
If your only problem is ClickHandler not being called try using addDOMHandler instead of addClickHandler
yourWidget.addDomHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
}
},ClickEvent.getType());
The solution is a bit tricky.
public class PlentyDialogWindow extends DialogBox {
/*
* Create custom inner class extending `FlowPanel`. You need it only
* to make `onAttach` and `onDetach` methods be visible to wrapping
* class (e.g. your `PlentyDialogWindow` class).
*/
static class MyCaptionPanel extends FlowPanel {
#Override
protected void onAttach() {
super.onAttach();
}
#Override
protected void onDetach() {
super.onDetach();
}
}
/*
* `PlentyDialogWindow`'s field `captionPanel` will be an instance of
* this class.
*/
private MyCaptionPanel captionPanel = new MyCaptionPanel();
/*
* ... leave the rest of your class untouched ...
*/
/*
* Finally, overwrite `PlentyDialogWindow`'s `onAttach` and `onDetach`
* methods to invoke `captionPanel`'s corresponding methods:
*/
#Override
protected void onAttach() {
super.onAttach();
captionPanel.onAttach();
}
#Override
protected void onDetach() {
super.onDetach();
captionPanel.onDetach();
}
}
That's all.