2017-10-18 89 views
1

我工作的应用程序中使用的结构如下:,错件(在单独的JPanel类)获得焦点

  1. FrmMain(里面有我想补充我的“布局”面板,该面板)
  2. PnlNewCase
  3. PnlNewCaseNotes
  4. (其被添加到PnlNewCase面板之一)(以下简称“布局”,其被设置为接收区特定板面板)
  5. PnlNewPartsSelection我的存在的祸根)

我的想法是投入聚焦于特定的JTextField(tfNom)每当我创建PnlNewPartsSelection一个新的页面时,它被实例化,但每当我试着做那个焦点被设置为另一个JTextField(tfAddressDetails)。

What I want in focus (in blue) vs what gets focus (in red)

我试着调试整个事情,一直无法查明,需要做的事情。我也尝试使用更简单的代码来重现问题,但在这种情况下它可以工作。两者之间的唯一显着的区别是,简化代码只由一个JFrame和JPanel的,而更复杂的代码包含:JFrame的 - > JTabbedPane中 - >的JPanel - > JPanel的,所以我不知道这是不是挂JTabedPane以某种方式将JPanel或JPanel与JPanel交互。

下面是我正在使用的方法的概要,我希望能帮助别人弄清楚发生了什么。

的JFrame FrMain:

private void btnNewRepActionPerformed(java.awt.event.ActionEvent evt) { 
    tabs.addTab("R" + tabNo++, p); 
    tabs.setSelectedIndex(tabNo); 
} 

的JPanel PnlNewCase:

public PnlNewCase(boolean isNewRep) { 
    initComponents(); 
    checkRepStatus(isNewRep); 
} 


private void checkRepStatus(boolean isNewRep) { 
    if (isNewRep) { 
     btnNewNote.setVisible(false); 
     PnlNewCaseNotes p1 = new PnlNewCaseNotes(); 
     pnlNotes.add(p1); 
     PnlNewPartsSelection p2 = new PnlNewPartsSelection();  
     JTextField t = p2.getTfNom(); 
     pnlPartsCustomer.add(p2); 
     t.requestFocusInWindow(); 
     validate(); 
    } 
} 

的JPanel PnlNewCaseNotes:

public PnlNewCaseNotes() { 
    initComponents(); 
} 

的JPanel PnlNewPartsSelection:

public PnlNewPartsSelection() { 
    initComponents(); 
} 

/* A bunch of method calls to add place holders */ 

public JTextField getTfNom() { 
    return tfNom; 
} 

我也可以发表对每一类的代码如果需要的话(我只是觉得这应该是足够了)。

期待您的意见:)

+0

这是不可能的'PnlNewCase'是有物理屏幕上,当你调用't.requestFocusInWindow()' ,这使得通话静音。您需要首先在用户界面上实现“PnlNewCase”,然后重定向控件。也许在你调用'add'(和'revalidate' /'repaint')后,调用'requestFocusInWindow' ...你可能会发现你需要使用'SwingUtilities.invokeLater'来使它工作,虽然 – MadProgrammer

回答

2

退一步,穿过您的代码。让我们假设你正在做的事情一样

add(new PnlNewCase(true)); 

如果你走过的代码,你会发现它调用:

  • PnlNewCase构造函数(分配默认值实例字段)
    • initComponents
      • checkRepStatus。在这一点上,你开始建立你的代码,并呼吁t.requestFocusInWindow
  • 呼叫add传球PnlNewCase新实例到容器

而且这里位于核心问题。当您拨打t.requestFocusInWindow时,组件本身或其所连接的容器都不会被添加到UI中,因此无法为该字段提供焦点。

而是将组件添加到UI,然后请求焦点到该字段。因为方式的框架,你可能会发现你还需要使用SwingUtilities.invokeLater,使重点工作

也许做这样的事情......

public class PnlNewCase extends JPanel { 

     private PnlNewPartsSelection p2; 

     public PnlNewCase(boolean isNewRep) { 
      //... 
     } 

     private void checkRepStatus(boolean isNewRep) { 
      if (isNewRep) { 
       //... 
       p2 = new PnlNewPartsSelection(); 
       //... 
       //t.requestFocusInWindow(); 
      } 
     } 

     public void focusPrimaryField() { 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        p2.getTfNom().requestFocusInWindow(); 
       } 
      }); 
     } 
    } 

然后,你可以简单地做这样的事情?

PnlNewCase newCase = new PnlNewCase(true); 
add(newCase); 
revalidate(); 
repaint(); 
newCase.focusPrimaryField() 

作为一般的想法。

你可能也想看看How to Use the Focus Subsystem,以获得更好的理解,也许一些更多的想法

+0

感谢您花时间回答我的问题题 !你已经帮助我了解了这个问题,我为此感谢你。另一方面,我无法理解最后一段代码如何发挥作用。特别是newCase.focusPrimaryField()调用。 从我所了解的情况来看,您已将focusPrimaryField()方法添加到PnlNewCase类,但我没有得到最后一个片段的位置。 Frostain? FrmMain? – Thery

+0

这个想法是延迟请求焦点,直到你可以更好地保证UI在屏幕上成立为止 – MadProgrammer

+0

这里的重要部分是建立的UI(组件被添加,如果可能的话,在屏幕上实现)。您可以在'setVisible'之前将'callPrimaryField'添加到'setVisible'和它的“might”上,但如果可能的话在'setVisible'调用后添加它可能会更安全 – MadProgrammer