【自由生长的Python】为了能有资格放弃,使用toplevel,弹出一个窗体【04】

目标

利用toplevel,重写根(root)窗体,将显示图片的功能显示在一个toplevel弹出窗口中。

  • 重写root;
  • 修改HelloTkinter,封装一个弹出窗体;
  • 整体代码打个标签:V1.2.2。
    操作如视频所示:

【自由生长的python】利用toplevel做一个弹窗

总结

在实现目标的过程中,主要遇到问题就是在弹出toplevel时,隐藏根窗体;在退出toplevel窗体时,显示根窗体。可以注意一下main.py文件中这几个函数的调用,:

		self.root.withdraw() 
        
        myImageViewer = MyImageViewer(self.root)
        self.root.wait_window(myImageViewer.top)
        
        self.root.deiconify()
        self.root.update()    

最终可通过可以使用下面四行命令,体验一下程序运行的效果

git clone https://github.com/kamigo2018/myTkinter.git
cd myTkinter
git checkout V1.2.2 
python main.py

简单说一下要做啥

1、设计根(root)窗体

在这里插入图片描述
根窗体上就放上几个按键,提供不同的功能。其中除了显示图片这个功能,其他功能还没实现。“UDP程序”和“TCP程序”准备后面分别实现两个例子,简单展示一下socket通讯。“还没想好”,是真没想好还要干啥。

2、显示图片功能

在这里插入图片描述
没错,看起来和原来的窗体没啥区别。其实真的没有太大的区别,就是将原来的窗体在一个新的toplevel组件中显示出来了,没啥新东西。

再说一下都是咋做的

1、根窗体

新建main.py ,模仿HelloTkinter,为这个新应用创建 Application类。
在这里插入图片描述

  1. create函数
    在Application类中,创建create函数,用来展示整个界面。这个根窗口设计成宽度固定,长度可变,安放四个按钮,一个退出按钮的样子:
    def create(self):        
        '''
        将主界面设计成一个竖条形状,分成两个区域:自主研发功能区+退出按键区。
        自主研发功能区:目前里面放置多个功能按键,后续按下每一个按键弹出一个界面。
        退出按键区:就放置一个按键,用来退出。
        '''
        self.frameFont = tkFont.Font(family='微软雅黑',size = '16')
        
        # 整个区域划分成两个窗体,一个用来放功能按键,一个专门用来放退出按键。
        # 我还想给这个中间加条线。现在还不会。不过应该可以加,如何能让他明显一点?
        self.funcFrame = tk.Frame(self.root);
        self.separatorLine = ttk.Separator(self.root,orient='horizontal',style='red.TSeparator')
        self.quitFrame = tk.Frame(self.root);
        
        # ==start==
        # 设置上面两部分区域的框架,容纳其他显示在顶层页面的组件
        self.funcFrame.grid(row = 0, column=0, sticky='NWES')
        self.separatorLine.grid(row = 1, column=0, sticky='NWES') # 这条分割线没有显示出来,没起作用?
        self.quitFrame.grid(row = 2, column=0, sticky='NWES')
        
        tk.Grid.rowconfigure(self.root,0,weight=15)
        # tk.Grid.rowconfigure(self.root,1,weight=15) #还是看不到这条线
        tk.Grid.rowconfigure(self.root,2,weight=1) # 甚至应该考虑这个窗体是否应该固定大小
        tk.Grid.columnconfigure(self.root,0,weight = 1)
        # ==end==
        
        # 实例化在funcFrame里面的4个函数按键
        self.button1 = tk.Button(self.funcFrame,text='显示图片',font=self.frameFont, command = self.func1)
        self.button2 = tk.Button(self.funcFrame,text='UDP程序',font=self.frameFont, command = self.func2)
        self.button3 = tk.Button(self.funcFrame,text='TCP程序',font=self.frameFont, command = self.func3)
        self.button4 = tk.Button(self.funcFrame,text='还没想好',font=self.frameFont, command = self.func4)
        
        # ==start==
        # 设置以上4个按键的位置
        self.button1.grid(row=0,column=0,rowspan=1,sticky='NWES')
        self.button2.grid(row=1,column=0,rowspan=1,sticky='NWES')
        self.button3.grid(row=2,column=0,rowspan=1,sticky='NWES')
        self.button4.grid(row=3,column=0,rowspan=1,sticky='NWES')
        
        tk.Grid.rowconfigure(self.funcFrame,0,weight=1)
        tk.Grid.rowconfigure(self.funcFrame,1,weight=1)
        tk.Grid.rowconfigure(self.funcFrame,2,weight=1)
        tk.Grid.rowconfigure(self.funcFrame,3,weight=1)
        
        tk.Grid.columnconfigure(self.funcFrame,0,weight=1)
        # ==end==
        
        # 实例化一个退出按键
        self.buttonQuit = tk.Button(self.quitFrame,text='退 出',font=self.frameFont)       
        self.buttonQuit.config(bg='gray',fg='black',command=self.quit)
        
        # ==start==
        # == 设置quitFrame中按键的大小和位置 ==
        self.buttonQuit.grid(row=0,column=0,sticky='NWES')
        tk.Grid.rowconfigure(self.quitFrame,0,weight=1)        
        tk.Grid.columnconfigure(self.quitFrame,0,weight=1)        
        # ==end==
        pass

