Can't get keyboard focus on JTextField in JDialog - java

I have a Swing app that has a JDialog pop up and ask for a username and password. I thought it'd be good to have the keyboard focus already in the username field, but everything I've tried so far doesn't work (even though one solution I tried works for a different text field in the program), so....I need some help. Here's my code:
//JTextField usernameField = ...
JDialog dialog = pane.createDialog("Password:");
dialog.setVisible(true);
//Take 1
usernameField.requestFocusInWindow();
//Take 2
dialog.addWindowFocusListener(new WindowAdapter() {
public void windowGainedFocus(WindowEvent e) {
usernameField.requestFocusInWindow();
}
});
//Take 3 - This is what I used elsewhere quite successfully
dialog.addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent e ) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
usernameField.requestFocusInWindow();
}
});
}
});
For what it's worth, this is with Linux / X11 / Openbox. And when I use GTK, I have to press Tab once to select the appropriate field, but when I use Metal, I have to press it twice.
Thanks in advance.

See Dialog Focus for tips & strategies.

Related

Popup keyboard in java

for a embedded kiosk system i need a popup keyboard, something like in every android smartphone. If someone click on a textfield a popup keyboard will show, if someone click a other point as the textfield, the popupkeyboard will hide.
I already realize the popupkeyboard:
public Keyboard() {
super("pop-up keyboard");
setDefaultCloseOperation(EXIT_ON_CLOSE);
txt = new JTextField(20);
keyboard = new PopUpKeyboard(txt);
txt.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Point p = txt.getLocationOnScreen();
p.y += 30;
keyboard.setLocation(p);
keyboard.setVisible(true);
}
});
If i click on the textfield the keyboard open. But now i have no idea how to hide the keyboard if the focus on the textfield is lost. I have tried this, but it haven't worked:
txt.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
//
}
#Override
public void focusLost(FocusEvent e) {
keyboard.setVisible(false);
}
});
Have someone a idea how to hide the keyboard?
Thanks for your help!
I already realize the popupkeyboard:
The popup keyboard should be an undecorated JDialog. Focus would be on the dialog while you are pressing keys.
if someone click a other point as the textfield, the popupkeyboard will hide.
Then you can add a WindowListener to the dialog and handle the windowDeactivated event and close the dialog.

Opening JXDatePicker on gaining focus

I am trying to extend JXDatePicker so that it opens up when it gains focus.
Have searched for suggest that I understand without success.
Is there an elegant way of doing this?
Astonishingly, it's not really possible :-(
For once, the JXDatePicker itself has no api to show/hide the popup (only BasicDatePickerUI has). Plus the ui delegate has some internal magic (read: hacks ... cough) that makes a FocusListener even worse to handle than usually in compound components.
A snippet to play with:
final JXDatePicker picker = new JXDatePicker();
FocusListener l = new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
// no api on the picker, need to use the ui delegate
BasicDatePickerUI pickerUI = (BasicDatePickerUI) picker.getUI();
if (!pickerUI.isPopupVisible()) {
pickerUI.toggleShowPopup();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// opening the popup moves the focus to ... ?
// need to grab it back onto the editor
picker.getEditor().requestFocusInWindow();
}
});
}
#Override
public void focusLost(FocusEvent e) {
}
};
// need to register the listener on the editor
picker.getEditor().addFocusListener(l);
JComponent content = new JPanel();
content.add(new JButton("dummy"));
content.add(picker);
Not really satisfying, as automatic closing of the popup on transfering the focus out again doesn't work reliably, needs two tabs (don't know why)
I had the same problem.
This worked for me:
jXDatePicker.getEditor().addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
BasicDatePickerUI pickerUI = (BasicDatePickerUI) jXDatePicker.getUI();
if (!pickerUI.isPopupVisible() && e.getOppositeComponent() != getRootPane() && e.getOppositeComponent() != jXDatePicker.getMonthView()) {
pickerUI.toggleShowPopup();
}
}
#Override
public void focusLost(FocusEvent e) {}
});
This piece of code is used to avoid focus issues:
e.getOppositeComponent() != getRootPane()

Handle barcode scan in Java

