当我们点击target值为_blank的链接时,JCEF默认以弹出窗口的形式打开新页面,要实现tab栏形式,可参考以下步骤

  1.创建一个实现CefLifeSpanHandlerAdapter的类,重写onBeforePopup方法:根据url创建一个CefBrowser对象,将CefBrowser的UI组件设置到JTabbedPane

  2.设置onBeforePopup方法的返回值为true,取消弹出窗口

  注意:因为JTabbedPane默认没有关闭按钮,需要自己使用JPanel之类的组件实现

  设计思路:打开新窗口时,在JTabbedPane里新建一个Tab,利用CefClient创建一个CefBrowser对象,并将CefBrowser的UI添加到Tab,显示新创建的Tab

  JTabbedPane默认没有关闭按钮,我们自定义一个JPanel来实现标题栏和关闭按钮。JPanel包含两个JLabel标题,一个显示页面标题,一个显示“X”。为“X”添加单击事件监听器,当点击“X”时,销毁Tab关联的CefBrowser对象,移除Tab

  这里先写一个实体类,用来保存Tab关闭时要用到的数据

  TabBrowser

  public class TabBrowser {

  /**索引,与关闭按钮关联*/

  private int index;

  /**浏览器对象*/

  private CefBrowser browser;

  /**浏览器标题*/

  private JLabel title;

  /**

  * 获取 索引,与关闭按钮关联

  * @return index

  */

  public int getIndex() {

  return index;

  }

  /**

  * 设置 索引,与关闭按钮关联

  * @param index 索引,与关闭按钮关联

  */

  public void setIndex(int index) {

  this.index = index;

  }

  /**

  * 获取浏览器对象

  * @return browser

  */

  public CefBrowser getBrowser() {

  return browser;

  }

  /**

  * 设置 浏览器对象

  * @param browser browser

  */

  public void setBrowser(CefBrowser browser) {

  this.browser = browser;

  }

  /**

  * 设置浏览器标题

  * @return title

  */

  public JLabel getTitle() {

  return title;

  }

  /**

  * 设置 浏览器标题

  * @param title 浏览器标题

  */

  public void setTitle(JLabel title) {

  this.title = title;

  }

  /**

  * @param index

  * @param browser

  * @param title

  */

  public TabBrowser(int index, CefBrowser browser, JLabel title) {

  super();

  this.index = index;

  this.browser = browser;

  this.title = title;

  }

  }

  创建一个处理标题更新的Handler

  DisplayHandler

  public class DisplayHandler extends CefDisplayHandlerAdapter {

  private TabbedPaneTestFrame frame;

  public DisplayHandler(TabbedPaneTestFrame frame) {

  this.frame=frame;

  }

  /* (non-Javadoc)

  * @see org.cef.handler.CefDisplayHandlerAdapter#onTitleChange(org.cef.browser.CefBrowser, java.lang.String)

  */

  @Override

  public void onTitleChange(CefBrowser browser, String title) {

  this.frame.updateTabTitle(browser, title);

  // super.onTitleChange(arg0, arg1);

  }

  }

  创建一个处理弹出窗口的Handler

  LifeSpanHandler

  public class LifeSpanHandler extends CefLifeSpanHandlerAdapter {

  private TabbedPaneTestFrame frame;

  public LifeSpanHandler(TabbedPaneTestFrame frame) {

  this.frame=frame;

  }

  /* (non-Javadoc)

  * @see org.cef.handler.CefLifeSpanHandlerAdapter#onBeforePopup(org.cef.browser.CefBrowser, org.cef.browser.CefFrame, java.lang.String, java.lang.String)

  */

  @Override

  public boolean onBeforePopup(CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) {

  this.frame.createBrowser(target_url);

  //返回true表示取消弹出窗口

  return true;

  }

  }

  创建一个点击关闭按钮的监听器

  TabCloseListener

  public class TabCloseListener implements MouseListener{

  private int index;

  private TabbedPaneTestFrame frame;

  public TabCloseListener(int index,TabbedPaneTestFrame frame) {

  this.index=index;

  this.frame=frame;

  }

  /* (non-Javadoc)

  * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)

  */

  @Override

  public void mouseClicked(MouseEvent e) {

  // TODO Auto-generated method stub

  System.out.println("点击了关闭事件...");

  frame.removeTab(null, index);

  }

  /* (non-Javadoc)

  * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)

  */

  @Override

  public void mousePressed(MouseEvent e) {

  // TODO Auto-generated method stub

  }

  /* (non-Javadoc)

  * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)

  */

  @Override

  public void mouseReleased(MouseEvent e) {

  // TODO Auto-generated method stub

  }

  /* (non-Javadoc)

  * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)

  */

  @Override

  public void mouseEntered(MouseEvent e) {

  // TODO Auto-generated method stub

  }

  /* (non-Javadoc)

  * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)

  */

  @Override

  public void mouseExited(MouseEvent e) {

  // TODO Auto-generated method stub

  }

  }

  主类代码

  TabbedPaneTestFrame

  public class TabbedPaneTestFrame extends JFrame{

  /**

  *

  */

  private static final long serialVersionUID = 871314861019393323L;

  private static CefApp cefApp;

  private static CefClient cefClient;

  private boolean useOSR;

  private boolean isTransparent;

  /**tabbedPane对象*/

  private static JTabbedPane tabbedPane;

  /**TabBrowser对象列表**/

  private List tbList=new Vector();

  /**tab使用的索引。此索引不是tab在tabbedpane中的索引,此索引用来移除tab栏**/

  private int tbIndex=0;

  /**默认的标题名*/

  private final static String TITLE_INFO="正在载入...";

  public TabbedPaneTestFrame(String url) {

  //是否Linux系统

  useOSR=OS.isLinux();

  //是否透明

  isTransparent=false;

  //添加Handler,在CEFAPP状态为终止时退出程序

  CefApp.addAppHandler(new CefAppHandlerAdapter(null) {

  @Override

  public void stateHasChanged(org.cef.CefApp.CefAppState state) {

  // Shutdown the app if the native CEF part is terminated

  if (state == CefAppState.TERMINATED) System.exit(0);

  }

  });

  CefSettings settings = new CefSettings();

  settings.windowless_rendering_enabled = useOSR;

  //获取CefApp实例

  cefApp=CefApp.getInstance(settings);

  //创建客户端实例

  cefClient = cefApp.createClient();

  //添加鼠标右键菜单handler

  cefClient.addContextMenuHandler(new MenuHandler());

  //添加浏览器标题更改handler

  cefClient.addDisplayHandler(new DisplayHandler(this));

  //添加浏览器窗口弹出handler

  cefClient.addLifeSpanHandler(new LifeSpanHandler(this));

  tabbedPane=new JTabbedPane(JTabbedPane.TOP,JTabbedPane.SCROLL_TAB_LAYOUT);

  getContentPane().add(tabbedPane, BorderLayout.CENTER);

  pack();

  setTitle("测试JCEF-Tab栏");

  setSize(800, 600);

  setVisible(true);

  //添加一个窗口关闭监听事件

  addWindowListener(new WindowAdapter() {

  @Override

  public void windowClosing(WindowEvent e) {

  closeAllBrowser();

  CefApp.getInstance().dispose();

  dispose();

  }

  });

  createBrowser("http://www.baidu.com");

  }

  /**

  * 关闭所有浏览器

  * @author:liuming

  */

  public void closeAllBrowser() {

  for(int i=tbList.size()-1;i>=0;i--) {

  TabBrowser tb=tbList.get(i);

  tb.getBrowser().close(true);

  tabbedPane.removeTabAt(i);

  System.out.println("移除索引为"+i+"的tab...");

  }

  }

  /**

  * 根据url创建一个新的tab页

  * @author:liuming

  * @param url

  * @return 最后一个tab的索引

  */无锡人流医院哪家好 http://www.bhnnkyy120.com/

  public int createBrowser(String url) {

  CefBrowser browser = cefClient.createBrowser(url, useOSR, isTransparent);

  tabbedPane.addTab(".", browser.getUIComponent());

  int lastIndex=tabbedPane.getTabCount()-1;

  tbIndex++;

  //创建自定义tab栏

  JPanel jp=new JPanel();

  JLabel ltitle=new JLabel(TITLE_INFO);

  JLabel lclose=new JLabel("X");

  jp.setOpaque(false);

  ltitle.setHorizontalAlignment(JLabel.LEFT);

  lclose.setHorizontalAlignment(JLabel.RIGHT);

  jp.add(ltitle);

  jp.add(lclose);

  //添加关闭按钮监听事件

  lclose.addMouseListener(new TabCloseListener(tbIndex,this));

  //设置tab栏标题的关键句

  tabbedPane.setTabComponentAt(lastIndex, jp);

  TabBrowser tb=new TabBrowser(tbIndex, browser, ltitle);

  tbList.add(tb);

  tabbedPane.setSelectedIndex(lastIndex);

  return lastIndex;

  }

  /**

  * 修改标题

  * @author:liuming

  * @param browser

  * @param title

  */

  public void updateTabTitle(CefBrowser browser,String title) {

  if(title!=null && !"".equals(title)) {

  if(title.length()>12) title=title.substring(0, 12)+"...";

  for(TabBrowser tb:tbList) {

  if(tb.getBrowser()==browser) {

  tb.getTitle().setText(title);

  break;

  }

  }

  }

  }

  /**

  * 移除tab

  * @author:liuming

  * @param browser

  * @param index

  */

  public void removeTab(CefBrowser browser,int index) {

  if(browser!=null) {

  for(int i=0;i

  TabBrowser tb=tbList.get(i);

  if(tb.getBrowser()==browser) {

  tb.getBrowser().close(true);

  tabbedPane.removeTabAt(i);

  tbList.remove(i);

  // System.out.println("移除索引为"+i+"的tab");

  break;

  }

  }

  }else {

  for(int i=0;i

  TabBrowser tb=tbList.get(i);

  if(tb.getIndex()==index) {

  tb.getBrowser().close(true);

  tabbedPane.removeTabAt(i);

  tbList.remove(i);

  // System.out.println("移除索引为"+i+"的tab");

  break;

  }

  }

  }

  }

  public static void main(String[] args) {

  new TabbedPaneTestFrame("http://www.baidu.com");

  }

  }

