即使在新窗口上调用show()函数,Electron js桌面应用程序也不会显示 [英] Electron js desktop app not showing even after calling show() function on new window

查看:212
本文介绍了即使在新窗口上调用show()函数,Electron js桌面应用程序也不会显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Electron js的新手,但是当我在命令行上运行 npm run start 时,该窗口似乎有时显示,但有时也不显示。我不知道怎么了。我什至尝试删除新创建的 BrowserWindow 上的 show:false 部分,但是,在运行 npm run start 还有一些时间。当我使用Electron-packager打包应用程序时,我仍然面临同样的问题


编辑:我发现,当我删除renderer.js文件中的所有代码时, ,它可以正常运行,但是当我放回代码时,它会产生该问题,所以问题可能出在渲染器过程中。


在.app / main.js

  // const {menu_template,save_as_id} = require('./ app-menu'); 
const {app,BrowserWindow,Menu,dialog,ipcMain} = require(‘electron’);
const path = require('path');

/ **
*在调用
时创建一个新窗口* /
函数createWindow(){
let x; //窗口x坐标或屏幕上的水平位置
让y; //如果(BrowserWindow.getAllWindows()。length> = 3)返回,则窗口y坐标或屏幕在屏幕上的垂直位置

;

const focusWindow = BrowserWindow.getFocusedWindow();
if(focusedWindow){
让[posX,posY] = focusedWindow.getPosition();
//记录窗口位置
console.log(`窗口位置
x:$ {posX},y:$ {posY}`);

if(!focusedWindow.isNormal())
posX = posY = 50;
//将窗口随机放置在屏幕上
const randX = Math.round(Math.random()* 20);
const randY = Math.round(Math.random()* 20);
const _randX = -randX-5;
const _randY = -randY-5;

x = posX +(randX< = 10?_randX:randX);
y = posY +(randY <= 10?_randY:randY);
//检查窗口是否不完全可见
const isOffScreen = x< 0 || & 0;
//然后将窗口设置在特定位置:60
if(isOffScreen)
x = y = 60;
}

//创建新的浏览器窗口
let newWindow = new BrowserWindow({
x,
y,
minWidth:300,
minHeight:300,
show:false,
webPreferences:{
enableRemoteModule:true,
nodeIntegration:true,
preload:path.join(__ dirname, 'preload.js')
}

});

newWindow.on( closed,()=> {
newWindow = null;
});

newWindow.loadFile(’./ app / index.html’);
newWindow.once('ready-to-show',()=> {
//现在将GUI加载到窗口时显示当前窗口
newWindow.show( );
console.log('Window ready to show');

//设置窗口标题以指示当前文件未命名为
//并且需要保存的
newWindow.setTitle('Untitled-NoteEditor');
});
}

//在应用程序首次启动时创建新窗口
app.whenReady()。then(()=> {
// Menu.setApplicationMenu( menu_template);
createWindow();
})

/ **
*只需将targetTarget的标题设置为title
* @param {*} targetWindow到接收者以进行标题更改
* @param {*} title窗口的新标题
* /
const setWindowTitle =(targetWindow,title)=> targetWindow.setTitle(title);

exports.createWindow = createWindow;
// export.chooseFile =选择文件;
exports.setWindowTitle = setWindowTitle

在./app/renderer.js


  const {ipcRenderer,remote} = require(电子); 
const mainProcess = remote.require(’./ main.js’);
const app = remote.app;

var text = document.getElementById(’text’); // TextArea
var initialTextContent;
var g_targetTitle;


// //按下键时,显示状态表明文本已被编辑并且需要保存
text.addEventListener('keyup',()=> {
const target = remote.getCurrentWindow();
letchangedIndicatorChar ='*';
let _windowTitle = target.getTitle();
let isWindowStartUp = _windowTitle.startsWith(' Untitled');

//如果更改被删除,则将窗口标题还原为初始标题
if(text.value == initialTextContent)
mainProcess.setWindowTitle(target,g_targetTitle) ;

//不应该基于此约束
if(!isWindowStartUp&&!_windowTitle.startsWith('*')&&!_ windowTitle.endsWith ('txt')){
让newWindowTitle = changedIndicatorChar + _windowTitle;
mainProcess.setWindowTitle(target,newWindowTitle);
}
});

在./app/index.html

 <!DOCTYPE html> 
