当我们点击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. JSOI 2010 连通数

    洛谷 P4306 [JSOI2010]连通数 洛谷传送门 题目描述 度量一个有向图联通情况的一个指标是连通数,指图中可达顶点对个的个数. 如图 顶点 11 可达 1,~2,~3,~4,~51, 2, ...

  2. JDOJ 2175: 忠诚2

    JDOJ 2175: 忠诚2 题目传送门 Description 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让 ...

  3. 第二阶段冲刺(个人)——four

    今天的的计划:选择功能界面的背景设计,使得整体效果看上去吸引眼球. 昨天做了什么?选择功能界面的选择框排版设计. 遇到的困难: 还是js的函数 设计,思路不是很清晰.

  4. 总结敏捷开发之Scrum

    敏捷开发的概念 敏捷开发是一种以人为核心,迭代,循序渐进的开发方法. 为什么说是以人为核心?传统的瀑布模型是以文档驱动的,但是在敏捷中,只写少量的文档,注重的是人与人之间面对面的交流. 什么是迭代?迭 ...

  5. GIL全局解释锁

    目录 一 介绍 二 GIL介绍 三 GIL与多线程 四 多线程性能测试 一 介绍 ''' 定义: In CPython, the global interpreter lock, or GIL, is ...

  6. spark基础知识四

    围绕spark的其他特性和应用.主要包括以下几个方面 spark自定义分区 spark中的共享变量 spark程序的序列化问题 spark中的application/job/stage/task之间的 ...

  7. 下载mqtt.fx

    #下载mqtt.fxhttp://www.jensd.de/apps/mqttfx/1.7.1/

  8. Android 从零编写一个带标签 TagTextView

    最近公司的项目升级到了 9.x,随之而来的就是一大波的更新,其中有个比较明显的改变就是很多板块都出了一个带标签的设计图,如下: 怎么实现 看到这个,大多数小伙伴都能想到这就是一个简单的图文混排,不由得 ...

  9. Java实现添加压缩文件

    package junittest; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStr ...

  10. Scala反射(二)

    我们知道,scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射 ...