JTabbedPane不会在鼠标单击上更改面板 [英] JTabbedPane won't change panel on mouseclick

查看:222
本文介绍了JTabbedPane不会在鼠标单击上更改面板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Main class that stores a TabbedComponent(extending JTabbedPane) as a variable. Another class (ToolbarComponent(extending JMenuBar) is also stored as a variable within my main class.

在工具栏上的用户事件上,它将调用父类(主类)以获取TabbedComponent对象,并调用一种方法来创建新标签页.一切正常.

Upon a user event on the Toolbar, it calls the parent class (main), to get the TabbedComponent object and call a method to create a new tab. Which all works fine.

我的问题是,当我尝试用鼠标单击ta时,没有任何变化.我很确定我不需要MouseAdapter上的监听器来进行简单的操作,但是我猜会在需要时添加它.

My issue is that when I attempt to click on a ta with my mouse, nothing changes. I'm pretty sure that I don't need a listener on MouseAdapter for something that simple, but will add it if I need it I guess.

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

Below is are stripped down versions of classes relevant to this issue

公共类ExampleClass扩展了JFrame {

public class ExampleClass extends 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的侦听器将像这样

To create a new tab, ToolBarComponent's listener calls like this

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;
}
}

这真的只是我想念的东西吗?

It this something really simply that I am missing?

推荐答案

您的代码显示出设计上的严重不足,抱歉(我并不是故意的意思,但是我花了三年的大部分时间来解决此问题的行为,所以它给我带来了令人讨厌的抽搐.)

Your code demonstrates a significant lack of design, sorry (I'm not trying to be mean, but I've spent the better part of 3 years undoing this kind of behavior so it gives me a nasty twitch).

您的问题是您要覆盖getParent,这是Component的方法,用于确定组件的实际添加位置.这会导致系统内部运行出现问题.

Your problem is you are overriding getParent, which is method of Component used to determine where the component is actually added to. This is causing issues for the internal workings of the system.

无需向选项卡组件提供父框架.如果由于某种原因确实需要重新访问父框架,请考虑使用SwingUtilities.getWindowAncestor.如果您只是打算为框架中的选项卡提供功能,请创建interface,该功能可以在选项卡与控制器/引擎之间建立契约.

There is no need to supply the parent frame to the tab component. If you REALLY need to get access back to the parent frame for some reason, consider using SwingUtilities.getWindowAncestor. If you are just planing to supply functionality for the tab in the frame, create a interface that can establish the contract between the tab and the controller/engine.

别让我开始使用Action ...

Don't get me started on the Action ...

示例

我不确定您实际上要达到什么目的,但是绝对不需要传递对浏览器选项卡或主框架的引用.您传递给他们的程序的元素只是不需要知道关于父母的太多信息即可完成工作,而且,您在很大程度上限制了组件的灵活性和可重用性.

I'm not sure what is you're actually trying to achieve, but there is absolutely no need to pass around a reference to the browser tab or the main frame. The elements of your program your passing them to just don't need to know that much information about their parents in order to achieve there work, also, you are significantly limiting the flexibility and re-usability of your components.

下面,我使用一个简单的interface \ controller,它提供示例中各个视图和控件之间的协定.各个元素都不是真正需要了解更多...

Below, I use a simple interface\controller that provides a contract between the various views and controls within the example. None of the various elements really need to know much more...

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;
        }
    }
}

这篇关于JTabbedPane不会在鼠标单击上更改面板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