-1

我有一个将 TabbedComponent(扩展 JTabbedPane)存储为变量的 Main 类。另一个类 (ToolbarComponent(extending JMenuBar) 也作为变量存储在我的主类中。

在 Toolbar 上发生用户事件时,它会调用父类(main),以获取 TabbedComponent 对象并调用方法来创建新选项卡。这一切都很好。

我的问题是,当我尝试用鼠标单击 ta 时,没有任何变化。我很确定我不需要 MouseAdapter 上的侦听器来做一些简单的事情,但如果我需要它我猜会添加它。

以下是与此问题相关的类的精简版本

公共类 ExampleClass 扩展 JFrame {

private TabbedBrowserPaneComponent cTabbedBrowserPane;

public ExampleClass() {
    super("");

    // Set up Components
    this.cTabbedBrowserPane = new TabbedBrowserPaneComponent(this);

    // Set up behaviour
    setSize(500, 300);
    setVisible(true);
}

/**
 * @return the cTabbedBrowserPane
 */
public TabbedBrowserPaneComponent getTabbedBrowserPane() {
    return cTabbedBrowserPane;
}


/**
 * @param cTabbedBrowserPane the cTabbedBrowserPane to set
 */
public void setTabbedBrowserPane(TabbedBrowserPaneComponent cTabbedBrowserPane) {
    this.cTabbedBrowserPane = cTabbedBrowserPane;
}

}

public class TabbedBrowserPaneComponent extends JTabbedPane {

// Parent class of the component
private JFrame parent = null;

public TabbedBrowserPaneComponent(JFrame parent) {
    super();
    setParent(parent);

    // Add an initial pane
    createNewTab();
    parent.getContentPane().add(this);
}

public void createNewTab() {
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(new JScrollPane(), BorderLayout.CENTER);
    this.addTab("Tab " + this.getTabCount(), panel);
}

/**
 * @return the parent
 */
public JFrame getParent() {
    return parent;
}

/**
 * @param parent the parent to set
 */
public void setParent(JFrame parent) {
    this.parent = parent;
}
}

要创建一个新选项卡,ToolBarComponent 的侦听器调用如下

public class CreateNewTabAction extends AbstractAction {

// Parent
private JMenu parent;

public CreateNewTabAction(JMenu parent) {
    super();
    this.setParent(parent);

    // Values for the tab
    putValue(Action.NAME, "New Tab");
}

@Override
public void actionPerformed(ActionEvent e) {
    ExampleClass.class.cast((parent.getParent().getParent())).getTabbedBrowserPane().createNewTab();
}

/**
 * @return the parent
 */
public JMenu getParent() {
    return parent;
}

/**
 * @param parent the parent to set
 */
public void setParent(JMenu parent) {
    this.parent = parent;
}
}

我真的很想念这件事吗?

4

1 回答 1

3

抱歉,您的代码明显缺乏设计(我不是刻薄,但我花了 3 年的大部分时间来消除这种行为,所以它给了我一个讨厌的抽搐)。

您的问题是您正在覆盖getParent,这是Component用于确定组件实际添加到何处的方法。这导致了系统内部工作的问题。

无需向选项卡组件提供父框架。如果您出于某种原因确实需要访问父框架,请考虑使用SwingUtilities.getWindowAncestor. 如果您只是计划为框架中的选项卡提供功能,请创建一个interface可以在选项卡和控制器/引擎之间建立合同的工具。

不要让我开始Action...

一个例子

我不确定您实际上想要实现什么,但绝对没有必要传递对浏览器选项卡或主框架的引用。您将程序的元素传递给它们只是不需要知道有关其父项的太多信息即可实现那里的工作,而且,您极大地限制了组件的灵活性和可重用性。

下面,我使用了一个简单的interface\controller,它在示例中的各种视图和控件之间提供了一个契约。各种元素中的任何一个都不需要知道更多......

public class ExampleClass {

    public static void main(String[] args) {
        new ExampleClass();
    }

    public ExampleClass() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                BrowserPane browserPane = new BrowserPane();
                CreateNewTabAction createNewTabAction = new CreateNewTabAction(browserPane);

                JMenu mnu = new JMenu("Stuff");
                mnu.add(createNewTabAction);

                JMenuBar mb = new JMenuBar();
                mb.add(mnu);

                JToolBar tb = new JToolBar();
                tb.add(createNewTabAction);

                JFrame frame = new JFrame();
                frame.setJMenuBar(mb);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(browserPane);
                frame.add(tb, BorderLayout.NORTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface TabController {

        public void createNewTab();
    }

    public class BrowserPane extends JPanel implements TabController {

        private TabbedBrowserPaneComponent cTabbedBrowserPane;

        public BrowserPane() {
            setLayout(new BorderLayout());
            // Set up Components
            this.cTabbedBrowserPane = new TabbedBrowserPaneComponent();
            add(cTabbedBrowserPane);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        public void createNewTab() {

            cTabbedBrowserPane.createNewTab();

        }
    }

    public class TabbedBrowserPaneComponent extends JTabbedPane {

        public TabbedBrowserPaneComponent() {
            super();
            createNewTab();
        }

        public void createNewTab() {
            JPanel panel = new JPanel(new BorderLayout());
            panel.add(new JScrollPane(), BorderLayout.CENTER);
            this.addTab("Tab " + this.getTabCount(), panel);
        }
    }

    public class CreateNewTabAction extends AbstractAction {

        private TabController controller;

        public CreateNewTabAction(TabController controller) {
            super();
            this.controller = controller;
            putValue(Action.NAME, "New Tab");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getController().createNewTab();
        }

        /**
         * @return the parent
         */
        public TabController getController() {
            return controller;
        }
    }
}
于 2012-12-14T03:24:29.503 回答