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

Tkinter通过exec调用外部Python程序时组件显示位置异常问题咨询

问题原因
  • 核心原因是Timer类实例化时没有传入你在prog2中创建的窗口对象作为父容器:你调用的是Timer(),而__init__方法的window参数默认值为None,此时tkinter会自动将当前程序的主窗口(也就是main.py的窗口)作为这些未指定父容器组件的父级,因此ButtonShow、progress、outText会显示在main窗口中。单独运行prog2时,程序只有prog2自己创建的这一个Tk窗口,所以就算未传入参数,默认父容器也是该窗口,因此所有组件显示正常。
  • 额外不规范点:你通过exec运行prog2的代码时,两个脚本共享tkinter上下文,main.py已经存在一个主Tk实例,prog2中再创建tk.Tk()属于错误用法,同一个tkinter应用不应该存在多个Tk实例,副窗口应该用Toplevel实现;同时你的代码存在导入规则混用的问题,from tkinter import *之后不应该再用tk.前缀调用组件,且缺失action_VNC变量定义,单独运行本应报错,是exec共享了main的上下文才没有触发报错。
修复方案

方案1:最小改动修复当前问题

仅修改prog2.py末尾的Timer实例化代码,传入你创建的window对象即可:
把Timer()改为Timer(window=window)

方案2:更规范的完整修复(推荐)

1. 重写main.py,放弃exec执行方式,改为导入函数调用

import tkinter as tk

def open_prog2():
    import prog2
    prog2.create_window()

# 明确指定main窗口的主实例
root = tk.Tk()
buttonHMI = tk.Button(root, text="Program HMI", width=15, font=("Arial", 14), command=open_prog2)
buttonHMI.grid(column=0, row=3, columnspan=1, padx=20, pady=10, sticky=tk.W)

root.mainloop()

2. 重写prog2.py,封装为独立函数,副窗口用Toplevel实现

import tkinter as tk
from tkinter import ttk

def create_window():
    # 副窗口使用Toplevel,不要新建Tk实例
    window = tk.Toplevel()
    # 补充缺失的变量定义
    action_VNC = tk.BooleanVar()

    CB1 = tk.Checkbutton(window, text="Enable VNC", font=("Arial", 12), variable=action_VNC)
    CB1.grid(row=0, sticky=tk.W, padx=10)
    CB1.configure(bg='#34aeeb')

    ButtonClose= tk.Button(window, text="Close", width=20, font=("Arial", 14), command=window.destroy)
    ButtonClose.grid(columnspan=2, column = 3, row=9, sticky=tk.W, padx=10, pady=10)

    class Timer:
        def __init__(self, window):
            self.sv = tk.StringVar()
            # 所有组件明确指定父容器为传入的window
            ButtonShow = tk.Button(window, text="Program HMI", width=20, font=("Arial", 14), command=self.actions)
            ButtonShow.grid(columnspan=2, row=9, column = 0, sticky=tk.W, padx=10, pady=10)

            progress = ttk.Progressbar(window, orient = tk.HORIZONTAL, length = 500, mode = 'determinate')
            progress.grid(row=10, columnspan = 4, sticky=tk.W, padx=10, pady=10)

            outText = tk.Text(window, width=50, height=20, wrap=tk.WORD)
            outText.grid(row=11, columnspan=4, padx=10)
        
        def actions(self):
            print("action")

    # 实例化时明确传入窗口对象
    Timer(window)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:45:03