I have a table that has a JDialog for add new record, When i click to add Button and want to add a new record and JDialog opened, I close JDialog window and it returns null for my all columns of my table rows.
This is my JDialog constructor:
public class AddBookDialog extends JDialog implements ActionListener {
public AddBookDialog(JFrame owner) {
super(owner, "Add New Book", true);
initComponents();
saveBtn.addActionListener(this);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == cancelBtn) dispose();
else if (e.getSource() == saveBtn) saveAction();
}
}
public void saveAction() {
if (nameTf.getText().trim().length() != 0) {
if (!haveDigit(nameTf.getText().trim())) setBookName(nameTf.getText().trim());
else {
JOptionPane.showMessageDialog(null, "Book Name have digit");
return;
}
} else {
JOptionPane.showMessageDialog(null, "Enter Book Name");
return;
}
if (isbnTf.getText().trim().length() != 0) {
if (haveSpace(isbnTf.getText().trim()) || haveLetter(isbnTf.getText().trim())) {
JOptionPane.showMessageDialog(null, "Enter Correct ISBN");
return;
}
setIsbn(isbnTf.getText().trim());
} else {
JOptionPane.showMessageDialog(null, "Enter Book ISBN");
return;
}
setBorrowStatus("No");
setDate(dateGenerate());
dispose();
}
I try to control this problem in my table GUI class:
public class BookPage_Admin extends JFrame implements ActionListener {
...
public void addAction() {
AddBookDialog dialog = new AddBookDialog(this);
if (dialog.getBookName() != null && dialog.getIsbn() != null && dialog.getBorrowStatus() != null &&
dialog.getDate() != null) {
Object[] added = new Object[]{dialog.getBookID(), dialog.getBookName(), dialog.getIsbn(), dialog.getBorrowStatus(), dialog.getDate()};
model.addRow(added);
}
}
}
But still when i close it, it returns null for my row.
How to prevent returning null when close it?
Just in case if no one will answer you:
When you initiate Dialog, aka AddBookDialog dialog = new AddBookDialog(this); you can override ActionListener on the Frame side like:
AddBookDialog dialog = new AddBookDialog(this);
dialog.setModal(true);
dialog.getSaveBtn().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object[] added = new Object[]{dialog.getBookID(), dialog.getBookName(), dialog.getIsbn(), dialog.getBorrowStatus(), dialog.getDate()};
model.addRow(added);
}
});
// importent set visible after ActionListener!!
dialog.setVisible(true);
Hope it will help,
Related
I've been practicing creating a simple registration form GUI and lately I've discovered about Focus Listener. I've implemented it to my program in order to further refine it and somehow I made it work. While it does indeed work how I intended it to be, my next goal is to instead of allowing users to automatically input in the JTextField, I want them to be able to manually click in and out of the Text Field as they please. The problem is I have a hard time thinking on how can implement this.
currently this is my code:
package com.main;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class RegisterScreen extends JFrame implements ActionListener, FocusListener{
JLabel lblCreateUser, lblCreatePassword, lblHeader;
JTextField txtNewUsername, txtNewPassword;
JButton btnCreateAccount, btnReturnBack;
public RegisterScreen(){
super("Create new User");
setLayout(null);
lblCreateUser = new JLabel("Please enter your Email Address");
lblCreatePassword = new JLabel("Please enter your Password");
lblHeader = new JLabel("Create new account");
txtNewUsername = new JTextField("Username");
txtNewPassword = new JTextField("Password");
btnCreateAccount = new JButton("Create account");
btnReturnBack = new JButton("Back");
lblHeader.setBounds(130, 50, 300,40);
lblCreateUser.setBounds(50,115, 300,40);
lblCreatePassword.setBounds(50, 200, 300, 40);
txtNewUsername.setBounds(50, 150, 300, 40);
txtNewPassword.setBounds(50, 230, 300, 40);
btnCreateAccount.setBounds(50, 280,125, 40);
btnReturnBack.setBounds(223, 280,125, 40);
btnReturnBack.addActionListener(this);
btnCreateAccount.addActionListener(this);
txtNewUsername.addFocusListener(this);
txtNewPassword.addFocusListener(this);
add(lblHeader);
add(lblCreateUser);
add(txtNewUsername);
add(lblCreatePassword);
add(txtNewPassword);
add(btnCreateAccount);
add(btnReturnBack);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent exit){
System.exit(0);
}
});
setSize(400,600);
setVisible(true);
setResizable(false);
}
public static void main (String []args){
RegisterScreen register = new RegisterScreen();
}
public void actionPerformed(ActionEvent e) {
File user = new File("Usernames.txt");
File pass = new File("Passwords.txt");
if (e.getSource() == btnCreateAccount) {
try (BufferedWriter addUser = new BufferedWriter(new FileWriter(user, true)); BufferedWriter addPass = new BufferedWriter(new FileWriter(pass, true))) {
if(txtNewUsername.getText().isEmpty() && txtNewPassword.getText().isEmpty()){
JOptionPane.showMessageDialog(null, "Username or Password must not be blank", "Error", 0);
}
else{
addUser.write(txtNewUsername.getText());
addUser.newLine();
addPass.write(txtNewPassword.getText());
addPass.newLine();
JOptionPane.showMessageDialog(null, "Account Successfully Created", "Success", JOptionPane.INFORMATION_MESSAGE);
}
}
catch (IOException exp) {
JOptionPane.showMessageDialog(this, "Account creation failed", "Error", JOptionPane.ERROR_MESSAGE);
}
}
else if(e.getSource() == btnReturnBack){
LoginScreen login = new LoginScreen();
dispose();
}
}
public void focusGained(FocusEvent e) {
if (e.getSource() == txtNewUsername){
txtNewUsername.setText("");
}
if (e.getSource() == txtNewPassword){
txtNewPassword.setText("");
}
}
public void focusLost(FocusEvent e) {
if (e.getSource() == txtNewUsername){
txtNewUsername.setText("Username");
}
if (e.getSource() == txtNewPassword){
txtNewPassword.setText("Password");
}
}
}
I am still a beginner at programming and sorry if you find my code a bit too long but any help is much appreciated!
Some people (including myself) call this sort of thing a Field Watermark. You need to add some conditions within your if statements contained in both the focusGained and focusLost events, for example:
#Override
public void focusGained(FocusEvent e) {
if (e.getSource() == txtNewUsername && txtNewUsername.getText().equals("Username")) {
txtNewUsername.setForeground(Color.black);
txtNewUsername.setText("");
}
else if (e.getSource() == txtNewPassword && txtNewPassword.getText().equals("Password")) {
txtNewPassword.setForeground(Color.black);
txtNewPassword.setText("");
}
}
#Override
public void focusLost(FocusEvent e) {
if (e.getSource() == txtNewUsername && txtNewUsername.getText().trim().isEmpty()) {
txtNewUsername.setForeground(Color.lightGray);
txtNewUsername.setText("Username");
}
else if (e.getSource() == txtNewPassword && txtNewPassword.getText().trim().isEmpty()) {
txtNewPassword.setForeground(Color.lightGray);
txtNewPassword.setText("Password");
}
}
And during your components initialization:
txtNewUsername = new JTextField("Username");
txtNewUsername.setForeground(Color.lightGray); // ****
txtNewPassword = new JTextField("Password");
txtNewPassword.setForeground(Color.lightGray); // ****
I've learned in this other question that it's possible by overriding the addNotify method, but that's not working. Here's my code:
private boolean accessPasswordFrame(String titleText, String labelText, String errorMessage, int accessType) {
JPasswordField passwordField = new JPasswordField() {
public void addNotify() {
super.addNotify();
requestFocus();
}
};
final JComponent[] inputs = new JComponent[] {
new JLabel(labelText),
passwordField
};
int result = JOptionPane.showConfirmDialog(frame, inputs, titleText, JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
String rootPass = new String(passwordField.getPassword());
if (accessType == ADMIN_TYPE) {
if (rootPass.equals(ROOT_PASSWORD)) {
return true;
} else {
JOptionPane.showMessageDialog(null,
errorMessage, "Erro",
JOptionPane.ERROR_MESSAGE);
}
} else if (accessType == USER_TYPE) {
if (PasswordFrame.getPasswords() != null) {
for (Map.Entry<String, String> e : PasswordFrame.getPasswords().entrySet()) {
if (rootPass.equals(e.getValue())) {
lastUser = e.getKey();
return true;
} else {
JOptionPane.showMessageDialog(null,
errorMessage, "Erro",
JOptionPane.ERROR_MESSAGE);
}
}
} else {
JOptionPane.showMessageDialog(null,
"Usuários cadastrados não existem.", "Erro",
JOptionPane.ERROR_MESSAGE);
}
}
}
return false;
}
Once the JOptionPane appears, the default focus is on the "Ok" button:
And if I just requestFocus() before showing the dialog, it doesn't work as well.
You can add a listener to the component so that the listener is invoked when the option pane is made visible and you can then request focus on the component.
Check out RequestFocusListener class found in Dialog Focus for a reusable solution.
Provided solutions didn't work for me. Following code worked in my case:
passwordField.setFocusable(true);
passwordField.requestFocusInWindow();
passwordField.setCaretPosition(0);
note that JFrame which contains password field has to be visible before calling .requestFocusInWindow()
I have a JList problem. I have listeners for this JList (both mouse and keyboard).
I would like, after you double clicked on one of the option of the list (or pressed Enter), that the JFrame closes. I couldn't find that anywhere. Could you please help me with that?
Here's the class that I use (taken from StackOverflow):
import javax.swing.*;
import java.awt.event.*;
import java.util.Vector;
public class ActionJList extends JList {
ActionListener al;
boolean close=false;
public ActionJList(String[] it){
super(it);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (me.getClickCount() == 2) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
me.consume();
close=true;
}
}
});
addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
ke.consume();
}
}
});
this.setSelectedIndex(0);
}
public ActionJList(Vector it){
super(it);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (me.getClickCount() == 2) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
me.consume();
}
}
});
addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
ke.consume();
}
}
});
this.setSelectedIndex(0);
}
public void addActionListener(ActionListener al){
this.al = al;
}
public boolean getClose(){return close;}
}
You can always use the following snippet:
Window window = SwingUtilities.getWindowAncestor(ActionJList.this);
if (window!=null)
window.setVisible(false);
NB: instead of adding a KeyListener/KeyAdapter to your JList, consider using Swing KeyBindings.
For what it is worth check out List Action for a reusable class that adds the MouseListener and Key Bindings for you. Also, the source of the event is the JList so it makes it easy for you to create your Action using Guillaume's suggestion.
There is no need to make a reference to the JFrame available. The SwingUtilities approach is the better way.
This might be a very simple thing that I'm overlooking, but I just can't seem to figure it out.
I have the following method that updates a JTable:
class TableModel extends AbstractTableModel {
public void updateTable() {
try {
// update table here
...
} catch (NullPointerException npe) {
isOpenDialog = true;
JOptionPane.showMessageDialog(null, "No active shares found on this IP!");
isOpenDialog = false;
}
}
}
However, I don't want isOpenDialog boolean to be set to false until the OK button on the message dialog is pressed, because if a user presses enter it will activate a KeyListener event on a textfield and it triggers that entire block of code again if it's set to false.
Part of the KeyListener code is shown below:
public class KeyReleased implements KeyListener {
...
#Override
public void keyReleased(KeyEvent ke) {
if(txtIPField.getText().matches(IPADDRESS_PATTERN)) {
validIP = true;
} else {
validIP = false;
}
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
if (validIP && !isOpenDialog) {
updateTable();
}
}
}
}
Does JOptionPane.showMessageDialog() have some sort of mechanism that prevents executing the next line until the OK button is pressed? Thank you.
The JOptionPane creates a modal dialog and so the line beyond it will by design not be called until the dialog has been dealt with (either one of the buttons have been pushed or the close menu button has been pressed).
More important, you shouldn't be using a KeyListener for this sort of thing. If you want to have a JTextField listen for press of the enter key, add an ActionListener to it.
An easy work around to suite your needs is the use of showConfirmDialog(...), over showMessageDialog(), this lets you take the input from the user and then proceed likewise. Do have a look at this example program, for clarification :-)
import javax.swing.*;
public class JOptionExample
{
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
int selection = JOptionPane.showConfirmDialog(
null
, "No active shares found on this IP!"
, "Selection : "
, JOptionPane.OK_CANCEL_OPTION
, JOptionPane.INFORMATION_MESSAGE);
System.out.println("I be written" +
" after you close, the JOptionPane");
if (selection == JOptionPane.OK_OPTION)
{
// Code to use when OK is PRESSED.
System.out.println("Selected Option is OK : " + selection);
}
else if (selection == JOptionPane.CANCEL_OPTION)
{
// Code to use when CANCEL is PRESSED.
System.out.println("Selected Option Is CANCEL : " + selection);
}
}
});
}
}
You can get acces to the OK button if you create optionpanel and custom dialog. Here's an example of this kind of implementation:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author OZBORN
*/
public class TestyDialog {
static JFrame okno;
static JPanel panel;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
zrobOkno();
JButton przycisk =new JButton("Dialog");
przycisk.setSize(200,200);
panel.add(przycisk,BorderLayout.CENTER);
panel.setCursor(null);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
przycisk.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
cursorImg, new Point(0, 0), "blank cursor"));
final JOptionPane optionPane = new JOptionPane(
"U can close this dialog\n"
+ "by pressing ok button, close frame button or by clicking outside of the dialog box.\n"
+"Every time there will be action defined in the windowLostFocus function"
+ "Do you understand?",
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION);
System.out.println(optionPane.getComponentCount());
przycisk.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
final JFrame aa=new JFrame();
final JDialog dialog = new JDialog(aa,"Click a button",false);
((JButton)((JPanel)optionPane.getComponents()[1]).getComponent(0)).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
aa.dispose();
}
});
dialog.setContentPane(optionPane);
dialog.pack();
dialog.addWindowFocusListener(new WindowFocusListener() {
#Override
public void windowLostFocus(WindowEvent e) {
System.out.println("Zamykam");
aa.dispose();
}
#Override public void windowGainedFocus(WindowEvent e) {}
});
dialog.setVisible(true);
}
});
}
public static void zrobOkno(){
okno=new JFrame("Testy okno");
okno.setLocationRelativeTo(null);
okno.setSize(200,200);
okno.setPreferredSize(new Dimension(200,200));
okno.setVisible(true);
okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel=new JPanel();
panel.setPreferredSize(new Dimension(200,200));
panel.setLayout(new BorderLayout());
okno.add(panel);
}
}
Try this,
catch(NullPointerException ex){
Thread t = new Thread(new Runnable(){
public void run(){
isOpenDialog = true;
JOptionPane.setMessageDialog(Title,Content);
}
});
t.start();
t.join(); // Join will make the thread wait for t to finish its run method, before
executing the below lines
isOpenDialog = false;
}
In order to have custom button captions in an input dialog, I created the following code:
String key = null;
JTextField txtKey = new JTextField();
int answerKey = JOptionPane.showOptionDialog(this, new Object[] {pleaseEnterTheKey, txtKey}, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, okCaption);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
How can I move the focus (cursor) to the text field as the dialog is displayed?
UPDATE
This does not work for me, I mean the textfield has no focus:
OS: Fedora - Gnome
public class Test {
public static void main(String[] args) {
String key = null;
JTextField txtKey = new JTextField();
txtKey.addAncestorListener(new RequestFocusListener());
int answerKey = JOptionPane.showOptionDialog(null, new Object[]{"Please enter the key:", txtKey}, "Title", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{"OKKK", "CANCELLLL"}, "OKKK");
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
}
}
Dialog Focus shows how you can easily set the focus on any component in a modal dialog.
public static String getPassword(String title) {
JPanel panel = new JPanel();
final JPasswordField passwordField = new JPasswordField(10);
panel.add(new JLabel("Password"));
panel.add(passwordField);
JOptionPane pane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
#Override
public void selectInitialValue() {
passwordField.requestFocusInWindow();
}
};
pane.createDialog(null, title).setVisible(true);
return passwordField.getPassword().length == 0 ? null : new String(passwordField.getPassword());
}
passing null as the last argument is the solution. At least it worked for me.
String key = null;
JTextField txtKey = new JTextField();
int answerKey = JOptionPane.showOptionDialog(this, new Object[] {pleaseEnterTheKey, txtKey}, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, null);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
But even this solution bring another problem:
Focused component and Default component are different. Default component or default button is the button which its onclick fires if you press ENTER KEY.The last argument define the default component which gets the focus too and passing null brings the problem of having no default component!
I solved it for my code this way but I guess it is not a best practice:
String key = null;
final JTextField txtKey = new JTextField();
txtKey.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 10) { //enter key
Container parent = txtKey.getParent();
while (!(parent instanceof JOptionPane)) {
parent = parent.getParent();
}
JOptionPane pane = (JOptionPane) parent;
final JPanel pnlBottom = (JPanel) pane.getComponent(pane.getComponentCount() - 1);
for (int i = 0; i < pnlBottom.getComponents().length; i++) {
Component component = pnlBottom.getComponents()[i];
if (component instanceof JButton) {
final JButton okButton = ((JButton)component);
if (okButton.getText().equalsIgnoreCase(okCaption)) {
ActionListener[] actionListeners = okButton.getActionListeners();
if (actionListeners.length > 0) {
actionListeners[0].actionPerformed(null);
}
}
}
}
}
}
});
I had the same problem with the RequestFocusListener() not working on Linux, after following the discussion on http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574 I found that adding an invokeLater fixed it for now...
public class RequestFocusListener implements AncestorListener
{
public void ancestorAdded(final AncestorEvent e)
{
final AncestorListener al= this;
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JComponent component = (JComponent)e.getComponent();
component.requestFocusInWindow();
component.removeAncestorListener( al );
}
});
}
public void ancestorMoved(AncestorEvent e) {}
public void ancestorRemoved(AncestorEvent e) {}
}
The trick is to (a) use an AncestorListener on the text component to request focus, and when the focus is lost again (given to the default button), ask for focus a second time using a FocusListener on the text component (but don't keep asking for focus after that):
final JPasswordField accessPassword = new JPasswordField();
accessPassword.addAncestorListener( new AncestorListener()
{
#Override
public void ancestorRemoved( final AncestorEvent event )
{
}
#Override
public void ancestorMoved( final AncestorEvent event )
{
}
#Override
public void ancestorAdded( final AncestorEvent event )
{
// Ask for focus (we'll lose it again)
accessPassword.requestFocusInWindow();
}
} );
accessPassword.addFocusListener( new FocusListener()
{
#Override
public void focusGained( final FocusEvent e )
{
}
#Override
public void focusLost( final FocusEvent e )
{
if( isFirstTime )
{
// When we lose focus, ask for it back but only once
accessPassword.requestFocusInWindow();
isFirstTime = false;
}
}
private boolean isFirstTime = true;
} );
Better way to do it: create the JOptionPane using the constructor, override selectInitialValue to set the focus, and then build the dialog using createDialog.
// Replace by the constructor you want
JOptionPane pane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
#Override
public void selectInitialValue() {
textArea.requestFocusInWindow();
}
};
JDialog dialog = pane.createDialog(owner, title);
dialog.setVisible(true);
Try this
String key = null;
JTextField txtKey = new JTextField();
Object[] foo = {pleaseEnterTheKey, txtKey};
int answerKey = JOptionPane.showOptionDialog(this, foo, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, foo[1]);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
I found a solution !
Very primitive, but works.
Just jump to the field by java.awt.Robot using key "Tab".
I've created utils method calls "pressTab(..)"
For example:
GuiUtils.pressTab(1); <------------- // add this method before popup show
int result = JOptionPane.showConfirmDialog(this, inputs, "Text search window", JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION)
{
}
If you should press multiple times on "Tab" to get your Component you can use below method:
GUIUtils.pressTab(3);
Definition:
public static void pressTab(int amountOfClickes)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Robot robot = new Robot();
int i = amountOfClickes;
while (i-- > 0)
{
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
}
}
catch (AWTException e)
{
System.out.println("Failed to use Robot, got exception: " + e.getMessage());
}
}
});
}
If your Component location is dynamic, you can run over the while loop without limitation, but add some focus listener on the component, to stop the loop once arrived to it.