In my application I have a screen where I use Accelerators. I'm using the function key F3 to execute an operation in my application. It works fine everytime, but when I click in any TextField on this screen the function key doesn't execute.
Here is the code where I set the Accelerator:
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.F3),
new Runnable() {
#Override
public void run() {
// do sth here
}
}
);
When I click my textfield and then hit the F3 function key it doesn't work.
Someone knows the solution?
This works for me using Java 1.8.0_45. However I encounter a similar issue with an editable Combobox field.
Edited:
Upon further investigation it does seem to occur with text field as well. I worked around it using the following custom class in place of text field:
public class ShortcutFriendlyTextField extends TextField{
public ShortcutFriendlyTextField() {
super();
addEventHandler(KeyEvent.KEY_RELEASED,new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
//handle shortcuts if defined
Runnable r=getScene().getAccelerators().get(new KeyCodeCombination(event.getCode()));
if(r!=null) {
r.run();
}
}
});
}
}
This answer is based on tikerman's. I added the code to handle modifier keys.
if (!event.getCode().isModifierKey()) {
Consumer<KeyCombination.Modifier[]> runAccelerator = (modifiers) -> {
Runnable r = getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), modifiers));
if (r != null) {
r.run();
}
};
List<KeyCombination.Modifier> modifiers = new ArrayList<>();
if (event.isControlDown()) modifiers.add(KeyCodeCombination.CONTROL_DOWN);
if (event.isShiftDown()) modifiers.add(KeyCodeCombination.SHIFT_DOWN);
if (event.isAltDown()) modifiers.add(KeyCodeCombination.ALT_DOWN);
runAccelerator.apply(modifiers.toArray(new KeyCombination.Modifier[modifiers.size()]));
}
Edit: fix consumer spelling.
If you have accelerators setup else where, such as a MenuBar, using some of the other solutions will cause the shortcut to be executed twice.
In my case, using modifiers with my shortcut (SHIFT + F3) works while in focus in the text area, but not while using just an accelerator such as just F3.
I set mine up to only use the event handler for shortcuts that do not use a modifier.
public static final double JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version"));
public static void makeInputFieldShortCutFriendly(Node node) {
//this bug wasn't fixed until 9.0
if (JAVA_VERSION < 9) {
node.addEventHandler(KeyEvent.KEY_RELEASED, (KeyEvent event) -> {
if (!event.getCode().isModifierKey()) {
if (!event.isAltDown() && !event.isShiftDown() && !event.isAltDown()) {
Runnable r = node.getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), KeyCodeCombination.SHORTCUT_ANY));
if (r != null) {
r.run();
}
}
}
});
}
}
Edit: No modifier shortcuts was fixed in Java 9. Given the popularity of JDK 8 right now, we should probably provide some backwards capatability or request users update there JRE to 9+.
I you are using JavaFx+Scene builder then just make a function that redirect all the event to the respective functions and then add this function to every element in the scene with OnKeyReleased event
Related
I am navigating between forms in the NEW GUI builder. The old one had a back button on every form by default.
How do I enable the back button on new gui builder in every form, every time i navigate in a new form? Tried through constants in theme.res. It is still not enabled by default.
Furthermore, is the method "new form1.show" the best way to navigate between forms ? (see code)
Assuming name files:
Main.java, myapplication.java, Form1 ,Form2 ,Form3
Code for navigation, assuming names button1 and Form3:
public void onbutton1ActionEvent(com.codename1.ui.events.ActionEvent ev) {
new Form3().show();
}
Back command from old gui builder, not working here:
public Form showForm(String resourceName, Command sourceCommand) {
try {
Form f = (Form)formNameToClassHashMap.get(resourceName).newInstance();
Form current = Display.getInstance().getCurrent();
if(current != null && isBackCommandEnabled() && allowBackTo(resourceName)) {
f.putClientProperty("previousForm", current);
setBackCommand(f, new Command(getBackCommandText(current.getTitle())) {
public void actionPerformed(ActionEvent evt) {
back(null);
}
});
}
if(sourceCommand != null && current != null && current.getBackCommand() == sourceCommand) {
f.showBack();
} else {
f.show();
}
return f;
} catch(Exception err) {
err.printStackTrace();
throw new RuntimeException("Form not found: " + resourceName);
}
}
I've tried:
form.setBackCommand(cmd);
public Command setBackCommand(String title, ActionListener<ActionEvent> listener)
public void setBackCommand(Command cmd)
public Command setBackCommand(String title, BackCommandPolicy policy, ActionListener<ActionEvent> listener)
public void setBackCommand(Command cmd, BackCommandPolicy policy)
boolean onBack() {
return true;
}
https://www.codenameone.com/blog/toolbar-back-easier-material-icons.html
on main.java and myapplication.java did not accept the commands.
Form3.getToolbar().setBackCommand("", e -> Form3.showBack());
althouth is should not work only for form3, but every form.
Did not work either. Putting "back command" on every sidemenu would not be the ideal solution, because we might be navigating to each form from different forms.
EXTRA:
Is there a way to enable global toolbar and global commands for all forms, so i do not copy paste the toolbar code for each new form? If not answered here, i might make a new thread.
Thanks.
The old GUI builder handled navigation as it was designed at a time when Nokia was the worlds leader in the mobile phone industry and a 4in device was considered large. Back then we assumed the UI was simpler for each form and the navigation was the hard part.
This changed. But the bigger problem for most developers was the concept of stateless navigation which triggered a lot of issues both in design and functionality.
The new GUI builder doesn't include any navigation code or any global code. Each form stands on its own.
Having said that you can implement your own state machine by just keeping form instances and showing the form you want to navigate to e.g.:
public static class Controller {
private static Form1 f1;
private static Form2 f2;
public static void showF1() {
if(f1 == null) f1 = new Form1();
f1.show();
}
// etc...
}
I used static context for simplicity but you can implement your own strategy. Notice that you can also insert global logic here e.g. add the toolbar as a function like:
private static void initForm(Form f) {
// add global commands to the toolbar
}
Alternatively you can derive all the forms from a common base class as the new GUI builder doesn't restrict your inheritance.
I'm fixing a JavaFX application on JDK 8. The app shows multiple images using something like "jLabel.setIcon(new Image(...))". I know their is a component to show images in JavaFX but it is not the issue (because I'm not allowed to modify neither that part from the source nor the FXML files).
My problem is when minimize or change the window ((using ALT+TAB)) and wait some time (even up 1 hour approx) to come back to the window, this doesn't show the images anymore. However, if I move the window, the images come back.
In an attempt to fix the problem (independently of use the minimize button or ALT+TAB), I added in the final of the init() method this piece of code:
public void init() {
...
stage.focusedProperty().addListener((observable, oldvalue, newvalue) -> {
if (newvalue) repaintImages();
});
}
private void repaintImages() {
Object obj = new Object();
synchronized (obj) {
jLabel.repaint();
jLabel.revalidate();
obj.notify();
}
try {
obj.wait();
} catch (Exception e) {
}
}
The code before runs repaintImages() after the windows is focused. I used synchronized with the idea to be ensured the code is executed in thread-safe (independently of lag), Anyway that doesn't fix the problem (images are missing yet). After that, I change this the code to use runLater():
public void init() {
...
stage.focusedProperty().addListener((observable, oldvalue, newvalue) -> {
if (newvalue) Platform.runLater(()->{repaintImages();});
});
}
private void repaintImages() {
Platform.runLater(() -> {
jLabel.repaint();
jLabel.revalidate();
});
}
And it doesn't work either. Please, any suggestion is welcome.
I know, I wrote a long question, but maybe a suggestion could be to move the window when it is focused. In that case, please give the correct way to do this because I tried and not worked too (using synchronized and runLater()). This is the piece of code I used to move the window (placing this into a synchronized block or in the lambda function in runLater()):
Translate elements = null;
if (positive_flag) {
elements = new Translate(1, 0, 0);
positive_flag = false;
} else {
elements = new Translate(-1, 0, 0);
positive_flag = true;
}
anchorPane.getTransforms().addAll(elements);
Finally, consider that to prove if any solution works, I need to wait even up 1h.
When clicking an Button it need to perform click action in this action should perform change event at this event source is null
My Code:
Multiview.java
#Override
public void onClick(ClickEvent event) {
if(event.getSource() instanceof PushButton)
{
PushButton pb = (PushButton)event.getSource();
if (id.equals("New")) {
int rowNO = startRow + tableModel.rows() - 1;
Window.selectedRow = rowNO;
Window.selectedNode = m_node;
Window.tabNo = multicomponentVO.tabNo;
Window.tabVO = tabfieldsVO;
Window.selectedqueryID=queryID;
Window.cVO = multicomponentVO;
Window.selectedcVO=multicomponentVO;
fireChange("viewnew");
}
}
private void fireChange(String action) {
this.action = action;
if (changeListeners != null) {
changeListeners.fireChange(new ChangeEvent(){});
}
}
Window.java
#Override
public void onChange(ChangeEvent event) {
Widget sender=(Widget)event.getSource();
if(sender instanceof Multiview)
{
// some stuff
}
My query is When firing change event in multiview.java it fires onchange in window.java but im getting event source is null.
Please anyone help to refine or resolve this query
Several issues are contributing to this.
changeListeners.fireChange(new ChangeEvent(){});
You've taken over how the even is supposed to be fired - instead of actually going through the event wiring that would do it right, you've made an object with no source, passed it to fireChange (which I bet is one of your own methods in changeListeners), though you don't have it listed, unless Multiview.fireChange is calling itself...?), and then are complaining that it has no source! Consider firing either from the widget (I'm assuming Mulitview is a widget), or making a handlerManager/eventBus inside Multiview and using that to send the event.
Next, you are firing a DOM event manually, which is a little weird - this is an event that is meant to be fired from user actions in the browser. Take a look at ValueChangeEvent<T> instead.
today I changed my Eclipse IDE from 3.7 to 4.2 and my plugin-project has a new feature in the Statusbar of the UI called QuickAccess. But I dont need it, so how can I disable this feature, because the position of my button bar has changed...
For all who have the same problem, it seems that this new feature is hardcoded and can't be disabled :/ https://bugs.eclipse.org/bugs/show_bug.cgi?id=362420
Go to Help --> Install New Software
https://raw.github.com/atlanto/eclipse-4.x-filler/master/pdt_tools.eclipse-4.x-filler.update/
Install that Plugin and Restart the Eclipse. Quick Access automatically hide.
or else you have an option to hide Window --> Hide Quick Access.
Here's a post that shows a way to hide it with CSS. Verified with Eclipse 4.3
Lars Vogel just reported in his blog post "Porting Eclipse 3.x RCP application to Eclipse 4.4 – now without QuickAccess box":
Bug 411821 ([QuickAccess] Contribute SearchField through a fragment or other means)
is now solved.
Thanks to René Brandstetter:
If a RCP app doesn't provide the QuickAccess element in its model, than it will not be visible. So the default is no QuickAcces, easy enough? :)
See the commit 839ee2 for more details
Provide the "QuickAccess" via a e4 application model fragment inside of the "org.eclipse.ui.ide.application".
This removes the "QuickAccess" search field from every none "org.eclipse.ui.ide.application".
You could also hide it and make it work comparable to how it used to work in Eclipse3.7: when user presses ctrl+3 Quick Access functionality pops up (In Eclipse4.3 the ctrl+3 shortcut is still available).
Example of code you could add to your implementation of WorkbenchWindowAdvisor (for Eclipse4.3 rcp application)
private IHandlerActivation quickAccessHandlerActivation;
#Override
public void postWindowOpen() {
hideQuickAccess();
}
private void hideQuickAccess() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
setQuickAccessVisible(window, false);
final IHandlerService service = (IHandlerService) window.getService(IHandlerService.class);
quickAccessHandlerActivation = service.activateHandler(QUICK_ACCESS_COMMAND_ID, new CustomQuickAccessHandler());
}
private void setQuickAccessVisible(IWorkbenchWindow window, boolean visible) {
if (window instanceof WorkbenchWindow) {
MTrimBar topTrim = ((WorkbenchWindow) window).getTopTrim();
for (MTrimElement element : topTrim.getChildren()) {
if (QUICK_ACCESS_ELEMENT_ID.equals(element.getElementId())) {
element.setVisible(visible);
if (visible) {
Composite control = (Composite) element.getWidget();
control.getChildren()[0].addFocusListener(new QuickAccessFocusListener());
}
break;
}
}
}
}
private class QuickAccessFocusListener implements FocusListener {
#Override
public void focusGained(FocusEvent e) {
//not interested
}
#Override
public void focusLost(FocusEvent e) {
((Control) e.widget).removeFocusListener(this);
hideQuickAccess();
}
}
private class CustomQuickAccessHandler extends AbstractHandler {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
final IHandlerService service = (IHandlerService) window.getService(IHandlerService.class);
setQuickAccessVisible(window, true);
if (quickAccessHandlerActivation != null) {
service.deactivateHandler(quickAccessHandlerActivation);
try {
return service.executeCommand(QUICK_ACCESS_COMMAND_ID, null);
} catch (NotDefinedException e) {
} catch (NotEnabledException e) {
} catch (NotHandledException e) {
}
}
return null;
}
}
Is there a way to disable the Back button in a browser (basically clearing the History token stack) in GWT? Once I browse to a certain page in my application I want to make sure that the user can't use the back button to go back, but only be able to use links on the page to navigate the site.
You cannot disable a button just intercept it and change its return to something the browser does not understand.
This removes the history:
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
To understand it see: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/8b2a7ddad5a47af8/154ec7934eb6be42?lnk=gst&q=disable+back+button#154ec7934eb6be42
However, I would recommend not doing this because your it goes against good UI practices. Instead you should figure out a way that the back button does not cause a problem with your code.
Call the method below in the onModuleLoad().
private void setupHistory() {
final String initToken = History.getToken();
if (initToken.length() == 0) {
History.newItem("main");
}
// Add history listener
HandlerRegistration historyHandlerRegistration = History.addValueChangeHandler(new ValueChangeHandler() {
#Override
public void onValueChange(ValueChangeEvent event) {
String token = event.getValue();
if (initToken.equals(token)) {
History.newItem(initToken);
}
}
});
// Now that we've setup our listener, fire the initial history state.
History.fireCurrentHistoryState();
Window.addWindowClosingHandler(new ClosingHandler() {
boolean reloading = false;
#Override
public void onWindowClosing(ClosingEvent event) {
if (!reloading) {
String userAgent = Window.Navigator.getUserAgent();
if (userAgent.contains("MSIE")) {
if (!Window.confirm("Do you really want to exit?")) {
reloading = true;
Window.Location.reload(); // For IE
}
}
else {
event.setMessage("My App"); // For other browser
}
}
}
});
}
I found a way to make GWT ignore the back-button: Just add historyitem x if no historyitem was set and do nothing on x.
set a historyitem on startup
History.newItem("x")
in the ValueChangeHandler of History add the following:
String historyToken = event.getValue();
if (!historyToken.equals("x"))
History.newItem("x");
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
That is not a fool proof solution. In fire fox I can press the back button and the onWindowClosing method is never invoked. The reason is that I have used History.newItem() and since history exists the back button or backspace buttons simply navigate through the browser history.
So....fix that :)
Put this in your index.html file:
window.open('html page(For example trial.html)', 'Name of the desired site', width='whatever you want',height='whatever you want', centerscreen=yes, menubar=no,toolbar=no,location=no,
personalbar=no, directories=no,status=no, resizable=yes, dependent=no, titlebar=no,dialog=no');