java cs tab点击切换标签的实现 panel
代码实现效果如下

主界面的类如下
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import test.ButtonTabComponent;
 
public class TabComponentsDemo extends JFrame{
 
    private JTabbedPane pane = new JTabbedPane();
    private JMenuItem scrollTabItem ;
    private JMenuItem componentTabItem;
    private final int numTab = 5;
      
    public TabComponentsDemo(String title) {
       //设置frame标题名
       super(title);
       //设置关闭方式
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       //创建菜单栏
       initMenu();
       //将tabpane添加到frame中
       add(pane);
      
    }
   
    //初始化tabpanel相关配置,并且用于resize的调用
    public  void runTest() {
       //设置有关闭按键的标签
       componentTabItem.setSelected(true);
      
       //设置标签
       for(int i = 0 ; i < numTab ; i++)
       {
           //标签名
           String name = "tab "+i;
           //创建标签
           pane.add(name,createContent(name));
           //初始化标签上的文字和Button
           initTabComponent(i);
       }
      
      
       //设置frame的大小
       setSize(new Dimension(500,500));
       //将frame放到屏幕的正中央
       setLocationRelativeTo(null);
       //显示frame
       setVisible(true);
      
 
    } 
   
    //创建标签内容部分
    private Component createContent(String name) {
       //创建一个panel,并设置布局为一个分块
       JPanel panel = new JPanel(new GridLayout(1,1));
       //创建一个label
       JLabel label = new JLabel(name);
       //设置label的文本格式
       label.setHorizontalAlignment(JLabel.CENTER);
       //将label放入panel中
       panel.add(label);
       return panel;
    }
 
    //初始化带有关闭按钮的标签头部
    private void initTabComponent(int i) {
       //用这个函数可以初始化标签的头部
       pane.setTabComponentAt(i, new ButtonTabComponent(pane));
       }
   
    //创建菜单栏
    private void initMenu() {
       //创建一个菜单条
       JMenuBar mb = new JMenuBar();
      
       //创建重叠tab选项
       scrollTabItem = new JCheckBoxMenuItem("重叠tab");
       //设置快捷键
        scrollTabItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
       //设置监听事件
       scrollTabItem.addActionListener(new ActionListener() {
          
           @Override
           public void actionPerformed(ActionEvent arg0) {
              if(pane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
                  pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
              else
                  pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
           }
       });
      
       //设置可关闭的标签的菜单
       componentTabItem = new JCheckBoxMenuItem("设置可关闭的tab");
      componentTabItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));
       componentTabItem.addActionListener(new ActionListener() {
          
           @Override
           public void actionPerformed(ActionEvent e) {
              for(int i = 0 ; i < numTab ; i++)
              {
                  if(componentTabItem.isSelected())
                     initTabComponent(i);
                  else
                     pane.setTabComponentAt(i, null);
              }
           }
       });
      
       //设置重置标签
       JMenuItem reSetItem = new JMenuItem("重置");
       reSetItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,InputEvent.CTRL_MASK));
       reSetItem.addActionListener(new ActionListener() {
          
           @Override
           public void actionPerformed(ActionEvent e) {
              runTest();
           }
       });
      
       //创建菜单
       JMenu menu = new JMenu("选项");
       //添加菜单项
       menu.add(componentTabItem);
       menu.add(scrollTabItem);
       menu.add(reSetItem);
      
       //添加菜单
       mb.add(menu);
       //添加菜单条(注意一个frame只能有一个菜单条,所以用set)
       setJMenuBar(mb);
      
    }
 
    public static void main(String[] args) {
       SwingUtilities.invokeLater(new Runnable() {
          
           @Override
           public void run() {
              new TabComponentsDemo("可关闭的tab测试").runTest();
           }
       });
    }
 
 
}
会用到的另一个类如下:
package test;
 
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.plaf.basic.BasicButtonUI;
 
public class ButtonTabComponent extends JPanel{
    private final JTabbedPane pane;
 
    public ButtonTabComponent(final JTabbedPane pane) {
       //设置标签头要水平的,从左向右的排列组件,并且组件的间距为0(横向和纵向)
       super(new FlowLayout(FlowLayout.LEFT, 0, 0));
      
       if(pane == null)
           throw new NullPointerException("pane can not be null");
       this.pane = pane;
      
       //不画出panel的边界
       setOpaque(false);
      
       //创建标签头的文字内容
       JLabel label = new JLabel(){
           //重写方法,返回pane指定位置的名字,这里有点绕,可以好好理解理解
           //为什么不直接设置标签的内容,而是通过重写函数来修改标签内容
           //可能是希望业务逻辑尽量不要散落在外部
           @Override
           public String getText() {
              //可以获得当前panel在tab中的位置
              int i = pane.indexOfTabComponent(ButtonTabComponent.this);
              if(i != -1)
                  //得到当前panel的名字(实际是tab的名字)
                  return pane.getTitleAt(i);
              return null;
           }
       };
      
       label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
       add(label);
       //创建关闭按钮(就是那个差按键)
       JButton button = new TabButton();
       add(button);
       setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
    }
   
    private class TabButton extends JButton implements ActionListener{
       public TabButton() {
           //设置按键的大小
           final int size = 17;
           setPreferredSize(new Dimension(size,size));
           //设置按键的提示信息
           setToolTipText("关闭窗口");
           //设置按键的绘制于普通按键相同
           setUI(new BasicButtonUI());
           //不对Button进行填充,就是按键是透明的
           setContentAreaFilled(false);
           //按键不能获得焦点
           setFocusable(false);
           //设置按键的边框为雕刻样式
           setBorder(BorderFactory.createEtchedBorder());
           //系统不自动绘制按键边界(这个边界在鼠标放上去之后才绘制)
           setBorderPainted(false);
          
           //添加按键点击事件
           addActionListener(TabButton.this);
           //添加鼠标事件(主要是mouseover 和 mouse exit)
           addMouseListener(mouseListener);
          
       }
 
       //重写Button的绘制函数
       @Override
       protected void paintComponent(Graphics g) {
           super.paintComponent(g);
          
           //创建一个graphics2D,因为需要在Button上画差
           Graphics2D g2 = (Graphics2D) g.create();
          
           //设置画笔,宽度为2
           g2.setStroke(new BasicStroke(2));
           //设置画笔颜色
           g2.setColor(Color.BLACK);
           //当鼠标移动到Button上时,画笔为紫色
           if(getModel().isRollover())
              g2.setColor(Color.PINK);
           //绘制差
           int delta = 6;
           g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
            g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
            //释放画笔资源
            g2.dispose();
       }
 
       @Override
       public void actionPerformed(ActionEvent arg0) {
           //当按键被点击,关闭当前标签页
           int i = pane.indexOfTabComponent(ButtonTabComponent.this);
           if(i != -1)
              pane.remove(i);
       }
      
       private final MouseListener mouseListener = new MouseAdapter() {
           @Override
           public void mouseEntered(MouseEvent event) {
              //鼠标移入按键,绘制按键边界
              Component c = event.getComponent();
              if(c instanceof AbstractButton)
                  ((AbstractButton)c).setBorderPainted(true);
           }
          
           @Override
           public void mouseExited(MouseEvent event) {
              //鼠标移出按键,不绘制按键边界
              Component c = event.getComponent();
              if(c instanceof AbstractButton)
                  ((AbstractButton)c).setBorderPainted(false);
           }
          
       };
      
    }
   
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号