Let me describe little bit whats my situation,
I have SWT Text in my Java SE SWT application:
let say USER will write something (String) to the created Text while app running. I would like to introduce some MouseListener which would do exactly this:
When USER would click into Textobject/widget, this Text would clear(setText("");) itselves(if there was previously written some String).
MouseListener has 3 methods: mouseDown(...), mouseUp(..), mouseDoubleClick(...) -> I should use onlymouseDown(...) in this case - nothing more isnt nescesary.
In mouseDown(..) method I would need to call method of actual Text object reference : "XY".setText(""); Text which was clicked-into by mouse. -> This I somehow could not obtain.
I would like to have it somehow like general MouseListener onMouseClickText which could be applied to any SWT Text I will use in my app.
Does anybody know how to do such MouseListener or better : how to obtain this reference to existing clicked SWT Text, inside MouseListener?
here is example code:
package sk.tokra.example;
//imports here
.
.
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
.
.
public class Application {
//class fields
Text text;
private static final Logger logger = LoggerFactory.getLogger(Application.class);
.
.
.
// main
public static void main(String[] args) {
logger.debug("main(), Starting app!");
try {
Application window = new Application();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
logger.debug("main(), Exiting app!");
return;
}
/**
* Open the window.
*/
public void open() {
logger.debug("open()");
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
text = new Text(shell, SWT.BORDER);
text.addMouseListener(onMouseClickText);
.
.
.
}
//other stuff/methods/listener part
private MouseListener onMouseClickText = new MouseListener() {
#Override
public void mouseUp(MouseEvent arg0) {
logger.debug("onMouseClickFind, mouseUp()");
}
#Override
public void mouseDown(MouseEvent arg0) {
logger.debug("onMouseClickFind, mouseDown()");
// HERE I WOULD NEED to obtain refence of Text
// then call .setText("");
}
#Override
public void mouseDoubleClick(MouseEvent arg0) {
logger.debug("onMouseClickFind, mouseDoubleClick()");
}
};
}
As Naveen suggested it is much better to you use a focus listener because the same text widget can receive focus through numerous different ways (like tabbing on keyboard). You might want to handle that case as well.
In any case, whether you use a FocusListener or MouseListener on the Text, you can fetch the widget which actually caused the event. In case of the mouse listener you receive an instance of MouseEvent and you can use MouseEvent#widget to access the Text control. Your code would look something like below in the listener implementation:
//other stuff/methods/listener part
private MouseListener onMouseClickText = new MouseListener() {
#Override
public void mouseUp(MouseEvent arg0) {
((Text) arg0.widget).setText("");
}
...
}
You may add the same listener instance to multiple Text widgets, it should work.
Related
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 have some text field on my form. And I like focusGained and focusLost event. Doing this with 2 or 3 text field is easy. But, after 18 text field, well, it's kinda confusing.
Is there any way to shorten the focusGained and focusLost event?
Example:
txtSomeTextFocusGained(java.awt.event FocusEvent evt){
if(txtSomeText.getText().equals("Text here!"){
txtSomeText.setText("");
}
}
txtSomeTextFocusLost(java.awt.event FocusEvent evt){
if(txtSomeText.getText().equals(""){
txtSomeText.setText("Text here!");
}
}
That's one text field, I've problem handling with about 18 text field. Any way to simplify that?
Thanks.
The methods are simple enough, so I can't think of a way to simplify them any further. What you can do, though, is prevent code repetition by declaring one FocusListener instance and then add it using addFocusListener(...) to all text-fields.
It would look something like this:
// Instantiate a FocusListener ONCE
java.awt.event.FocusListener myFocusListener = new java.awt.event.FocusListener() {
public void focusGained(java.awt.event.FocusEvent focusEvent) {
try {
JTextField src = (JTextField)focusEvent.getSource();
if (src.getText().equals("Text here!") {
src.setText("");
}
} catch (ClassCastException ignored) {
/* I only listen to JTextFields */
}
}
public void focusLost(java.awt.event.FocusEvent focusEvent) {
try {
JTextField src = (JTextField)focusEvent.getSource();
if (src.getText().equals("") {
src.setText("Text here!");
}
} catch (ClassCastException ignored) {
/* I only listen to JTextFields */
}
}
};
(You could omit the try-catch blocks if you were absolutely sure that the source of the event would always be a JTextField, but it is always a bad practice to rely on such assumptions.)
Then, for every JTextField you only need to add the same FocusListener:
...
someTextField.addFocusListener(myFocusListener);
...
(It's only half a line - difficult to get any shorter than that.)
Another alternative would be to subclass JTextField, adding a FocusListener in the constructor, but I don't see any advantage over the first solution (unless you want a more flexible/powerful solution, e.g. different text for each JTextField etc).
If you want just to set some text in field which gets focused you could write separated event handler class which implements FocusListener and then override focusGained and focusLost methods. Something like this:
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JTextField;
public class CustomFocusListener implements FocusListener {
JTextField txt;
String textWhenFocusGained;
String textWhenFocusLost;
public CustomFocusListener(JTextField txt, String textWhenFocusGained,
String textWhenFocusLost) {
this.txt = txt;
this.textWhenFocusGained = textWhenFocusGained;
this.textWhenFocusLost = textWhenFocusLost;
}
#Override
public void focusGained(FocusEvent arg0) {
txt.setText(textWhenFocusGained);
}
#Override
public void focusLost(FocusEvent arg0) {
txt.setText(textWhenFocusLost);
}
}
Use this.
if(txtSomeText.getText().equals("Text here!")){
txtSomeText.setText("");
/////////////// It's problem of lower and supper case you should make ur text in lower case in code. and for desing of jtextfield it's ok
txtIdDeVoyageur = new JTextField();
txtIdDeVoyageur.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
if(txtIdDeVoyageur.getText().trim().toLowerCase().equals("id de voyageur")){
txtIdDeVoyageur.setText("");
txtIdDeVoyageur.setForeground(Color.black);
}
}
#Override
public void focusLost(FocusEvent e) {
if (txtIdDeVoyageur.getText().trim().equals("") ||
txtIdDeVoyageur.getText().trim().toLowerCase().equals("id de voyageur"))
{
txtIdDeVoyageur.setText("id de voyageur");
txtIdDeVoyageur.setForeground(new Color (153,153,153));
}
}
});
There's a text field and when lost focus it will validate the inputs, if not passed, print out the error message (to be simple here just has an empty check). And there's a button next to the text field, it will print out the text once click on it.
As I tried, when input some text and then click the button it will trigger both the focus lost event of text field and the event of button. In a other word, it will do the validation first and then print out the input text.
Here comes my question, what is the good approach to prevent printing out the text if the validation not passed? Or is there a way to "ignore" the click event on button if validation not passed?
I tried to use a boolean flag which indicate the validation result and check the flag when perform the action for button, but I do not think it is a good approach. As I know there's an event dispatcher thread in Swing which deal with the events, is it possible I can cancel the events from here?
Below is a piece of code which explain the question:
public class SimpleDemo
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new FlowLayout());
frame.setContentPane(content);
final JTextField textField = new JTextField(10);
textField.addFocusListener(new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
String text = textField.getText();
// do some validation here, if not validated
// do not trigger the event on button.
if ("".equals(text))
{
System.out.print("please input a text!");
}
}
});
content.add(textField);
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// action performed for button
String text = textField.getText();
System.out.println(text);
}
});
content.add(button);
frame.setVisible(true);
frame.pack();
}
}
I faces similar issue while working on an application. I solved it like below
I created a abstract class ApplicationFrame which every frame in the application extends
public abstract class ApplicationFrame extends JFrame implements ActionListener {
#Override
final public void actionPerformed(ActionEvent event) {
if(validateInput()){
performAction(event);
}
}
/*
* Sub class should override this method to receive any action
*/
protected void performAction(ActionEvent event) {};
/*
* Sub class should override this method to perform validation
*/
abstract protected boolean validateInput();
}
All Frames will now extend this base frame, as below:
public class Frame1 extends ApplicationFrame{
#Override
protected void performAction(ActionEvent event) {
// perform action
}
#Override
protected boolean validateInput() {
// return true or false depending upon the validation results
}
// if you want to add Action Listener, you need to add like this:
btnSomeButton.addActionListener(this);
}
If you need to handle Focus events, you can make ApplicationFrame or the base frame implement FocusListener.
This is my custom implementation to solve the problem, hope this helps.
Make the button disabled on start-up
Upon lost focus, validate the text & enable button only when the input passes validation.
Upon start of text change, disable the button
It's always makes sense to make ui to communicate with user. So you can show "please input a text" as the default text of the textField when nothing is entered by user.
Here is the code for such custom textField:
public class TextFieldWithDefaultText extends JTextField implements FocusListener{
private final String hint;
public TextFieldWithDefaultText (String $text)
{
super($text);
this.hint = $text;
addFocusListener(this);
}
#Override
public void focusGained (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText("");
}
}
#Override
public void focusLost (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText(hint);
}
}
#Override
public String getText ()
{
String typed = super.getText();
return typed.equals(hint) ? "" : typed;
}
}
Write the acttionListerner for your button like this:
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(!textField.getText().isEmpty())
System.out.println(textField.getText());
}
});
And ur textField implementation should be :
final TextFieldWithDefaultText textField = new TextFieldWithDefaultText ("please input a text");
Hope this helps :)
I'm building an Eclipse application and I'm trying to make a shortcut for launching an action when pressing F5, and make that the default action when that Tab/ViewPart has the focus.
I have read that this is not possible, or very complex. Is there any simple/straight way of doing it?
I tried with:
Display.getCurrent().addFilter(...)
this.addKeyListener(new KeyAdapter() {...})
...
Making this in the constructor is my best:
this.getShell().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.keyCode == SWT.F5) {
//doAnything()
}
}
});
And this doesn't work when loaded, but if I switch from this to another View/Tab starts to work. But it works too when others have focus (which I don't want).
Is there anyway of making this work at the start, and only when the focus is in the View?
You should define work in a handler & then should use key bindings as given in this example. You can find a good example here. Hope it solves your need.
You should look at RetargetableActions. I think that's Eclipse way of doing it:
You need to look at extensions org.eclipse.ui.bindings and org.eclipse.ui.contexts.
Define a command and its handler
Define a binding for the command
define context (cxtId)
associate context with command so that command is available only when context is active
Activate context when you open the view or form.
If you get the listener of the events of the component it will listen on the events. And if the event occur for this component it will be notified.
To add listener of the key event on the ViewPart we should create the control which could be able listen on the event.
public class SampleView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "views.SampleView";
private Composite mycomposite;
public void createPartControl(Composite parent) {
mycomposite = new Composite(parent, SWT.FILL);
//then add listener
mycomposite.addKeyListener(keyListener);
}
private KeyListener keyListener = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
showMessage("key pressed: "+ e.keyCode);
}
};
//the rest of focusing and handle event
private void showMessage(String message) {
MessageDialog.openInformation(
mycomposite.getShell(),
"Sample View",
message);
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
mycomposite.setFocus();
}
}
//the end
I know that there is another way to do this, but I prefer to see if anyone has an answer for doing it this way. The original way is to get the integer return value after calling the ShowDialog() function; I want to grab it from within the Event (shown below) itself. I've thrown some code in there to check if a file is selected, but I need to check whether the approval button (the OK button) has been selected before it gets there. Does anyone know how to check which button is pressed in a FileChooser dialog, using a setup like below?
Here's my code:
private void FileChooser_OpenMouseClicked(java.awt.event.MouseEvent evt) {
if(!FileChooser_Open.getSelectedFile().equals(null))
{
}
}
Original method:
//In response to a button click:
int returnVal = fc.showOpenDialog(aComponent);
The difference is that the original method gets a return value when the dialog box is closed, while in this method, I do not know of a way to get that return value (I believe the box has already closed, but there is nothing there to catch the return value). I apologize if I do not appear to be making a lot of sense.
edit: More information
So this is how I am creating the dialogue (a menu item, "Open" raises an event, which calls the showOpenDialog() method. As you can see, it is not capturing the return value (bear with me). Is it possible then to get the return value or at design a method to figure out whether the OK button is then pressed in the MouseClicked event? I guess I am trying to focus on an event-based programming style, where the code reacts according to the event raised, and grabbing the checking for the OK / approval button click inside the Open Menu event seems a little...disorganized from my perspective. Perhaps I am too used to C# / WinForm's approach to this problem?
private void MenuItem_OpenActionPerformed(java.awt.event.ActionEvent evt) {
FileChooser_Open.showOpenDialog(this);
}
private void FileChooser_OpenMouseClicked(java.awt.event.MouseEvent evt) {
if(!FileChooser_Open.getSelectedFile().equals(null))
{
}
}
If I understand the question, you might be able to use a JFileChooser#approveSelection() method:
OTN Discussion Forums : How to react on events fired by a JFileChooser?
java - JFileChooser with confirmation dialog - Stack Overflow
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class ApproveSelectionDemo {
public JComponent makeUI() {
final JPanel p = new JPanel();
final JFileChooser fileChooser = new JFileChooser() {
#Override public void approveSelection() {
if(!getSelectedFile().exists()) {
int returnVal = JOptionPane.showConfirmDialog(
this, "message", "title", JOptionPane.YES_NO_OPTION);
if(returnVal!=JOptionPane.YES_OPTION) {
return;
}
}
super.approveSelection();
}
};
p.add(new JButton(new AbstractAction("Open") {
#Override public void actionPerformed(ActionEvent e) {
int retvalue = fileChooser.showOpenDialog(p);
if(retvalue==JFileChooser.APPROVE_OPTION) {
System.out.println(fileChooser.getSelectedFile());
}
}
}));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new ApproveSelectionDemo().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}