I want to have my application react to barcodes being scanned to trigger button presses. For example the user could scan the ((PRINT)) barcode to activate the print button.
The barcodes will just be treated as if the user had entered some text. I am not sure if the scanners will be set up to append an enter or a tab or nothing on the end, so I don't want to make an assumption on that basis.
The application is a Java/Swing application.
I have looked at keybindings/action maps and the like, but they seem to be focussed on key chords/single key entries. I need it to not trigger the binding until the whole string is entered.
The tricky bit is that this should work wherever the user is focussed in the screen. They will not normally enter ( characters, so some kind of trigger on that might work. I am not sure how to handle the rest of the string though.
Edit: Apologies if it wasn't clear in the question, but the barcode scanner isn't anything "special" to the application, it's just like another keyboard. So the user won't be typing in (print), but effectively that is what the barcode scanner will be doing, if that makes sense.
So there are only two ways to trigger the print: pressing the button, or "typing" the string (print). The tricky part is that the user can be focussed anywhere on the application. I am only worried about if the application has focus as a whole, not which field the user is focussed on. The particular screen in question has checkbuttons and left/right selectors on it, so the user isn't necessarily going to be typing in to a field.
I had a problem just like yours, and created a project (currently proof of concept with some problems) to make barcode handling in swing easier.
It is based in the fact that the barcode readers emulate a keyboard but differently to humans they "type" with a constant timing. It will basically allow you to listen to "barcode read" events.
The project location: https://github.com/hablutzel1/swingbarcodelistener
Demo usage:
public class SimpleTest extends JFrame {
public SimpleTest() throws HeadlessException {
// start of listening for barcode events
Toolkit.getDefaultToolkit().addAWTEventListener(new BarcodeAwareAWTEventListener(new BarcodeCapturedListener() {
#Override
public void barcodeCaptured(String barcode) {
JOptionPane.showMessageDialog(SimpleTest.this, "barcode captured: " + barcode);
}
}), AWTEvent.KEY_EVENT_MASK);
// end of listening for barcode events
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JLabel("Capture barcode demo"));
getContentPane().add(new JTextField(25));
}
public static void main(String[] args) {
SimpleTest simpleTest = new SimpleTest();
simpleTest.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
simpleTest.setVisible(true);
simpleTest.pack();
}
}
It has some problems now but as a starting point I think it is ok, if you have time to improve it it would be great.
Correct me if I missunderstood, but it sounds like you have a barcode-scanner which will enter text into a field. But you want to be alerted when the text in the field equals something (so an action can take place) regardless of how it was entered (by barcode scanner or key press).
I'd recommend using a DocumentListener to alert you of changes to the text field - this should work with both of your requirements.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TempProject extends Box{
public TempProject(){
super(BoxLayout.Y_AXIS);
final JTextArea ta = new JTextArea();
ta.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void changedUpdate(DocumentEvent arg0) {
doSomething();
}
#Override
public void insertUpdate(DocumentEvent arg0) {
doSomething();
}
#Override
public void removeUpdate(DocumentEvent arg0) {
doSomething();
}
public void doSomething(){
if(ta.getText().equalsIgnoreCase("print")){
System.out.println("Printing...");
//Need to clear text in a separate swing thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
ta.setText("");
}});
}
}
});
add(ta);
}
public static void main(String args[])
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setContentPane(new TempProject());
frame.setPreferredSize(new Dimension(500, 400));
frame.pack();
frame.setVisible(true);
}
});
}
}
I do not completely understand the question, and this is a bit too long to put in a comment. As far as I understood it, you have a Swing application and a bar-code scanner which has 3 different ways to trigger the same operation
User enters some text ("print") in the UI and this triggers the print action
The UI has a print button which can be pressed by the user and this triggers the print action
User can scan a "print" bar code and this triggers the print action
The part I do not understand is why the scanning of the bar code, which should trigger the print action, has anything to do with the UI-part where the user can input text.
I assume the scanning of the barcodes happens on another thread then the Event Dispatch Thread. Once you scanned a barcode and parsed it, you need to trigger the "print" action. You can do this directly without bothering going through the UI.
This is my approach. It's working. Just get the miliseconds for ensure doesn't read twice. Just add a Key Listener (implemented in the same JFrame).
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
logger().info("keytyped" + e.getKeyChar() + " code "+e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
logger().info("all keys " + keyspressed);
return;
}
// will not last more than a second...
if (keyspressed == null || System.currentTimeMillis() - currentTimeMillis > 1000) {
keyspressed = e.getKeyChar()+"";
currentTimeMillis = System.currentTimeMillis();
} else {
keyspressed = keyspressed + e.getKeyChar();
currentTimeMillis = System.currentTimeMillis();
}
}
private String keyspressed = null;
private long currentTimeMillis = System.currentTimeMillis();

How to trap the Window minimizing event?

