JDK-4465870 : JTabbedPane: can't intercept mouse events when using scrolled tabs
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_98
  • CPU: x86
  • Submitted: 2001-06-04
  • Updated: 2001-11-16
  • Resolved: 2001-11-16
Related Reports
Relates :  
Description

Name: bsC130419			Date: 06/04/2001


java version "1.4.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b65)
Java HotSpot(TM) Client VM (build 1.4.0-beta-b65, mixed mode)

In following code, I have created a subclass of JTabbedPane in
order to associate right-click popup menus with the tabs:

//===== sample code =============================================

import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

public class TabbedPaneTest extends JFrame
{
  MyTabbedPane tabPane;
  
  public TabbedPaneTest(int layoutPolicy)
  {
    setTitle("TabbedPaneTest");
    setBounds(50,50,400,300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    tabPane = new MyTabbedPane(JTabbedPane.TOP, layoutPolicy);
    tabPane.addTab("Tab one", new JPanel());
    tabPane.addTab("Tab two", new JPanel());
    getContentPane().add(tabPane, BorderLayout.CENTER);
    setVisible(true);
  }

  public static void main(String[] argv)
  {
    int policy = JTabbedPane.WRAP_TAB_LAYOUT;
    if (argv.length > 0 && "scrolled".equals(argv[0]))
    {
      policy = JTabbedPane.SCROLL_TAB_LAYOUT;
    }
    new TabbedPaneTest(policy);
  }
  
  
  class MyTabbedPane extends JTabbedPane
  {
    public MyTabbedPane(int tabPlacement, int layoutPolicy)
    {
      super(tabPlacement, layoutPolicy);
    }
    
    protected void processMouseEvent(MouseEvent evt)
    {
      if (evt.getID() == MouseEvent.MOUSE_PRESSED
          && evt.getButton() == MouseEvent.BUTTON3)
      {
        int index = indexAtLocation(evt.getX(), evt.getY());
        getTabPopup(index).show(this, evt.getX(), evt.getY());
      }
      else
      {
        super.processMouseEvent(evt);
      }
    }
  
    private JPopupMenu getTabPopup(final int index)
    {
      String title = getTitleAt(index);
  
      JPopupMenu pm = new JPopupMenu();
      JMenuItem close = new JMenuItem("Remove " + title);
      close.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent evt)
        {
          remove(index);
        }
      });
      pm.add(close);
  
      return pm;
    }
  }
}

//===============================================================

Compile the code and run it using the default wrapped tab layout:

   % java TabbedPaneTest

A frame containing a tabbed pane with two tabs appears.  Right-
click on either of the tabs, and a popup menu appears, giving you
the option of removing that tab.  Now close the frame and rerun
the program in scrolled mode:

   % java TabbedPaneTest scrolled

This time, right-clicking on a tab doesn't bring up a menu; it
just selects the tab, the same as left- or middle-clicking does.
The problem is that the mouse event is now being generated, not
by the tabbed pane itself, but by the ScrollableTabSupport object,
which is a private instance of a private inner class of
BasicTabbedPaneUI.  There is simply no way to get at this thing to
intercept its events or to attach listeners to it.

This means that developers who want to let their users choose
between wrapped and scrolled tab layouts will either have to warn
them that any right-click functions (like popup menus) will only be
available in wrapped mode, or just not include those functions for
the sake of consistency.  Anything you can do in one mode should be
doable in both.


You might provide a callback method in JTabbedPane for subclassers
to override if they so choose:


  protected void rightButtonPressed(MouseEvent evt) {}


...and rewrite the MouseHandler to something like this:


  public class MouseHandler extends MouseAdapter
  {
    public void mousePressed(MouseEvent e)
    {
      if (!tabPane.isEnabled())
      {
        return;
      }
      if (e.getButton() == MouseEvent.BUTTON1)
      {
        int tabIndex = getTabAtLocation(e.getX(), e.getY());
        if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex))
        {
          if (tabIndex == tabPane.getSelectedIndex())
          {
            if (tabPane.isRequestFocusEnabled())
            {
              tabPane.requestFocus();
              tabPane.repaint(rects[tabIndex]);
            }
          }
          else
          {
            tabPane.setSelectedIndex(tabIndex);
          }
        }
      }
      else if (e.getButton() == MouseEvent.BUTTON3)
      {
        tabPane.rightButtonClicked(e);
      }
    }
  }
(Review ID: 125727) 
======================================================================

Comments
EVALUATION This will be fixed with RFE 4499556 where you will be able to specify the component used in the tab. Closing this bug as will not fix. Please look at the RFE for further information. ###@###.### 2001-11-16
16-11-2001