< html lang = en>

< head>
<元字符集= UTF-8>
<元名称=视口内容=宽度=设备宽度,初始比例= 1.0。
< title>注释编辑器< / title>
< link rel =样式表 href =" style.css">
< / head>

< body>
< textarea id ="文本>< / textarea>
< / body>
< script src = ./ renderer.js< / script>

< / html>


解决方案

我建议您阅读我的电子简介首先发布,因为这是很好的知识。 / p>

有些事情在这里困扰您:


  1. 您创建的新窗口正在被垃圾回收,因为 let newWindow 函数createWindow()中。您需要在此功能的外部 中存储对这些窗口的引用。 示例

  2. 我不建议使用远程 nodeIntegration 。这些是易受安全问题影响的古老方法。 这篇文章也有一些很好的信息。

这里是您尝试做的事情的一个刺,以此作为起点。它不能完全处理多个窗口,但是我认为您可以对此进行扩展以开始使用!


main.js

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

//保留窗口对象的全局引用,否则,当JavaScript对象被垃圾回收时,窗口将自动关闭
//。
让胜利;

异步函数createWindow(){

//创建浏览器窗口。
win = new BrowserWindow({
width:800,
height:600,
webPreferences:{
nodeIntegration:false,//是Electron v5之后的默认值
contextIsolation:true,//防止原型污染
enableRemoteModule:false,//关闭远程
preload:path.join(__ dirname, preload.js)//使用预加载脚本
}
});

//加载应用程序
win.loadFile( ./ app / index.html);

//在关闭窗口时发出。
win.on( closed,()=> {
//取消引用窗口对象,通常,如果您的应用程序支持多窗口,则将Windows
//存储在数组中,这是
// //应该删除相应元素的时间。
win = null;
});

win.once( ready-to-show,()=> {
//现在显示当前窗口,当GUI已加载到窗口
win.show();
console.log( Window ready to show);

//设置窗口标题以指示当前文件未命名
//,并且需要保存
win.setTitle( Untitled-NoteEditor);
});
}

app.on( ready,createWindow);

ipcMain.on( toMain,(event,args)=> {
win.setTitle(args);
});

preload.js

  const {
contextBridge,
ipcRenderer
} = require( electron);

//公开受保护的方法,这些方法允许渲染器进程使用
// ipcRenderer而不暴露整个对象
contextBridge.exposeInMainWorld(
api, {
changeTitle:(title)=> {
ipcRenderer.send( toMain,title);
}
}
);

index.html

 <!doctype html> 
< html lang = en-US>
< head>
<元字符集= utf-8 />
< title>标题< / title>
< / head>
< body>
< script>
//更新窗口的标题
window.api.changeTitle( new title);
< / script>
< / body>
< / html>


I am new to Electron js, but when I run npm run start on the command line, the window seems to show sometimes, but also doesn't show sometimes. I have no idea what is wrong. I even tried removing the show : false part on the newly created BrowserWindow but, the same problem still occurs after running npm run start a few more time. When I package the app using Electron-packager I still face same problem

Edit: I found out that when I removed all the code in the renderer.js file, it works perfectly, but when I put the code back, it produces that problem, so probably the problem lies in the renderer process

