您的当前位置:首页正文

我的Python心路历程 第十一期 (11.3 初探python调试总结之互相import引发的两个窗口问题)

2024-11-19 来源:个人技术集锦

背景

今日我的Python心路历程是 初探python调试总结之互相import引发的两个窗口问题)

分析

开门见山看问题截图如下:

很显然出现了两个一模一样的窗体,头大了。

方案

tk_win.py代码如下:

#!/usr/bin/python
# coding=UTF-8

import tkinter as tk

#互相import产生pyc文件,且没有if __name__ == '__main__':,导致编译报错
import function

#放在函数外面会导致function.time_clock()也会调用一次窗体创建的操作
t1 = tk.Tk()
t1.title('test')

def main0():
    t1.mainloop()
    print('main0()')
    
if __name__ == '__main__':
    main0()

function.py代码如下:

import time
import tk_win

def time_clock():
		//此处代码无关紧要,故暂不体现

如上两个文件,一目了然二者相互import了,而且tk_win.py部分代码是全局定义的,后来折磨明白这才是重点,加上不同的title后测试效果如下描述。
title不一样,运行效果如下图所示:

代码如下:

t1 = tk.Tk()
t1.title('test')

def main0():
    t1.title('main0')
    t1.mainloop()

将代码和截图拼在一起看就一目了然了,两个窗体,两个title对应,这样就大体明白怎么回事了。

如上所述,问题基本清楚了,取消相互import后是正常的,但窗体文件被import后就会出现这种现象,通过现象看本质,应该是main函数体内和体外两者形成了两个实体对象所导致的差异。

故此,解决问题的方式就是统一为同一个实体对象,让大家操作一个实体对象,这样就不会发生意外了,也就是保持一致性。

优化代码后,运行效果如下图所示:

现在好多了,统一到了同一个窗体,累的我满头大汗,不寒酸上代码,tk_window.py文件代码为:

#!/usr/bin/python
# coding=UTF-8

import tkinter as tk

#互相import产生pyc文件,且没有if __name__ == '__main__':,导致编译报错
import function
import index_data

#主窗体类定义
class mainWindow:
    root = None
    name = ''   #窗体名称
    width = 0   #窗体宽度
    height = 0  #窗体高度
    top_frame = None
    bottom_frame = None
    left_frame = None
    centre_frame = None

    def __init__(self, name):
        self.name = name

    def inition(self):
        self.root = tk.Tk()  # 创建主窗口

        # s = graphic0.Show()  # Show实例化
        screenWidth = self.root.winfo_screenwidth()  # 获取屏幕宽的分辨率
        screenHeight = self.root.winfo_screenheight()
        x, y = int(screenWidth / 4), int(screenHeight / 4)  # 初始运行窗口屏幕坐标(x, y),设置成在左上角显示
        self.width = int(screenWidth / 2)  # 初始化窗口是显示器分辨率的1.2分之一
        self.height = int(screenHeight / 2)
        self.root.geometry('{}x{}+{}+{}'.format(self.width, self.height, x, y))  # 窗口的大小跟初始运行位置
        self.root.title(self.name) #显示主窗口1
        # root.resizable(0, 0)  # 固定窗口宽跟高,不能调整大小,无法最大窗口化
        self.root.iconbitmap('favicon.ico')  # 窗口左上角图标设置,需要自己放张图标为icon格式的图片文件在项目文件目录下
        self.root.state('zoomed')  # 窗口最大化处理

        #设置底部栏高度,尝试几次后发现20比较合理
        topHeight = 20
        # 构建上方菜单栏目框架
        self.top_frame = tk.Frame(self.root, width=self.width, height=topHeight, relief=tk.SUNKEN, bg='#353535', bd=5,
                             borderwidth=4)
        self.top_frame.pack(fill=tk.BOTH, side=tk.TOP, expand=0)

        # 构建底部状态栏目框架
        self.bottom_frame = tk.Frame(self.root, width=self.width, height=topHeight, relief=tk.SUNKEN, bg='#353535', bd=5,
                                borderwidth=4)
        self.bottom_frame.pack(fill=tk.BOTH, side=tk.BOTTOM, expand=0)

        #函数外体被执行多次的原因是自身和import的时候也会被执行
        print ('width=%d.' % self.width)
        print ('height=%d.' % self.height)
        print ('screenWidth0=%d.' % screenWidth)
        print ('screenHeight0=%d.' % screenHeight)

        #设置左部栏宽度,尝试几次后发现20比较合理
        leftWidth = 20
        # 构建左边功能栏目框架
        self.left_frame = tk.Frame(self.root, width=leftWidth, height=self.height-topHeight*2, relief=tk.SUNKEN, bg='#353535', bd=5, borderwidth=4)
        self.left_frame.pack(fill=tk.BOTH, side=tk.LEFT, expand=0)

        #设置左部栏宽度,尝试几次后发现20比较合理
        centerHeight = self.height - topHeight*2
        # 构建中间显示栏目框架
        self.centre_frame = tk.Frame(self.root, width=self.width-leftWidth, height=centerHeight, relief=tk.SUNKEN, bg='#353535', bd=5,
                                borderwidth=4)
        self.centre_frame.pack(fill=tk.BOTH, expand=1)

# **********************************************************************************************************************
# 全局变量定义
mWin = mainWindow(u'GP量化评估分析')
# 全局变量设置结束
**********************************************************************************************************************

#窗体界面实现函数
def uiFunc():
    # 构建各个框架的标签或按钮
    top_label = tk.Label(mWin.top_frame, text='菜单栏目', bd=1)
    top_label.pack()

    bottom_label = tk.Label(mWin.bottom_frame, text='状态栏目', bd=1)
    bottom_label.pack(side=tk.LEFT)

    # 在状态栏目添加系统时钟功能
    function.time_clock()

    #定义按钮并和对应功能函数关联起来
    left_button1 = tk.Button(mWin.left_frame, text='全景', bd=1, command=index_data.stockindex_function)
    left_button1.pack()


    # 显示主窗口2
    mWin.root.mainloop()
    print ('screenWidth=%d.' % mWin.width)
    print ('screenHeight=%d.' % mWin.height)

#main执行入口
if __name__ == '__main__':
    mWin.inition()
    uiFunc()

function.py代码如下:

import time
import tk_window

def time_clock():
		//此处代码无关紧要,故暂不体现
综上所述,如果在main函数体外直接写的代码会在被import的时候默认再执行一次,所以全局定义即消耗公共资源又会出问题,所以把握不好跟局部的关系,容易搞混。

参考:
1、
2、

显示全文