Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

java - JTabbedPane won't change panel on mouseclick

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.

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.

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

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).

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.

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.

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

An Example

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.

Below, I use a simple interfacecontroller 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;
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...