主頁 > 軟體工程 > 打開新視窗后如何銷毀視窗?

打開新視窗后如何銷毀視窗?

2021-11-06 16:15:22 軟體工程

我正在使用 tkinter 開發一款名為“Flag Quiz”的游戲。我有一個名為的腳本mainmenu,我可以在其中選擇簡單模式和困難模式。如果我單擊其中一個按鈕,最近的mainmenu視窗就會消失,并會打開一個新的 tkinter 視窗。

這是我的mainmenu腳本:

from tkinter import *
import tkinter as tk
from hardmode import HardApp
from easymode import EasyApp

class TitleScreen(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title('Flag Quiz')
        self.geometry('600x600')
        self.resizable(0,0)
        self.make_widgets()



    def make_widgets(self):
        self.background = PhotoImage(file = './background.png')
        self.label = Label(self, image=self.background)
        self.label.place(x=0, y=0, relwidth=1, relheight=1)
        self.easy = Button(self, text="Easy Mode", height=2, width=6, font=('default', 20), command=self.play_easy)
        self.hard = Button(self, text="Hard Mode", height=2, width=6, font=('default', 20), command=self.play_hard)
        self.easy.place(relx=0.5, rely=0.45, anchor=CENTER)
        self.hard.place(relx=0.5, rely=0.55, anchor=CENTER)

    def play_easy(self):
        self.withdraw()
        self.app = EasyApp()
        #self.app.start()

    def play_hard(self):
        self.withdraw()
        self.app = HardApp()
        #self.app.start()




    def start(self):
        self.mainloop()

TitleScreen().start()

這是我的簡單模式腳本:

import tkinter as tk
from tkinter import *
import random
import os
import json

class EasyApp(tk.Toplevel):
    def __init__(self):
        super().__init__()
        self.title('Flag Quiz')
        self.geometry('')
        self.resizable(0,0)
        self.score = 0
        self.create_widgets()

    def create_widgets(self):
        # variables
        self.user_guess = StringVar(self)
        self.text = StringVar(self)
        self.text.set(" ")

        # initial image
        self.scoretext = Label(self, text="Score: ").pack(side='top', fill='x')
        self.scorevalue = Label(self, text=self.score).pack(side='top', fill='x')
        self.file = random.choice(os.listdir('pngs'))
        self.randimg = PhotoImage(file='pngs/{}'.format(self.file))
        self.randimg = self.randimg.subsample(2, 2)
        self.panel = Label(self, image=self.randimg)
        self.panel.pack()

        self.country, self.ext = self.file.split('.')
        self.countries = self.load_lookup()
        self.countryname = [country for country in self.countries if country['alpha2'] == self.country]

        self.s = []
        for i in range(0,3):
            country = random.choice(self.countries)
            self.s.append(country['de'])

        self.s.append(self.countryname[0]['de'])
        random.shuffle(self.s)

        self.btndict = {}
        for i in range(4):
            self.btndict[self.s[i]] = Button(self, text=self.s[i], height=2, width=35, font=('default', 20), command=lambda j=self.s[i]: self.check_input(j))
            self.btndict[self.s[i]].pack()


    def check_input(self, d):
        if d != self.countryname[0]['de']:
            print("Falsch")
        else:
            self.score  = 5
            for widget in self.winfo_children():
                widget.destroy()
            self.create_widgets()



    def load_lookup(self):
        with open('lookup.json') as file:
            self.obj = file.read()

        self.countryobj = json.loads(self.obj)
        return self.countryobj

    # def start(self):
    #     self.mainloop()

單擊關閉按鈕(windows/osx 上用于關閉視窗的默認按鈕)后,我的簡單模式應用程式中的視窗消失了,但 PyCharm 說我的程式仍在運行。

I made some investigations and removed the self.withdraw() function in the function play_easy(self) in my mainmenu script. So now the mainmenu is still open after I click on the easy mode button. If I'm closing both windows now, the program fully ends. Replacing self.withdraw() with self.destroy() is not working. The main menu is closed, but a new empty window opens instead.

Any suggestions on how to handle this problem so that my program fully ends if I click the close button within the easy/hard mode window?

uj5u.com熱心網友回復:

您有兩個視窗 - 使用創建的主視窗Tk和使用創建的子視窗Toplevel當您close button用來關閉主視窗時,它也應該關閉所有子視窗,但是當您關閉子視窗時,它不會關閉主視窗(父視窗)而只關閉自己的子視窗 - 因為通常再次顯示主視窗以選擇其他視窗很有用選項并再次打開子視窗。


其中一種方法是destroy首先視窗并使用Tk創建新視窗。

但是在這種方法中,您不能使用第二個視窗中的某個按鈕回傳到第一個視窗 - 有時這可能是問題。即使您再次創建第一個視窗,它也不會記住以前的值(如果您有一些Entry或其他小部件來設定值)

# from tkinter import *  # PEP8: `import *` is not preferred`
import tkinter as tk

class EasyApp(tk.Tk):  # use `Tk` instead of `Toplevel`

    def __init__(self):
        super().__init__()
        self.scoretext = tk.Label(self, text="EasyApp")
        self.scoretext.pack()

    #def start(self):
    #    self.mainloop()

class TitleScreen(tk.Tk):
    
    def __init__(self):
        super().__init__()
        self.button = tk.Button(self, text="Easy Mode", command=self.play_easy)
        self.button.pack()

    def play_easy(self):
        self.destroy()  # destroy current window
        self.app = EasyApp()

    def start(self):
        self.mainloop()

TitleScreen().start()

另一種方法是在您使用時使用并在此函式主視窗()中self.wm_protocol("WM_DELETE_WINDOW", self.on_close)執行函式on_closeclose buttondestroymaster

這樣您仍然可以使用Button回傳到主視窗,它會記住以前的內容。

# from tkinter import *  # PEP8: `import *` is not preferred`
import tkinter as tk

class EasyApp(tk.Toplevel):  # still use `Toplevel`

    def __init__(self, master):  # send main window as master/parent
        super().__init__(master)  # it will also set `self.master = master`
        
        self.scoretext = tk.Label(self, text="EasyApp")
        self.scoretext.pack()
        
        self.button = tk.Button(self, text="Go Back", command=self.go_back)
        self.button.pack()

        # run `on_close` when used `close button`
        #self.protocol("WM_DELETE_WINDOW", self.on_close)
        self.wm_protocol("WM_DELETE_WINDOW", self.on_close)
        
    def go_back(self):
        self.destroy()           # destroy only current window
        self.master.deiconify()  # show again main window

    def on_close(self):
        self.destroy()         # destroy current window
        self.master.destroy()  # destroy main window
        
class TitleScreen(tk.Tk):
    
    def __init__(self):
        super().__init__()

        self.entry = tk.Entry(self)
        self.entry.pack()
        self.entry.insert('end', "You can change text")
        
        self.button = tk.Button(self, text="Easy Mode", command=self.play_easy)
        self.button.pack()

    def play_easy(self):
        self.withdraw()  
        self.app = EasyApp(self)  # send main window as argument

    def start(self):
        self.mainloop()

TitleScreen().start()

uj5u.com熱心網友回復:

這是一個相當簡單的架構,可以做你想做的事。一個應用程式類派生自Tk(),它隱藏了它通常顯示的默認“根”視窗,它顯示的所有視窗都是Toplevel我命名的自定義子類的子類BaseWin

此類只是一個Toplevel將其洗掉(關閉)協議設定為呼叫名為on_close(). 這個額外的方法只是在退出應用程式mainloop()導致它終止之前銷毀當前視窗

TitleScreen創建應用程式類的實體時,會自動顯示第一個視窗(類的實體)。這個視窗有兩個,Button一個標記為Easy Mode另一個標記為Hard Mode當單擊其中一個時,在Toplevel通過呼叫其destroy()方法洗掉當前視窗后,將創建適當子類的實體

mainmenu.py

import tkinter as tk
from tkinter.constants import *
from tkinter import font as tkfont
from basewin import BaseWin
from easymode import EasyApp
from hardmode import HardApp


class SampleApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title('Flag Quiz')
        self.geometry('600x600')
        self.resizable(FALSE, FALSE)
        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold")
        self.withdraw()  # Hide default root Tk window.
        startpage = TitleScreen(self.master)
        self.mainloop()


class TitleScreen(BaseWin):
    def __init__(self, master):
        super().__init__(master)
        self.make_widgets()

    def make_widgets(self):
        label = tk.Label(self, text="This is the Start Page", font=self.master.title_font)
        label.pack(side="top", fill="x", pady=10)

        self.easy = tk.Button(self, text="Easy Mode", font=('default', 20),
                              command=self.play_easy)
        self.hard = tk.Button(self, text="Easy Mode", font=('default', 20),
                              command=self.play_hard)
        self.easy.pack()
        self.hard.pack()

    def play_easy(self):
        self.destroy()
        self.app = EasyApp(self.master)

    def play_hard(self):
        self.destroy()
        self.app = HardApp(self.master)


if __name__ == '__main__':
    SampleApp()

basewin.py

import tkinter as tk
from tkinter.constants import *


class BaseWin(tk.Toplevel):
    def __init__(self, master):
        super().__init__(master)
        self.protocol("WM_DELETE_WINDOW", self.on_close)

    def on_close(self):
        self.destroy()      # Destroy current window
        self.master.quit()  # Quit app.

easymode.py

import tkinter as tk
from tkinter.constants import *
from basewin import BaseWin


class EasyApp(BaseWin):
    def __init__(self, master):
        super().__init__(master)
        self.title('Flag Quiz')
        self.resizable(FALSE, FALSE)
        self.make_widgets()

    def make_widgets(self):
        label = tk.Label(self, text="This is the Easy App", font=self.master.title_font)
        label.pack(side="top", fill="x", pady=10)

hardmode.py

import tkinter as tk
from tkinter.constants import *
from basewin import BaseWin


class HardApp(BaseWin):
    def __init__(self, master):
        super().__init__(master)
        self.title('Flag Quiz')
        self.resizable(FALSE, FALSE)
        self.make_widgets()

    def make_widgets(self):
        label = tk.Label(self, text="This is the Hard App", font=self.master.title_font)
        label.pack(side="top", fill="x", pady=10)

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/350132.html

標籤:python tkinter

上一篇:子小部件的子小部件未顯示-為什么以及如何修復它?

下一篇:筆記本中的條目-Tkinter

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more