电子学中语境菜单的堆积

时间:2017-02-09 22:36:11

标签: node.js menu ipc electron atom-editor

我正在构建一个基于电子的应用程序,其中包含一个包含唯一行的网格。我想要一个特定于每一行的上下文菜单。这是一个例子:

Image of GUI with context menu

虽然裁剪了此屏幕截图,但您可以看到有多行,每行包含单独的数据。由于我想右键单击一行并获得一个独特的上下文菜单,我已经实现了electron-context-menu,它可以在第一次右键单击时工作,但随后的右键单击会导致上下文菜单的堆叠效果

具体来说,这是发生的事情:

  1. 我右键单击Row-1并显示正确的上下文菜单
  2. 我右键单击第2行,然后重复显示第1行的上下文菜单,然后显示第2行的上下文菜单。 (注意在屏幕截图中显示的上下文菜单与我的鼠标所在的行不对应)
  3. 这会重演。
  4. 在React.JS中,这是我的监听器,它根据contextmenu模块的需要收集electron-context-menu对象:

      handleContextMenu() {
        this.props.contextMenu({
          window: electron.remote.BrowserWindow.getFocusedWindow(),
          prepend: (params, browserWindow) => [{
            label: `Library Compare ${this.state.msn}`,
            click: () => this.runLibCompare()
          }],
          append: (params, browserWindow) => [{
            label: '---',
          }]
        })
      };
    

    其中this.props.contextMenu(...)计算要输入的React.JS组件:

    const contextMenu = eRequire('electron-context-menu');
    

    我做了一些大规模的调试,我不认为问题是模块。我使用的模块基本上组织了有关上下文菜单的信息,然后使用electron.remote函数和来自电子内部的menu.popup函数。这是指向specific line in github的链接。

    const menu = (electron.Menu || electron.remote.Menu).buildFromTemplate(menuTpl);
    menu.popup(electron.remote ? electron.remote.getCurrentWindow() : win);
    

    menu.popup的来电导致此line in electron

      const remoteMemberFunction = function (...args) {
        if (this && this.constructor === remoteMemberFunction) {
          // Constructor call.
          let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(args))
          return metaToValue(ret)
        } else {
          // Call member function.
          let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(args))
          return metaToValue(ret)
        }
    

    }

    所以我看到了对ipcRender.sendSync的调用 - 但是当我在ipcMain的{​​{3}}中添加调试语句时,我看不到任何输出!

    ipcMain.on('ELECTRON_BROWSER_MEMBER_CALL', function (event, id, method, args) {
      try {
        args = unwrapArgs(event.sender, args)
        let obj = objectsRegistry.get(id)
    
        if (obj == null) {
          throwRPCError(`Cannot call function '${method}' on missing remote object ${id}`)
        }
    
        callFunction(event, obj[method], obj, args)
      } catch (error) {
        event.returnValue = exceptionToMeta(error)
      }
    })
    

    当我将调试语句添加到上面的函数时,我没有看到任何输出。这就是我搜索墙的地方。

    我正在使用电子1.4.15。我知道这个问题应该是可以解决的,所有Atom IDE(基于电子的)都没有这个问题,即使它有多个上下文菜单。

    我认为我需要清理一些内存,我只是想不通如何清除以前上下文菜单的堆栈!

1 个答案:

答案 0 :(得分:2)

我通过首先使用e.target获取点击目标来解决这个问题。然后,根据它,我调用相应的contextmenu。如果目标点击不在我的应用的目标列表中,我使用默认的上下文菜单。

window.addEventListener(
    "contextmenu",
    e => {
        e.preventDefault();
        if (e.target.id === 'fullscr'){

        console.log(e && e.target);

       // e.preventDefault();
        mymenu.popup(remote.getCurrentWindow());
        }else{
            editmenu.popup(remote.getCurrentWindow());
        }
        console.log(e.which);
    },
    false
);