【问题标题】:Electron browser window电子浏览器窗口
【发布时间】:2018-05-20 07:21:15
【问题描述】:

我的电子应用程序中有 2 个 BrowserWindow 实例,mainWindowsecondaryWindowmainWindow 中有一个按钮,单击该按钮应打开 secondaryWindow

现在我的问题是,在 secondaryWindow 关闭之前,我不希望能够点击 mainWindow 中的任何内容。

我能得到的最接近的是使用mainWindow.hide(),但这只是完全隐藏了窗口,我希望在secondaryWindow 处于活动状态时仍然看到mainWindow,但它应该被禁用/不活动。

有什么建议吗?

【问题讨论】:

  • 使子窗口成为模态窗口。 window.open() 的示例这将禁用父窗口,直到子窗口关闭。

标签: electron


【解决方案1】:

打开子窗口有两种方式:

1.从主进程:

您可以从主进程打开子窗口。例如,这对于菜单中的自定义窗口很有用。

在这里,您可以使用构造函数使其成为parent 的子代。如果modal 属性为真,则在关闭子窗口之前,父窗口将无法访问。

function createChild(parent, html) {
  //creates modal window
  child = new BrowserWindow({
    width: 786,
    height: 847,
    parent: parent,
    modal: true,
    show: false
  });
  child.loadURL(html);
  child.webContents.openDevTools();
  child.once("ready-to-show", () => {
    child.show();
  });
}

2。从渲染器进程

现在,我们并不总是想通过 IPC 向主进程发送事件来打开子窗口,对吧?

我们不需要。为此,我们可以使用窗口上的open 函数。

例如:

const button = document.querySelector('button')
button.addEventListener('click', e => {
     self.open(`file://${__dirname}/child.html`)
})

要使这个窗口成为你的父窗口和模态窗口的子窗口,你可以在父窗口上注册一个事件监听器:

parent.webContents.on(
    "new-window",
    (event, url, frameName, disposition, options, additionalFeatures) => {
      Object.assign(options, {
        parent: parent,
        modal: true
      });
    }
  );

这样,在父窗口调用window.open()时,会打开一个模态子窗口。

示例

main.js

const { app, BrowserWindow } = require("electron");

let win;
function createWindow() {
  win = new BrowserWindow({ width: 1000, height: 800 });
  win.loadURL(`file://${__dirname}/index.html`);
  win.webContents.openDevTools();
  win.on("closed", () => {
    win = null;
  });

  win.webContents.on(
    "new-window",
    (event, url, frameName, disposition, options, additionalFeatures) => {
      Object.assign(options, {
        parent: win,
        modal: true
      });
    }
  );
}

app.on("ready", createWindow);

index.html

<!DOCTYPE html>
<html>

<body>
    <p>I am the parent, you can't touch me until you closed my child!</p>
    <button>Open child!</button>
    <script>
        const button = document.querySelector('button')
        button.addEventListener('click', e => {
            self.open(`file://${__dirname}/child.html`)
        })
    </script>
</body>

</html>

child.html

<!DOCTYPE html>
<html>

<body>
    I'm the child!
</body>

</html>

更新 Electron 5 或更高版本

出于安全原因,默认情况下,在渲染器进程中禁用了电子 5 节点集成。由于此示例在渲染器进程中使用了__dirname(它是节点 API 的一部分),因此我们需要重新引入它,因为它不再可用。在这个例子中,我为此目的使用了一个预加载脚本:

main.js

const { app, BrowserWindow } = require("electron");

let win;
function createWindow() {
  win = new BrowserWindow({
    width: 1000,
    height: 800,
    webPreferences: {
      preload: `${__dirname}/preload.js`,
    },
  });
  win.loadURL(`file://${__dirname}/index.html`);
  win.webContents.openDevTools();
  win.on("closed", () => {
    win = null;
  });

  win.webContents.on(
    "new-window",
    (_event, _url, _frameName, _disposition, options, _additionalFeatures) => {
      Object.assign(options, {
        parent: win,
        modal: true,
      });
    }
  );
}

app.whenReady().then(createWindow).catch(console.error);

preload.js

window.__dirname = __dirname;

index.html

<!DOCTYPE html>
<html>
  <body>
    <p>I am the parent, you can't touch me until you closed my child!</p>
    <button>Open child!</button>
    <script>
      const button = document.querySelector("button");
      button.addEventListener("click", (e) => {
        self.open(`file://${__dirname}/child.html`);
      });
    </script>
  </body>
</html>

child.html

<!DOCTYPE html>
<html>
  <body>
    I'm the child!
  </body>
</html>

【讨论】:

    猜你喜欢
    • 2021-03-24
    • 2017-02-21
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 2020-05-11
    • 2017-12-23
    • 1970-01-01
    • 2017-09-24
    相关资源
    最近更新 更多