使用 GridBagLayout 为 JFrame 自定义 FocusTraversalPolicy

发布于 2024-12-09 10:17:15 字数 4126 浏览 0 评论 0 原文

我有一个包含四个组件的 JFrame:三个 JPanel 和一个 JTabbedPane。两个面板具有可选组件,大约位于 BorderLayout.NORTH 和 EAST,而 JTabbedPane 大约位于 CENTER。 TabbedPane 的选项卡在窗格底部对齐。我说大约是因为实际布局是使用 GridBagLayout 完成的(抱歉!)。

目前,焦点遍历周期是这样的:

Current Cycle:  
   1) North JPanel  
   2) East JPanel  
   3) JTabbedPane selected tab  
   4) JTabbedPane selected tab content  

但是,我希望它是:

Desired Cycle:  
   1) North JPanel  
   2) JTabbedPane selected tab content  
   3) JTabbedPane selected tab  
   4) East JPanel  

我已经尝试了 Java Focus Guide 不幸的是:我无法让光标进入选项卡面板内容。

然后,我考虑扩展/更改其他 FocusTraversalPolicy 类,但也一无所获。

我相当确定问题是当前的 FocusTraversalPolicy 使用屏幕上的组件位置来确定布局周期。从技术上讲,侧面板在屏幕上的位置高于中心选项卡式窗格。但我真的很想改变这一点。还有其他人遇到过这个/有什么见解吗?谢谢!!

编辑:

这是一个带有正确布局代码的 SSCCE,演示了该问题。请注意:问题不在于布局,因为布局必须保持不变。

package SO;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

public class ssccee7729709{
    JPanel north;
    JPanel north2;
    JPanel east;
    JTabbedPane center;
    JFrame content;

    void initialize() {
        north = new JPanel(new FlowLayout()) {
            {
                this.setBackground(Color.CYAN);
            }
        };
        north.add(new JLabel("Title panel"));

        north2 = new JPanel(new FlowLayout()) {
            {
                this.setBackground(Color.RED);
            }
        };
        north2.add(new JLabel("north2 Panel"));
        north2.add(new JTextField(4));
        north2.add(new JTextField(4));

        east = new JPanel(new GridLayout(3,1)) {
            {
                this.setBackground(Color.BLUE);
            }
        };
        east.add(new JButton("b1"));
        east.add(new JButton("b2"));

        center = new JTabbedPane(JTabbedPane.BOTTOM, JTabbedPane.WRAP_TAB_LAYOUT);
        for (int i = 0; i < 2; i++) {
            JPanel panel = new JPanel(new GridLayout(4,1));
            panel.add(new JLabel("Panel " + i));
            panel.add(new JTextField(6));
            panel.add(new JTextField(6));
            panel.add(new JTextField(6));
            center.addTab("Tab " + i, panel);   
        }

        content = new JFrame();
        content.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        content.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        {
            gbc.fill = GridBagConstraints.BOTH;
            gbc.gridwidth = 4;
            gbc.weightx = 1;
            content.add(north, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.anchor = GridBagConstraints.PAGE_START;
            gbc.gridwidth = 1;
            gbc.weightx = 1;
            // gbc.weighty = .1;
            gbc.gridy = 1;
            gbc.gridx = 1;
            content.add(north2, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.gridwidth = GridBagConstraints.RELATIVE;
            gbc.gridheight = GridBagConstraints.RELATIVE;
            gbc.weighty = 1;
            gbc.gridy = 2;
            content.add(center, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.VERTICAL;
            gbc.anchor = GridBagConstraints.SOUTHEAST;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.gridx = 3;
            gbc.gridheight = 4;
            content.add(east, gbc);
        }

      content.setVisible(true);
      content.pack();
    }

    public static void main(String args[]) {
        ssccee7729709 so = new ssccee7729709();
        so.initialize();
    }

}

I have a JFrame with four components: three JPanels and a JTabbedPane. Two panels have selectable components and are located approximately in BorderLayout.NORTH and EAST, while the JTabbedPane sits approximately in CENTER. The tabs of the TabbedPane are aligned on the bottom of the pane. I say approximately because the actual layout is done with a GridBagLayout (sorry!).

Currently, the focus traversal cycle goes like this:

Current Cycle:  
   1) North JPanel  
   2) East JPanel  
   3) JTabbedPane selected tab  
   4) JTabbedPane selected tab content  

However, I'd like it to be:

Desired Cycle:  
   1) North JPanel  
   2) JTabbedPane selected tab content  
   3) JTabbedPane selected tab  
   4) East JPanel  

I have tried the Vector-based FocusTraversalPolicy given by the Java Focus Guide with no luck: I couldn't get the cursor to go down into the tab panel contents.

I then looked into extending/changing the other FocusTraversalPolicy classes out there, but got nowhere with that either.