JCEF-tab形式展示浏览器的更多相关文章

  1. EasyNVR摄像机网页无插件直播方案H5前端构建之:使用BootstrapPagination以分页形式展示数据信息

    背景介绍 EasyNVR核心在于摄像机的音视频流的获取.转换.转码与高性能分发,同时同步完成对实时直播流的录像存储,在客户端(PC浏览器.Android.iOS.微信)进行录像文件的检索.回放和下载. ...

  2. redis 一二事 - 设置过期时间,以文件夹形式展示key显示缓存数据

    在使用redis时,有时回存在大量数据的时候,而且分类相同,ID相同 可以使用hset来设置,这样有一个大类和一个小分类和一个value组成 但是hset不能设置过期时间 过期时间只能在set上设置 ...

  3. Easyui 实现点击不同树节点打开不同tab页展示不同datagrid表数据设计

    实现点击不同树节点打开不同tab页展示不同datagrid表数据设计 by:授客 QQ:1033553122 测试环境 jquery-easyui-1.5.3 需求描述 如上图, 1.点击左侧树,叶子 ...

  4. 获取url中的参数并以对象的形式展示出来

    速记:获取url中的参数并以对象的形式展示出来 function getUrlData(){ let url=window.location.search;//url中?之后的部分 console.l ...

  5. javascript 如何打印、输出数组内容(将数组内容以字符串的形式展示出来)

        1.情景展示 在实际开发过程中,为了调试,有时我们需要看数组中具体包含了哪些数据,但是, 如果我们直接打印该数组对象,显示的结果却不是我们想要的. 如何才能将数组内容打印出来呢?(将数组内容以 ...

  6. 以打字形式展示placeholder的插件

    http://weber.pub/以打字形式展示placeholder的插件/197.html

  7. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:使用BootstrapPagination以分页形式展示数据信息

    上一篇介绍通过接口来获取数据,本篇将介绍如何以分页形式展示出接口获取到的数据 获取到的数据往往会很多,为了追去页面的美观和方便用户的检索,需要进行分页的展示: EasyNVR可接如多通道,当我们的通道 ...

  8. 查询表格——建立动态表格,使用ajax输入查询条件将后台数据查询出来以表格的形式展示出来

    建立动态表格,使用ajax将前台查询条件传给后台,并将查询结果以表格的形式展示出来. 页面的展示效果如下图所示: 第一步:查询条件的部分: 代码如下: <div class="text ...

  9. 基于Vue、Bootstrap的Tab形式的进度展示

    最近基于Vue.Bootstrap做了一个箭头样式的进度展示的单页应用,并且支持了对于一个本地JS文件的检索,通过这个单页应用,对于Vue的理解又深入了一些.在这里把主要的代码分享出来. 本单页应用实 ...

随机推荐

  1. NOIP 2008 火柴棒等式

    洛谷 P1149 火柴棒等式 洛谷传送门 JDOJ 1540: [NOIP2008]火柴棒等式 T2 JDOJ传送门 Description 给你n根火柴棍,你可以拼出多少个形如"A+B=C ...

  2. 07_LACP负载分担(数通华为)

    1. 网络拓扑 2. SW1配置:[SW1]vlan batch 10 20[SW1]interface GigabitEthernet 0/0/1[SW1-GigabitEthernet0/0/1] ...

  3. Educational Codeforces Round 78 (Rated for Div. 2) B - A and B(思维)

  4. pytest--常用插件

    前戏 虽然pytest给我们提供了很多的功能,但是有些功能还是没有,而pytest的插件可以满足我们的需求,比如用例失败重跑,统计代码覆盖率等等功能. pytest-sugar pytest-suga ...

  5. 【luoguP1533】可怜的狗狗

    题目链接 发现区间按左端点排序后右端点也是单调的,所以扫一遍就行了,用权值线段树维护第\(k\)大 #include<algorithm> #include<iostream> ...

  6. 在eclipse中新建java问题报错:The type XXX cannot be resolved. It is indirectly referenced from required .class files

    在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误 ...

  7. snmpwalk 简介

    概述 SNMPWALK是一个通过SNMP GET-NEXT类型PDU,实现对目标AGENT的某指定MIB分支信息进行完整提取输出的命令工作. 命令⾏ snmpwalk [选项] agent [oid] ...

  8. virtualbox安装问题总结

    还是老问题 重点重点: https://blog.csdn.net/Loisleen/article/details/84975165#1install_the_gcc_make_perl_packa ...

  9. 安装kafka + zookeeper集群

    系统:centos 7.4 要求:jdk :1.8.x kafka_2.11-1.1.0 1.绑定/etc/hosts 10.10.10.xxx      online-ops-xxx-0110.10 ...

  10. Yarn和Zookeeper的区别

    Yarn:分布式资源管理器 Zookeeper:分布式协作服务 Zookeeper是一个分布式协调服务(Coordination),一个leader,多个follower组成的集群,就是为用户的分布式 ...