In .app/main.js

  // const {menu_template, save_as_id} = require('./app-menu');
    const {app, BrowserWindow, Menu, dialog, ipcMain} = require('electron');
    const path = require('path');
    
    /**
     * Create a new window when called
     */
    function createWindow() {
      let x; // Window x cordinate or horizontal position on screen
      let y; // Window y cordinate or vertical position on screen
    
      if (BrowserWindow.getAllWindows().length >= 3) return;
    
      const focusedWindow = BrowserWindow.getFocusedWindow();
      if (focusedWindow) {
        let [posX, posY] = focusedWindow.getPosition();
        // Log the window position
        console.log(`   Window position
                    x : ${posX}, y : ${posY}`);
    
        if (!focusedWindow.isNormal())
          posX = posY = 50;
        // Randomly place the window on the screen
        const randX = Math.round(Math.random() * 20);
        const randY = Math.round(Math.random() * 20);
        const _randX = -randX - 5;
        const _randY = -randY - 5;
    
        x = posX + (randX <= 10 ? _randX : randX);
        y = posY + (randY <= 10 ? _randY : randY);
        // check if window is not fully visible
        const isOffScreen = x < 0 || y < 0;
        // then set the window in a specific position: 60
        if (isOffScreen)
          x = y = 60;
      }
    
      // Create a new browser window
      let newWindow = new BrowserWindow({
        x,
        y,
        minWidth: 300,
        minHeight: 300,
        show: false,
        webPreferences: {
          enableRemoteModule: true,
          nodeIntegration: true,
          preload: path.join(__dirname, 'preload.js')
        }
    
      });
    
      newWindow.on('closed', () => {
        newWindow = null;
      });
    
      newWindow.loadFile('./app/index.html');
      newWindow.once('ready-to-show', () => {
        // now show the current window, when GUI has been loaded to the   window
        newWindow.show();
        console.log('Window ready to show');
    
        // set the window title to indicate that the current file is unnamed
        // and needs to be saved
        newWindow.setTitle('Untitled - NoteEditor');
      });
    }
    
    // Create new window on application first startup
    app.whenReady().then(() => {
    //   Menu.setApplicationMenu(menu_template);
      createWindow();
    })
    
    /**
     * Simply sets the `targetWindow`'s title, to `title`
     * @param {*} targetWindow to recipient for title change
     * @param {*} title the new title of window
     */
    const setWindowTitle = (targetWindow, title) =>      targetWindow.setTitle(title);
    
    exports.createWindow = createWindow;
    // exports.chooseFile = chooseFile;
    exports.setWindowTitle = setWindowTitle

In ./app/renderer.js

 const {ipcRenderer, remote} = require("electron");
const mainProcess = remote.require('./main.js');
const app = remote.app;

var text = document.getElementById('text'); // The TextArea
var initialTextContent;
var g_targetTitle;


// when a key is pressed, display status showing that text has been edited and needs to be saved
text.addEventListener('keyup', () => {
  const target = remote.getCurrentWindow();
  let changedIndicatorChar = '*';
  let _windowTitle = target.getTitle();
  let isWindowStartUp = _windowTitle.startsWith('Untitled');

  // revert the window title to initial title if changes were removed
  if (text.value == initialTextContent)
    mainProcess.setWindowTitle(target, g_targetTitle);

  // should not set window title again based on this constraints  
  if (!isWindowStartUp && !_windowTitle.startsWith('*') && !_windowTitle.endsWith('txt')) {
    let newWindowTitle = changedIndicatorChar + _windowTitle;
    mainProcess.setWindowTitle(target, newWindowTitle);
  }
});

In ./app/index.html

 <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Note Editor</title>
        <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
        <textarea id="text"></textarea>
    </body>
    <script src="./renderer.js"></script>
    
    </html>

解决方案

I'd recommend you read my introduction to electron post first, as it's good knowledge.

A few things are biting you here:

  1. Your new windows you are creating are getting garbage collected because let newWindow is in function createWindow(). You'll want to store a reference to these windows outside this function. An example.
  2. I don't recommend using remote or nodeIntegration. These are old ways of doing things that are prone to security problems. This post has some good information too.

Here's a stab at what you are trying to do, use this as a starting point. It doesn't quite handle multiple windows, but I think you can expand on this to get you started!

main.js

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

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

async function createWindow() {

  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      enableRemoteModule: false, // turn off remote
      preload: path.join(__dirname, "preload.js") // use a preload script
    }
  });

  // Load app
  win.loadFile("./app/index.html");

  // Emitted when the window is closed.
  win.on("closed", () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null;
  });

  win.once("ready-to-show", () => {
    // now show the current window, when GUI has been loaded to the window
    win.show();
    console.log("Window ready to show");
    
    // set the window title to indicate that the current file is unnamed
    // and needs to be saved
    win.setTitle("Untitled - NoteEditor");
  });
}

app.on("ready", createWindow);

ipcMain.on("toMain", (event, args) => {
  win.setTitle(args);
});

preload.js

const {
    contextBridge,
    ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        changeTitle: (title) => {
            ipcRenderer.send("toMain", title);
        }
    }
);

index.html

<!doctype html>
<html lang="en-US">
<head>
    <meta charset="utf-8"/>
    <title>Title</title>
</head>
<body>
    <script>
        // Update the title of the window
        window.api.changeTitle("new title");
    </script>
</body>
</html>

这篇关于即使在新窗口上调用show()函数,Electron js桌面应用程序也不会显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