You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在两个打开窗口间传递数据?项目管理器分类需求求助

实现项目分类选择模块的方案

我来帮你梳理这个功能的实现思路,下面用Electron + HTML/JS(桌面应用常用栈)和Python Tkinter两种常见方案来演示,你可以根据自己的技术栈调整。


核心逻辑梳理

不管用什么技术栈,这个功能的核心步骤都是一致的:

  • 主窗口触发模态选择窗口(模态窗口会阻止用户操作主窗口,确保选择完成后再返回)
  • 选择窗口内维护一个「选中分类」的状态变量,点击分类按钮时更新状态并高亮当前按钮
  • 点击「Choose」按钮时,将选中的分类值传递回主窗口,更新主窗口的文本框内容

方案1:Electron + HTML/JS 实现

1. 主窗口(main.html)

<!DOCTYPE html>
<html>
<head>
  <style>
    .category-input-group {
      display: flex;
      align-items: center;
      gap: 8px;
      margin: 20px;
    }
    #category-input {
      padding: 6px 10px;
      width: 200px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }
    .btn {
      padding: 6px 12px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      background: #0078d4;
      color: white;
    }
  </style>
</head>
<body>
  <div class="category-input-group">
    <label>Category:</label>
    <input type="text" id="category-input" readonly>
    <button class="btn" id="open-category-btn">(...)</button>
  </div>

  <script>
    const { ipcRenderer } = require('electron');

    // 打开分类选择窗口
    document.getElementById('open-category-btn').addEventListener('click', () => {
      ipcRenderer.send('open-category-window');
    });

    // 接收选择的分类并更新输入框
    ipcRenderer.on('category-selected', (event, category) => {
      document.getElementById('category-input').value = category;
    });
  </script>
</body>
</html>

2. 主进程(main.js)

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

let mainWindow;
let categoryWindow;

function createMainWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });
  mainWindow.loadFile('main.html');
}

// 创建分类选择窗口(模态)
function createCategoryWindow() {
  categoryWindow = new BrowserWindow({
    width: 400,
    height: 300,
    parent: mainWindow,
    modal: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });
  categoryWindow.loadFile('category-select.html');
}

// IPC事件监听
ipcMain.on('open-category-window', () => {
  createCategoryWindow();
});

ipcMain.on('send-category-to-main', (event, category) => {
  mainWindow.webContents.send('category-selected', category);
  categoryWindow.close();
});

app.whenReady().then(createMainWindow);

3. 分类选择窗口(category-select.html)

<!DOCTYPE html>
<html>
<head>
  <style>
    .category-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin: 20px;
    }
    .category-btn {
      padding: 8px 16px;
      border: 1px solid #ddd;
      border-radius: 4px;
      cursor: pointer;
      background: white;
    }
    .category-btn.active {
      background: #0078d4;
      color: white;
      border-color: #0078d4;
    }
    .confirm-btn {
      margin: 20px;
      padding: 8px 16px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      background: #0078d4;
      color: white;
    }
  </style>
</head>
<body>
  <h3 style="margin: 20px;">Choose a category</h3>
  <div class="category-buttons">
    <button class="category-btn">Web Development</button>
    <button class="category-btn">Mobile App</button>
    <button class="category-btn">Desktop App</button>
    <button class="category-btn">Data Analysis</button>
  </div>
  <button class="confirm-btn" id="choose-btn">Choose</button>

  <script>
    const { ipcRenderer } = require('electron');
    let selectedCategory = '';

    // 分类按钮点击逻辑:高亮+记录选中值
    const categoryButtons = document.querySelectorAll('.category-btn');
    categoryButtons.forEach(btn => {
      btn.addEventListener('click', () => {
        // 移除所有按钮的高亮
        categoryButtons.forEach(b => b.classList.remove('active'));
        // 高亮当前按钮
        btn.classList.add('active');
        // 记录选中的分类名称
        selectedCategory = btn.textContent;
      });
    });

    // 点击Choose按钮,传递分类到主窗口
    document.getElementById('choose-btn').addEventListener('click', () => {
      if (selectedCategory) {
        ipcRenderer.send('send-category-to-main', selectedCategory);
      } else {
        alert('Please select a category first!');
      }
    });
  </script>
</body>
</html>

方案2:Python Tkinter 实现

如果你用Python开发桌面应用,Tkinter是轻量且易用的选择:

import tkinter as tk
from tkinter import ttk, messagebox

class ProjectManagerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Project Manager")
        self.selected_category = ""

        # 主窗口布局
        self.main_frame = ttk.Frame(root, padding="20")
        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        ttk.Label(self.main_frame, text="Category:").grid(row=0, column=0, sticky=tk.W)
        self.category_entry = ttk.Entry(self.main_frame, width=30, state="readonly")
        self.category_entry.grid(row=0, column=1, padx=10)

        self.open_category_btn = ttk.Button(self.main_frame, text="(...)", command=self.open_category_window)
        self.open_category_btn.grid(row=0, column=2)

    def open_category_window(self):
        # 创建模态选择窗口
        self.category_window = tk.Toplevel(self.root)
        self.category_window.title("Choose a category")
        self.category_window.transient(self.root)
        self.category_window.grab_set()  # 模态化,阻止操作主窗口

        # 分类按钮框架
        category_frame = ttk.Frame(self.category_window, padding="20")
        category_frame.grid(row=0, column=0)

        categories = ["Web Development", "Mobile App", "Desktop App", "Data Analysis"]
        self.category_buttons = []
        for idx, cat in enumerate(categories):
            btn = ttk.Button(category_frame, text=cat, command=lambda c=cat: self.select_category(c))
            btn.grid(row=idx//2, column=idx%2, padx=5, pady=5)
            self.category_buttons.append(btn)

        # Choose按钮
        choose_btn = ttk.Button(self.category_window, text="Choose", command=self.confirm_category)
        choose_btn.grid(row=1, column=0, pady=10)

    def select_category(self, category):
        # 更新选中状态和高亮
        self.selected_category = category
        for btn in self.category_buttons:
            if btn["text"] == category:
                btn.config(style="Accent.TButton")
            else:
                btn.config(style="TButton")

    def confirm_category(self):
        if self.selected_category:
            # 更新主窗口输入框
            self.category_entry.config(state="normal")
            self.category_entry.delete(0, tk.END)
            self.category_entry.insert(0, self.selected_category)
            self.category_entry.config(state="readonly")
            self.category_window.destroy()
        else:
            messagebox.showwarning("Warning", "Please select a category first!")

if __name__ == "__main__":
    root = tk.Tk()
    app = ProjectManagerApp(root)
    root.mainloop()

关键细节说明

  • 模态窗口:一定要用模态窗口,避免用户在选择分类时操作主窗口,导致状态混乱
  • 状态管理:在选择窗口内维护selectedCategory变量,确保点击Choose时能拿到正确的选中值
  • 高亮逻辑:点击分类按钮时,要移除其他按钮的高亮样式,只保留当前按钮的,让用户清晰看到选中状态
  • 边界处理:要判断用户是否选中了分类,没选中时弹出提示,避免传递空值

内容的提问来源于stack exchange,提问作者HalionX Entertainment

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:27:44