Is it possible, in GWT, to temporarily suspend a certain key press until it is desired to allow that key press again? Like a global suspension. I have an issue where when I open the date picker on a RelativeDateItem in SmartGWT, that it causes the entire page to scroll out of view until the user hits the UP arrow again.
This is working for me for a JEditorPane:
#Override
public void keyTyped(KeyEvent evt) {
if (inTag() > -1) {
evt.consume();
}
The javadoc shows:
void java.awt.event.InputEvent.consume()
consume
public void consume()
Consumes this event so that it will not be processed in the default manner by the source which originated it.
The JEditorPane is in a JFrame which implements KeyListener and the JEditorPane does:
jEditorPaneSource.addKeyListener(this);
datepicker.addKeyPressHandler(new com.smartgwt.client.widgets.events.KeyPressHandler() {
public void onKeyPress(
com.smartgwt.client.widgets.events.KeyPressEvent event) {
event.preventDefault();
}
});
I believe you can block it with this.
Event.addNativePreviewHandler(new NativePreviewHandler(){
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
EventTarget eventTarget = event.getNativeEvent().getEventTarget();
Element el = Element.as(eventTarget);
switch (event.getTypeInt()){
case Event.ONKEYPRESS:
case Event.ONKEYUP:
case Event.ONKEYDOWN:
if (el.getNodeName().equalsIgnoreCase("NODE FROM DATEPICKER")) {
if (event.getNativeEvent().getKeyCode() == "yourKeyCodeToBlock"
event.cancel();
}
}
break;
}
}
});
Related
Task:
There is a large application in which new jComponent are periodically created. Need to add processing for all of them by mouse clicking on them with the "Alt" key pressed.
It is clear that this needs to be done using component.addMouseListener().
Is there a section of the JComponent creation code where we can insert our code?
Or are there other ways to solve the problem?
My code based on Rjelinek's suggestion:
public static void registrationMouseAction() {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(final AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
if (mouseEvent.getID() == MOUSE_CLICKED) {
// # left prev
if (mouseEvent.getButton() == 4) {
new BackRecentDefinitionAction().performed();
}
// # right next
if (mouseEvent.getButton() == 5) {
new BackRecentDefinitionAction().performed();
}
// # view modal editor
if (mouseEvent.getButton() == 1 && mouseEvent.isAltDown()) {
new OpenModalEditorRadixObjectsAction().performed();
}
}
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
}
Correction:
I need to have the processing of "Alt+MouseButton1" for all components in the application (for example, JButton, JPanel, etc.).
the solution for you lies somewhere in this lines. However I must say that on application start up it does make some mouse click on background, that will probably need to be addressed
EDIT
After posting I realized there is a request for alt key down, so I added this condition and it restrict code spam on start up. however its still not optimal
public class Main {
public static void main(String[] args) {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTListener(), AWTEvent.MOUSE_EVENT_MASK);
//your code
}
private static class AWTListener implements AWTEventListener{
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent evt && evt.isAltDown()) {
//your mouse event code
}
}
}
I want to create a JDialog where the text in the textfields is selected but only if the focus is gained from keyboard (TAB, CTRL+TAB). I have found several topics on this matter but had problems with implementing it.
Here is one which I was trying.
And my code:
public class Dialogg extends JDialog implements FocusListener, MouseListener {
private boolean focusFromMouse = false;
public Dialogg() {
JTextField tf1 = new JTextField("text1");
JTextField tf2 = new JTextField("text2");
tf1.addMouseListener(this);
tf2.addMouseListener(this);
tf1.addFocusListener(this);
tf2.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
if (!focusFromMouse) {
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse = true;
}
}
#Override
public void focusLost(FocusEvent e) {
focusFromMouse = false;
}
#Override
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
}
It does not work as intended, it does not matter what is focus source the text always highlights. When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked code so the flag is not reset when it should. Any hints?
EDIT:
As suggested by M. Prokhorov I have deleted less relevant (for the question) lines from the code.Thank you.
EDIT 2:
I am trying to wrap focus listener as suggested by camickr. It looks like this now:
tf1.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (!focusFromMouse){
tf1.selectAll();
focusFromMouse=true;
}
}
});
}
public void focusLost(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
focusFromMouse=false;
}
});
}
});
public void mouseClicked(MouseEvent e) {
focusFromMouse=true;
I am printing line after each event to see the action order and still mouseClicked happens last. What am I doing wrong?
EDIT 3:
OK, I have found a solution which fulfils requirements of my simple Dialog.
I could not find a way of doing this with use of invokeLater or EventQueue. Vladislav's method works but as I understand it restricts the user to only use the keyboard.
I have used the initial approach but I have added an auxiliary variable and few conditions which allow to pass the flag "unharmed" trough Events that should not change the flag at given moment. It may not be subtle or universal but works for my app. Here is the code:
public void focusGained(FocusEvent e) {
if(!focusFromMouse){
if (higlight){
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse=false;
}
}
}
public void focusLost(FocusEvent e) {
if (focusFromMouse){
higlight=false;
focusFromMouse=false;
}else{
higlight=true;
}
}
public void mousePressed(MouseEvent e) {
focusFromMouse=true;
}
At the first, by default, focus on JTextField is requested by mouse-press event, not by mouse-click.
So, this method:
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
is useless because the mouse-click event is triggered after the mouse-press event.
One way to solve your problem is to remove all native MouseListeners from JTextField:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Another way is to handle all mouse events and consume those of them, which are triggered by JTextField:
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked
Wrap the code in the FocusListener in a SwingUtilities.invokeLater(). The will place the code on the end of the Event Dispatch Thread (EDT), so the code will run after the variable in the MouseListener has been set.
See Concurrency in Swing for more information about the EDT.
Edit:
Just noticed the other answer. You might be able to do something simpler. Istead of listener for mouseClicked, listen for mousePressed. A mouseClicked event is only generated AFTER the mouseReleased event, so by that time the FocusListener logic has already been executed, even when added to the end of the EDT.
Edit 2:
If the above doesn't work then you might be able to use the EventQueue.peek() method to see if a MouseEvent is on the queue. This might even be easier than worrying about using the invokeLater.
In my project I need to fire an event after a node was clicked in my CellTree. I solved this with the following code.
model.setSelectionHandler(new SelectionChangeEvent.Handler()
{
#Override
public void onSelectionChange(SelectionChangeEvent event)
{
//My logic is here
}
});
The problem is that this only works if the node is not selected already. Clicking the node again will not fire the event. Is there a click handler or another event which is fired after a node was clicked?
Please try with SelectionHandler api .
This can be achieved by creating your own TreeItem that implements ClickHandler
public class CustomTreeItem extends TreeItem implements ClickHandler
{
//classes logic here
#Override
public void onClick(ClickEvent event)
{
// TODO Auto-generated method stub
}
}
Sometimes I use something like this:
model.setSelectionHandler(new SelectionChangeEvent.Handler()
{
#Override
public void onSelectionChange(SelectionChangeEvent event)
{
SomeType selected = model.getSelectedObject();
if (selected != null)
{
// Logic here...
model.clear();
}
}
});
But this solution obviously removes visual feedback what was selected.
You could add a DOM handler to your CellTree using [Widget.addDomHandler](http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/Widget.html#addDomHandler(H, com.google.gwt.event.dom.client.DomEvent.Type)):
cellTree.addDomHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
// TODO: check if a node is selected and it was clicked here
}
}, ClickEvent.getType());
Additionally you might need to prevent calling the handler twice if you use the selection handler as well and click a node.
Just a side note: Unfortunately I did not see an easy way to determine if the user actually clicked on a tree item like a bounds check for the click coordinates. So this might get a bit harder to achieve.
my layout like :
i want focus at Company Name Texfield when i press TAB button at first time , but right now i get focus at Add Button how can i manage it ?
i try code like
ChangeFocus(mTextFieldCompanyName, mTextAreaAboutUs);
ChangeFocus(mTextAreaAboutUs, mTextAreaContactUs);
ChangeFocus(mTextAreaContactUs, mButtonVideo);
ChangeFocus(mButtonVideo, mButtonImage);
ChangeFocus(mButtonImage, mButtonSave);
public void ChangeFocus(Control mControlFrom,final Control mControlTo)
{
mControlFrom.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event)
{
if (event.getCode() == KeyCode.TAB)
{
System.out.println("TAB pressed");
mControlTo.requestFocus();
event.consume(); // do nothing
}
}
});
}
Try wrapping your mTextFieldCompanyName inside Platform.runLater()
Platform.runLater(new Runnable() {
#Override
public void run() {
mTextFieldCompanyName.requestFocus();
}
});
Hope it helps :)
Right now I have the following code working:
#UiHandler("usernameTextBox")
void onUsernameTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
#UiHandler("passwordTextBox")
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
void keyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I would like the ability to have just one listener for all elements on the view without duplicating an event for each textbox.
The end goal is that if they press enter, regardless of where they are on the page, it should submit the form.
Thanks!
What works, but still requires you to specify it for each widget, but doesn't require duplicate code:
#UiHandler({"usernameTextBox", "passwordTextBox"})
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
Yes jackcrews is correct. Also you can try the following. It may be VerticalPanel, DockLayoutPanel etc....
UiBinder.ui.xml
<gwt:VerticalPanel ui:field="mainPanel">
<gwt:Label>Name</gwt:TextBox>
<gwt:TextBox ui:field="textBox">
</gwt:VerticalPanel>
Main.java
#UiField
VerticalPanel mainPanel;
public Main() {
focushandler();
}
void focusHandler() {
mainPanel.addDomHandler(new Handler(), KeyPressEvent.getType());
}
final class Handler implements KeyPressHandler {
#Override
public void onKeyPress(KeyPressEvent event) {
//Code what you expect
}
}
Actually this has more number of lines. But it is good practice.
Regards,
Gnik
I found out that the g:FocusPanel allows me to capture events for everything inside the panel.
#UiHandler("focusPanel")
void onFocusPanelKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}