4

我正在用 Java 编写一个聊天客户端,我希望有一个 JDialog 用于所有打开的聊天。所以我决定使用 JTabbedPane,其中一个选项卡代表一个聊天。

我在每个选项卡中都放了一个 JPanel,它只包含一个用于消息历史记录的 JTextPane 和一个用户输入消息的 JTextArea。

为了更好的可用性,我实现了一个功能,当

  1. 一个新的 ChatTab 被打开
  2. 用户在 ChatTab 之间切换(JTabbedPane 的 ChangeListener 触发)

我有一个类ChatWindow,它扩展了 JDialog 并显示了 JTabbedPane。这是我实现 ChangeListener 的地方。

private JTabbedPane chatTabPane;
private List<ChatTab> chatTabs;

public ChatWindow() {
    chatTabs = new ArrayList<ChatTab>();

    JPanel chatWindowPanel = new JPanel(new BorderLayout());

    chatTabPane = new JTabbedPane(JTabbedPane.TOP);
    chatWindowPanel.add(chatTabPane);

    this.add(chatWindowPanel, BorderLayout.CENTER);

    chatTabPane.addChangeListener(new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent arg0) {
            focusInputField();
        }
    });
}

public ChatTab addChatTab(Contact contact) {
    ChatTab newChatTab = new ChatTab();
    chatTabs.add(newChatTab);
    chatTabPane.addTab(contact.toString(), null, newChatTab.getPanel());
    return newChatTab;
}

public void focusInputField() {
    for (ChatTab chatTab : chatTabs) {
        if(chatTab.getPanel() == chatTabPane.getSelectedComponent()) {
            chatTab.focusInputField();
        }
    }
}

public JTabbedPane getChatTabs() {
    return chatTabPane;
}
}

ChatTab类中的focusInputField ()方法如下所示:

public void focusInputField() {
    inputField.requestFocusInWindow();
    inputField.requestFocus();
}

好的,这是更改选项卡时的焦点。除此之外,我还实现了在创建新的聊天选项卡时 JTextArea 的焦点。这是在ChatWindowController类中处理的。当我向ChatWindow类添加新选项卡时,我调用了一个方法setChatVisible() :

public void setChatVisible() {
    if(!chatWindow.isVisible()) {
        chatWindow.setVisible(true);

        chatWindow.focusInputField();
    }
}

所以这是我的问题:当我打开一个新的聊天选项卡时,焦点有效。在大多数情况下,当用户更改选项卡时它也可以工作,但是当我打开多个新的聊天选项卡并第一次在选项卡之间切换时它不会集中。我切换到的选项卡的 JTextArea 没有焦点。但是,当我再次切换时,它一直有效。

有谁知道是什么问题?我真的没主意了。

4

1 回答 1

4

不正确的同步可能会导致间歇性故障。应该批判性地检查几件事:

  • 验证您是否在事件分派线程(EDT) 上构造了所有 GUI 元素。

  • 由于您肯定在使用多个线程,因此请验证所有更新都发生在 EDT 上,例如.

  • 您可以使用在 EDT 上对事件进行排序,如此invokeLater()所示。

  • 更喜欢requestFocusInWindow()requestFocus()但不要同时使用两者。

于 2013-02-17T16:27:21.440 回答