和之前一样,还是使用grid布局方式,组件自适应容器窗体的形变。

  1. 按键功能函数
    最简单的退出功能,在按下“退出”键时触发。就是调用root窗体的destroy函数。遗留一个问题:虽然 root.quit() 和 root.destroy() 两个函数都可以实现退出功能,但是这两个功能有什么区别?我没有深究,这个当做一个问题,先留下来。
    def quit(self):
        # self.root.quit()
        self.root.destroy() # 这两个有什么区别?

比较麻烦的“显示图片”功能。这里新建了一个MyImageViewer的实例,通过这个实例新建了一个toplevel的组件,当做新的容器,显示图片。在创建这个窗体之前,记录了原始根窗体的大小,位置信息。并利用 root.withdraw() 和 root.deiconify(), root.update() 隐藏和显示根窗体。利用 wait_window(myImageViewer.top) 展示“显示图片”窗体。

    def func1(self):
        # 这里需要隐藏主界面,弹出对应功能界面。操作完成后,退出功能界面,回到主界面。
        # 保存原始窗体的大小,参考:
        # https://www.daniweb.com/programming/software-development/threads/322818/tkinter-window-size
        # https://www.imooc.com/wenda/detail/608947 
        
        # 主窗体的宽高尺寸
        winWidth = self.root.winfo_width()
        winHeight = self.root.winfo_height()
        
        # 主窗体在屏幕的位置
        screenX = self.root.winfo_x()
        screenY = self.root.winfo_y()
        
        self.root.withdraw()        
        
        myImageViewer = MyImageViewer(self.root)
        self.root.wait_window(myImageViewer.top)
        
        self.root.deiconify()
        self.root.update()        
        self.root.geometry(("{}x{}+{}+{}").format(winWidth,winHeight,screenX,screenY))

其他函数,例如func2,没有实质内容,就不说了。

    def func2(self):
        pass
        #print("UDP")

2、显示图片

之前的版本中,显示图片的功能,作为在根窗体中的主要功能,通过几个frame直接展示出来。这次,通过toplevel组件,重新组织这些frame框体。由于是重新组织,不是开发,所以相对来说就是复制并修改原有的的frame组件代码,主要修改内容,就是修改frame的父容器。
在HelloTkinter.py中,新建 MyImageViewer 类,基本上和原有的Appcliation很像。
在这里插入图片描述
看一下初始化函数,这里看到,我们实例化了一个toplevel组件,命名为top。top的父容器就是我们的根容器。

    def __init__(self,master):
        # 这里的 master 应该是根应用的tk.Tk()组件。        
        # 而这个类要产生一个toplevel组件,用来展示一个单独的功能窗体。
                
        self.master = master
        
        self.top = tk.Toplevel(self.master)
        
        tk.Grid.rowconfigure(self.top,0,weight=1)
        tk.Grid.columnconfigure(self.top,0,weight=1)
        
        self.imageResizeRatio = 100
        self.imageFlag = 0
        
        self.create()

之后,这个top就作为显示一个新的父窗体,容纳我们的的菜单栏,输入窗体,显示窗体。

    def create(self):
        pass
        # 干什么?显示图片,有菜单栏,有展示窗体,有输入窗体。
        # 创建菜单栏
        self.createMenu()
        
        # 创建显示文字的text widget 的Frame
        self.createShowResultFrame()
        
        # 创建输入文字的Frame
        self.createInputFrame()
        
    def createMenu(self):
        self.menuBar = tk.Menu()
        # menuBar的父窗体就变成了top。
        self.top.config(menu=self.menuBar)
        
        ... ... # 具体功能和之前版本中的一样,所以这里就不展示了。

打上标签

相比V1.2.1,程序有了新的根窗体,所以算是一个比较大的改变,这里打上标签:V1.2.2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值