I want to create a JFrame instance and on the click of its minimize button, I would like to hide it to the System Tray which is usually the taskbar of windows.
I'd come to know that by using SystemTray class in java.awt package I can do so but neither I'm getting any tutorial on it nor any working program example.
I'd asked this question here to either get the link to tutorial site for SystemTray class or if any body knows how to trap the window minimizing event, a working example.
The WindowListener interface and JFrame's addWindowListener() method should help you determine when the frame has been minimised.
This will trap the window minimized event and will create a tray icon. It will also remove the window from the taskbar and it will add a listener on the tray icon so that a mouseclick would restore the window. The code is a bit scrappy but should be good enough for your learning purposes:
public class Qwe extends JFrame {
public static void main(String[] args) {
final Qwe qwe = new Qwe();
qwe.addWindowStateListener(new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
if (e.getNewState() == ICONIFIED) {
try {
final TrayIcon trayIcon = new TrayIcon(new ImageIcon("/usr/share/icons/gnome/16x16/emotes/face-plain.png").getImage());
trayIcon.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
qwe.setVisible(true);
SystemTray.getSystemTray().remove(trayIcon);
}
});
SystemTray.getSystemTray().add(trayIcon);
qwe.setVisible(false);
} catch (AWTException e1) {
e1.printStackTrace();
}
}
}
});
qwe.setSize(200, 200);
qwe.setVisible(true);
}
}
best way would be create follows
1) SystemTray
2) add JPopopMenu to the SystemTray's Icon
3) set DefaultCloseOperation for TopLevelContainer (in your case JFrame)
by using WindowListener setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
in other cases always works setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
notice don't forget declare System.exit(1) to the SystemTray's JpopupMenu, from JMenuItem or another Action/Event, because in this form currenet JVM never gone from Native OS until PC power-off or restart
private void windowStateChanged(java.awt.event.WindowEvent evt) {
// Use getExtendedstate here.
}
WindowStateListener docs
Frame.getExtendedState() docs
frame.addWindowListener(new WindowAdapter() {#Override
public void windowIconified(WindowEvent e) {}
});

How do I close a JDialog and have the Window Event Listeners be notified?

Is there a way to close a JDialog through code such that the Window event listeners will still be notified? I've tried just setting visible to false and disposing, but neither seem to do it.
Closing a window (with dispose()) and hiding it (with setVisible(false)) are different operations, and produce different events -- and closing it from the operating system is yet another different operation that produces yet a different event.
All three will produce windowDeactivated to tell you the window's lost focus, but dispose() will then produce windowClosed, while closing from the OS will first produce windowClosing. If you want to handle both of these the same way, you can set the window to be disposed when closed:
window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
In general, setVisible(false) implies that you might want to use the window again, so it doesn't post any window events (apart from windowDeactivated). If you want to detect the hiding of a window, you need to use a ComponentListener;
window.addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent e) {
System.out.println("componentHidden()");
}
})
Note though that this will pretty much only work for explicit setVisible() calls. If you need to detect hiding more generally, you can use a HierarchyListener, but it's probably more trouble than it's worth.
window.addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
System.out.println("valid: " + window.isValid());
System.out.println("showing: " + window.isShowing());
}
});
Note that when you dispose a window you'll get a couple of HierarchyEvents, first for hiding and then for invalidation, but when you hide it with setVisible() it's still valid, so you won't get the invalidation.
I don't seem to have your problem. When I use the code below windowDeactivated() is called for either setVisible( false ) or dispose() and windowClosed() is also called for dispose().
ClosingDialog.java:
public class ClosingDialog extends JDialog {
public ClosingDialog(Frame owner, String title, boolean modal) {
super(owner, title, modal);
JPanel contentPanel = (JPanel) this.getContentPane();
JButton setVisButton = new JButton("setVisible( false )");
setVisButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ClosingDialog.this.setVisible(false);
}
});
JButton disposeButton = new JButton("dispose()");
disposeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ClosingDialog.this.dispose();
}
});
contentPanel.setLayout(new FlowLayout());
contentPanel.add(setVisButton);
contentPanel.add(disposeButton);
this.addWindowListener(new WindowListener() {
public void windowActivated(WindowEvent e) {
System.out.println("windowActivated");
}
public void windowClosed(WindowEvent e) {
System.out.println("windowClosed");
}
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
}
public void windowDeactivated(WindowEvent e) {
System.out.println("windowDeactivated");
}
public void windowDeiconified(WindowEvent e) {
System.out.println("windowDeiconified");
}
public void windowIconified(WindowEvent e) {
System.out.println("windowIconified");
}
public void windowOpened(WindowEvent e) {
System.out.println("windowOpened");
}
});
this.setSize(300, 300);
}
}
Dispatch a windowClosing event to the Window. Check out the ExitAction example from the Closing an Application entry.
Untested suggestion:
Have you tried getWindowListeners() and then iterating around to fire windowClosed() to each of the WindowListeners?
EDIT: the above suggestion is wrong. Keeping it for posterity.
I'm afraid calling dialog.dispose() works fine for me in my simple example.
I wanted to fire a windowClosing event from the code (just as if the user clicked the X), because I have an extra close button in the JDialog and want the same WindowListener (that I implemented using a WindowAdapter) to be run when the X is clicked and when the button is clicked. Running dispose() only fires windowClosed, not windowClosing, and I want a message to appear before the window is closed, for confirmation. I also didn't manage to fire windowClosing via JDialog's method processWindowEvent since it is protected.
Here is how I got it working though:
WindowAdapter adapter = (WindowAdapter)jdialog.getWindowListeners()[0];
adapter.windowClosing(new WindowEvent((Window)jdialog, WindowEvent.WINDOW_CLOSING));
Hope that helps someone.

Categories

Resources