I'm fairly sure the issue is the current FocusTraversalPolicy uses component location on screen to determine the layout cycle. Technically the side panel is higher on the screen than the center tabbed pane. I'd really like to change this though. Anybody else run into this/have any insight? Thanks!!

EDIT:

Here's an SSCCE with proper layout code demonstrating the problem. Just a note: the issue is NOT the layout, as that has to stay the same.

package SO;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

public class ssccee7729709{
    JPanel north;
    JPanel north2;
    JPanel east;
    JTabbedPane center;
    JFrame content;

    void initialize() {
        north = new JPanel(new FlowLayout()) {
            {
                this.setBackground(Color.CYAN);
            }
        };
        north.add(new JLabel("Title panel"));

        north2 = new JPanel(new FlowLayout()) {
            {
                this.setBackground(Color.RED);
            }
        };
        north2.add(new JLabel("north2 Panel"));
        north2.add(new JTextField(4));
        north2.add(new JTextField(4));

        east = new JPanel(new GridLayout(3,1)) {
            {
                this.setBackground(Color.BLUE);
            }
        };
        east.add(new JButton("b1"));
        east.add(new JButton("b2"));

        center = new JTabbedPane(JTabbedPane.BOTTOM, JTabbedPane.WRAP_TAB_LAYOUT);
        for (int i = 0; i < 2; i++) {
            JPanel panel = new JPanel(new GridLayout(4,1));
            panel.add(new JLabel("Panel " + i));
            panel.add(new JTextField(6));
            panel.add(new JTextField(6));
            panel.add(new JTextField(6));
            center.addTab("Tab " + i, panel);   
        }

        content = new JFrame();
        content.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        content.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        {
            gbc.fill = GridBagConstraints.BOTH;
            gbc.gridwidth = 4;
            gbc.weightx = 1;
            content.add(north, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.anchor = GridBagConstraints.PAGE_START;
            gbc.gridwidth = 1;
            gbc.weightx = 1;
            // gbc.weighty = .1;
            gbc.gridy = 1;
            gbc.gridx = 1;
            content.add(north2, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.gridwidth = GridBagConstraints.RELATIVE;
            gbc.gridheight = GridBagConstraints.RELATIVE;
            gbc.weighty = 1;
            gbc.gridy = 2;
            content.add(center, gbc);
        }
        {
            gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.VERTICAL;
            gbc.anchor = GridBagConstraints.SOUTHEAST;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.gridx = 3;
            gbc.gridheight = 4;
            content.add(east, gbc);
        }

      content.setVisible(true);
      content.pack();
    }

    public static void main(String args[]) {
        ssccee7729709 so = new ssccee7729709();
        so.initialize();
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吹泡泡o 2024-12-16 10:17:15

如果您查看默认策略 LayoutFocusTraversalPolicy 的源代码,它几乎只是扩展了 SortingFocusTraversalPolicy,它需要一个 Comparator

您应该能够提供自己的 Comparator,它是一个内部类,因此可以访问父组件,并通过查看自己及其父组件来提供适当的比较值。

查看 LayoutComparator 这是 LayoutFocusTraveralPolicy 使用的。

If you look at the source for LayoutFocusTraversalPolicy, which is the default policy, it pretty much just extends SortingFocusTraversalPolicy, which takes a Comparator<? extends Component>.

You should be able to provide your own Comparator which is an inner class and so has access to parent components, and provide appropriate comparison values by looking at themselves and their parents.

It probably wouldn't hurt to check out the source to LayoutComparator which is what LayoutFocusTraveralPolicy uses.

暖伴 2024-12-16 10:17:15

克隆 LayoutComparator 后,我必须将以下几行添加到 compare 方法中:

    ...previous code...
    int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b);

    /// added these:
    if (a instanceof EastPanel) {
        if (b instanceof JTabbedPane || b instanceof NorthPanel) {
            return -1;
        }
    }
    if (b instanceof EastPanel) {
        if (a instanceof JTabbedPane || a instanceof NorthPanel) {
            return 1;
        }
    }

    if (horizontal) {
        if (leftToRight) {
    ...more code...

老实说,我不知道这是如何工作的...使用 compare 订购组件的机制对我来说很奇怪......但这有效,所以......万岁魔法!

After cloning LayoutComparator, I had to add the following lines to the compare method:

    ...previous code...
    int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b);

    /// added these:
    if (a instanceof EastPanel) {
        if (b instanceof JTabbedPane || b instanceof NorthPanel) {
            return -1;
        }
    }
    if (b instanceof EastPanel) {
        if (a instanceof JTabbedPane || a instanceof NorthPanel) {
            return 1;
        }
    }

    if (horizontal) {
        if (leftToRight) {
    ...more code...

Honestly I don't know how this works...the mechanism of using compare to order components is strange to me...but this works, so... hooray magic!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文