I've got a simple Swing GUI with JButtons being run on a Surface tablet with a touchscreen. The buttons have ActionListeners. When these buttons are clicked from a mouse they visually depress correctly. However when they are tapped on the touchscreen they remain visually the same but still fire off an actionPerformed(). If they are double tapped then they visually depress correctly but fire off 2 actionPerformed()s.
Is there a way to get this button animation change to take place when the button is pressed, rather than clicked? I've tested it and I could use a MouseListener and put all my logic in mouseClicked() but it's not very elegant to ask touchscreen users to double tap a button.
The problem you have is that whereas a mouse click is a compound event, a touch on the screen is not. So there's no way that it can go down at the first event and up again at the second.
But what you can do, when you receive a touch event, is change the visual state of the button so it looks depressed (using setPressed(true)), then set a timer for 100ms or so, and set the state back to normal when the timer expires (using setPressed(false)).
Careful with the timer expiration: you need the setPressed(false) to happen on the UI thread. So you'll need to use SwingUtilities.invokeLater() as a wrapper round the second call to setPressed. Or, alternatively, use a javax.swing.Timer as the means of queueing the second call; it takes a delay and an Action, and the Action gets performed on the UI thread.
I use mouse listener but I implement my logic in the moussePressed method and it this works perfectly in IBM touch screens
class BtnNumbMl implements MouseListener {
public void mousePressed(MouseEvent e) {
**//your logic goes here**
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
have a good day
Related
I have developed a small desktop application. After running the program I am able to get the window which contains my GUI design. But If I drag the window inside my content is merging, but My requirement here is that I should not loss my content, but it should appear on the same window, any help would be appreciated?
Thanks in advance
I think you can add a ComponentListener to listen for the change of size of a frame. In the listener you have to implement componentResized and so on, to determine how it works if the size changes.
You can implement like this:
addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void componentResized(ComponentEvent e) {
if (e.getSource() instanceof JFrame) {
JFrame frame = (JFrame) (e.getSource());
int width = frame.getSize().width;
int height = frame.getSize().height;
//your logic here
}
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
});
But, here in my project someone(developed this app and with no knowledge of any layout manager) set all layout to be null, so I must use setBounds() to allocate every element. If you use some decent Layout Manager, like MigLayout, and set the width of every element to be some percentage of the windows' size, it will handle it for you and you are out of trouble.
You can see this question here. The link is the same as I posted in my comment above.
EDIT:
I just posted an answer showing how to do it properly without layout manager, but it's takes a lot of time... See here.
Is it possible obtain a feedback from JButton in a Java Swing application on a tablet?
I am using Windows 8 and if I switch a physical mouse to the device, motion feedback from JButton is in the typical way, but if I use a finger, the feedback disappears.
I have tried overriding methods customizing my inherited JButtons, and a estended etc., but I haven't hoped the goal... I guess it is related with when we touch the screen with a mouse, you only click a point on the screen, but if you touches with a finger, there are several pixels selected.
Any idea?
Thank you so so much!
Im not entirely sure what you mean by feedback, but I THINK the answer to the question your asking is no. Swing was never designed for that sort of interface. However if the feedback you are referring to is something like the button highlighting and swelling when clicked, this is usually something that should happen on its own. If as I suspect you are referring to a hover action being performed when youtouch but dont 'tap' the button, then there is likely no way for you to control that. As an alternative, if your application is not yet mature, you may want to consider switching from swing to JavaFX which uses CSS to give you a large amount of control over things like this.
I've got an acceptable solution. I will try to explain it as simple and complete as possible.
First of all, you have to use a JButton extended class like these:
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
/**
* Customized <code>JButton</code> to obtained a feedback user experience of movement.
* #author Gabriel Moreno.
*/
public class FeedbackTouchScreenButton extends JButton {
public FeedbackTouchScreenButton() {
super();
this.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(final MouseEvent e) {
new Thread(new Runnable() {
#Override
public void run() {
Color bg = e.getComponent().getBackground();
e.getComponent().setBackground(Color.BLUE); // For example
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
e.getComponent().setBackground(bg);
}
}).start();
} // mouseClicked()
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
});
} // FeedbackTouchScreenButton()
} // FeedbackTouchScreenButton
When you customize the action performed of the concerned button, you will have to throw (carefully) another thread. For example:
// ---
btnExample.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(final java.awt.event.ActionEvent evt) {
new Thread(new Runnable() {
#Override
public void run() {
btnExampleActionPerformed(evt);
} // run()
}).start();
}
});
// ---
This example apparently works. But actually only it seems... :-)
The reason is because on the tablet screen the 'onPressed' state of the component doesn't works with a finger like with a mouse pointer.
THE KEY: 'onClick' = 'onPressed' + 'onRelease'.
And 'onClick' is correctlty done on the touch screen. It is the moment when the trick is done, when you release your finger from the device.
I am learning java and Swing right now and trying to develop simple programms for education purposes.
So here is the question.
I have gridlayout and fields on my frame with default text
accNumberField = new JTextField("0", 10);
accNumberField.addFocusListener(new FocusListener() {
int focusCounter = 0;
#Override
public void focusGained(FocusEvent arg0) {
// TODO Auto-generated method stub
if (focusCounter > 0)
accNumberField.setText("");
focusCounter++;
}
What I want is that when user click on field for the first time the default text is disappered. So I add focus listener and used accNumberField.setText(""); in focusGained method.
But the problem is that for default first field in my frame getting focus right in time of frame creation. And default text is disappearing from the begining. I used counter as you can see. But that's not what I wanted.
I want that no field would get focus in time of creation and every field would be able to get focus from the time when user would click on one of them.
Sorry if I spelled something wrong. English is not my native language.
Found a thread having a code example of your desired functionality, Java JTextField with input hint. Precisely, you need to provide your own implementation of JTextField which will be holding the "default-text" in a field, specially created for that.
For your second question, you can set the focus to some button or frame itself.
Is there any reason that you use focusListener()? why not use mouseListener() as follow?
accNumberField.addMouseListener(new MouseAdapter()
{
#Override
public void mouseReleased(MouseEvent e)
{
accNumberField.setText("");
}
});
if you want to clear the text for the first click, you can simply use a boolean:
//outside constructor
private boolean isTextCleared = false;
//in constructor
accNumberField.addMouseListener(new MouseAdapter()
{
#Override
public void mouseReleased(MouseEvent e)
{
if (!isTextCleared)
{
accNumberField.setText("");
isTextCleared = true;
}
}
});
I am making a game that work with swing components (only for submitting high scores) but sometimes when I type things freeze; I don't know why and it's hard to debug.
So, I had to do this
create class SubmitHighScore(ScreenManager, int forScore)
implement KeyListener
I disabled swing to draw itself with the class that I created, called NullRepaintManager. I did this so I can draw without flicker
This is the implemented method that I filled
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
//e.consume();
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode()==KeyEvent.VK_ENTER){
highScore.addScore(new Score(highScoreTextField.getText(),score));
exit.tap();
}
//e.consume();
}
#Override
public void keyReleased(KeyEvent e) {
//filter High Score text. Only A-Z and a-z otherwhise will ignore
highScoreTextField.setText(filter(highScoreTextField.getText()));
//e.consume();
}
This is a simple name that will be submitted when a player presses the ENTER key, but it freezes sometimes. I have tried using setFocusTraversalKeysEnabled(false) and called e.consume (which makes my textfield not fill up when I called consume)
How do I fix this?
Is there another way to submit high scores? Note that I decorate high scores with bg and frame so it look just like another game.
hi i'm using swing and in my main frame(JFrame) i want that when ever user press + key one window lets say test should appear.
my key listener works fine if i don't call the show method of the newly added JInternalFrame but when i call the show method of my JInternalFrame the KeyListener stops listening any more.
i've tried a lot to solve it but all in vain so any help regarding this will be appreciated.
thanks.
this is my keyListener
_mainFrameKeyListener = new KeyListener()
{
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
System.out.println("the key pressed Id is : " + arg0.getKeyCode());
if(arg0.getKeyCode() == 107){
test Test = new test();
_mainDesktopPane.add(Test);
Test.show();
}
}
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
};
Sounds like you want a hot key instead of a key listener to avoid focus issues.
// Get the KeyStroke for our hot key
KeyStroke plus = KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0, true);
// Get the input map for our component
// In this case we are interested in key strokes in the focussed window
InputMap inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
// Map the key stroke to our "action key" (see below)
inputMap.put(plus, "my_action");
// Get the action map for our component
ActionMap actionMap = panel.getActionMap();
// Add the required action listener to out action map
actionMap.put("my_action", actionListener);
http://helpdesk.objects.com.au/java/how-to-specify-a-hot-key-for-a-swing-application
You would need to add the key listener to exactly the component that has focus (many components are actually composites).
So use JComponent.registerKeyboardAction with a condition of WHEN_IN_FOCUSED_WINDOW. Alternatively use JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW, true) and JComponent.getActionMap(true) as described in the registerKeyboardAction API docs.
Please check whether a runtime exception is thrown. may be you are in the wrong thread for showing this dialog or another issue could throw this exception.
Also please think about to use a asynch thread for showing your dialog instead of using the listener thread. But this is just a think about.