2017-10-18 75 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