Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Tk:如何创建自定义消息框_Python_Tkinter_Messagebox - Fatal编程技术网

Python Tk:如何创建自定义消息框

Python Tk:如何创建自定义消息框,python,tkinter,messagebox,Python,Tkinter,Messagebox,请给我一些建议 自定义消息框要求包括: 是模态的(实现的) 当显示消息框时,消息框位于前面,无法操作其他TK对象 等待消息框的返回值 我想等待消息框输入,然后再进行下一个操作(显示/隐藏小部件等) 我想继续处理申请(已实现) 原始Tk对象希望继续使用after方法进行常规处理 我想采用我自己的设计(已实现) 为了统一设计 -执行结果- 如果关闭消息框,将显示错误。 在关闭self.MainWindow\u obj之前,它不会继续执行Btn\u Messagebox\u clicked方法

请给我一些建议

自定义消息框要求包括:

  • 是模态的(实现的)

    当显示消息框时,消息框位于前面,无法操作其他TK对象

  • 等待消息框的返回值

    我想等待消息框输入,然后再进行下一个操作(显示/隐藏小部件等)

  • 我想继续处理申请(已实现)

    原始Tk对象希望继续使用after方法进行常规处理

  • 我想采用我自己的设计(已实现)

    为了统一设计

  • -执行结果-

    如果关闭消息框,将显示错误。 在关闭self.MainWindow\u obj之前,它不会继续执行Btn\u Messagebox\u clicked方法中的第二行。 我不知道为什么我会出错。此外,如果关闭消息框,您将不知道它为什么不会返回

    invalid command name "2291801753672dialog_mouse_release"
        while executing
    "2291801753672dialog_mouse_release 105 1 ?? ?? ?? 264 103442140 ?? 22 6 ?? 0 ?? ?? .!frame3.!button2 5 438 422 ??"
        invoked from within
    "if {"[2291801753672dialog_mouse_release 105 1 ?? ?? ?? 264 103442140 ?? 22 6 ?? 0 ?? ?? .!frame3.!button2 5 438 422 ??]" == "break"} break"
        (command bound to event)
    
    -代码-

    将tkinter作为tk导入
    从tkinter导入ttk
    从PIL导入图像、ImageTk、ImageDraw、ImageFont
    类自定义对话框(对象):
    定义初始化(自):
    self.title_bar_color='#8FAADC'
    self.item_ground_color='whitesmoke'
    self.background_color='#D9D9D9'
    self.select_bar_color='#BDD7EE'
    self.isDrag_DlgMotion=False
    self.drag_dx=0
    self.drag_dy=0
    def对话框\u左键单击(自身,事件):
    dialog\u x=self.dev\u dialog.winfo\u rootx()
    dialog\u y=self.dev\u dialog.winfo\u rooty()
    point_x=self.dev_dialog.winfo_pointerx()
    point_y=self.dev_dialog.winfo_pointery()
    dx=点x-对话框x
    dy=点y-对话框y
    如果(dx>=0,dx=0,dy 3:
    返回
    root=ttk.tkinter.Tk()
    #root=tk.Toplevel(父级)
    #root.overrideredirect(True)
    super()。\uuuu init\uuuuu()
    self.box\u state=状态
    self.box_message=消息
    self.box\u title=标题
    W=0
    H=1
    self.dlg_size=[400200]
    self.title\u bar\u width=self.dlg\u大小[W]
    self.title\u bar\u height=40
    self.btn\u bar\u高度=42
    self.btn_32x32_尺寸=42
    self.row\u高度=28
    self.btn\u行高度=32
    self.frm_空间=10
    self.parent=parent
    self.CreateDialog(根目录)
    root.wait\u窗口(root)
    #root.mainloop()
    def CreateDialog(自,根):
    W=0
    H=1
    如果self.parent!=无:
    self.parent.update_idletasks()
    ww=self.parent.winfo_screenwidth()
    wh=self.parent.winfo_屏幕高度()
    x=self.parent.winfo_rootx()
    y=self.parent.winfo_rooty()
    parent\u w=self.parent.winfo\u width()
    parent_h=self.parent.winfo_height()
    parent_x=self.parent.winfo_x()
    parent_y=self.parent.winfo_y()
    其他:
    root.update_idletasks()
    ww=root.winfo_屏幕宽度()
    wh=root.winfo_屏幕高度()
    x=root.winfo_rootx()
    y=root.winfo_rooty()
    父节点w=root.winfo\u宽度()
    parent_h=root.winfo_height()
    parent_x=root.winfo_x()
    parent_y=root.winfo_y()
    self.dev_dialog=root
    dialog=self.dev\u对话框
    对话框。重写直接(True)
    dlg_x=int((父对象x+父对象w)-(self.dlg_大小[w]/2))
    dlg_y=int((parent_y+parent_h)-(self.dlg_size[h]/2))
    如果dlg_x<0:dlg_x=0
    如果dlg_y<0:dlg_y=0
    几何体(“{}x{}+{}+{}.”格式(self.dlg_size[W],self.dlg_size[H],dlg_x,dlg_y))
    self.Title_Bar=tk.Frame(
    对话
    宽缓",,
    bg=self.title\u bar\u color,
    )
    self.Title\u Label=tk.Label(
    self.Title_栏,
    bg=self.title\u bar\u color,
    text=self.box\u标题,
    )
    dialog.bind(“”,self.dialog\u左键单击)
    dialog.bind(“”,self.dialog\u mouse\u move\u on)
    dialog.bind(“”,self.dialog\u鼠标\u释放)
    self.MsgArea_frame=tk.frame(
    对话
    宽缓",,
    bg=自选择条颜色,
    )
    self.message_frame=tk.frame(
    self.MsgArea_框架,
    宽缓",,
    bg=自身项目地面颜色,
    )
    self.label_message=tk.label(
    self.message_框架,
    bg=自身项目地面颜色,
    text=self.box\u消息,
    )
    self.BtnArea_frame=tk.frame(
    对话
    宽缓",,
    bg=自身项目地面颜色,
    )
    self.btn_ok=tk.按钮(
    self.BtnArea_框架,
    bg=自身项目地面颜色,
    text='确定',
    command=lambda:self.btn\u msgbox\u单击(1),
    )
    self.btn_yes=tk.按钮(
    self.BtnArea_框架,
    bg=自身项目地面颜色,
    text='是',
    command=lambda:self.btn\u msgbox\u单击(1),
    )
    self.btn_no=tk.按钮(
    self.BtnArea_框架,
    bg=自身项目地面颜色,
    text='否',
    command=lambda:self.btn\u msgbox\u单击(2),
    )
    self.btn_cancel=tk.按钮(
    self.BtnArea_框架,
    bg=自身项目地面颜色,
    text='取消',
    command=lambda:self.btn\u msgbox\u单击(3),
    )
    frm_空间=self.frm_空间
    msg_frm_w=4
    btn_fram_h=36
    消息\u区域\u h=self.dlg\u大小[h]-self.title\u条高度-frm\u空间*2-btn\u框架高度
    #框架
    自标题栏位置(
    x=0,y=0,
    宽度=自标题栏_
    
    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import tkinter as tk
    from tkinter import ttk
    
    from tkinter import messagebox
    
    from PIL import Image,ImageTk,ImageDraw,ImageFont
    
    import datetime
    
    class CustomDialog(object):
        def __init__(self):
    
            self.title_bar_color = '#8FAADC'
            self.item_ground_color = 'whitesmoke'
            self.background_color = '#D9D9D9'
            self.select_bar_color = '#BDD7EE'
    
            self.isDrag_DlgMotion = False
            self.drag_dx = 0
            self.drag_dy = 0
    
        def dialog_left_click(self,event):
            dialog_x=self.dev_dialog.winfo_rootx()
            dialog_y=self.dev_dialog.winfo_rooty()
            point_x=self.dev_dialog.winfo_pointerx()
            point_y=self.dev_dialog.winfo_pointery()
    
            dx = point_x - dialog_x
            dy = point_y - dialog_y
    
            if (dx >= 0 and dx <= self.title_bar_width) and (dy >= 0 and dy <= self.title_bar_height):
                self.drag_dx = dx
                self.drag_dy = dy
                self.isDrag_DlgMotion = True
            return
    
        def dialog_mouse_move_on(self,event):
            if self.isDrag_DlgMotion:
                X = event.x_root - self.drag_dx
                Y = event.y_root - self.drag_dy
                self.dev_dialog.geometry('+{0}+{1}'.format(X, Y))
                pass
            return
    
        def dialog_mouse_release(self,event):
            if self.isDrag_DlgMotion:
                self.isDrag_DlgMotion = False
            return
    
    class CommonMessageBoxDialog(CustomDialog):
        def __init__(self,title,message,state,parent = None):
            self.return_state = None
            self.isDestroy = False
    
            if not isinstance(title,str) or not isinstance(message,str) or not isinstance(state,int):
                return
            if state < 1 or state > 3 :
                return
    
            root = ttk.tkinter.Tk()
    
            #root = tk.Toplevel(parent)
            #root.overrideredirect(True)
    
            super().__init__()
    
            self.box_state = state
            self.box_message = message
            self.box_title = title
    
            W = 0
            H = 1
    
            self.dlg_size = [400,200]
    
            self.title_bar_width = self.dlg_size[W]
            self.title_bar_height = 40
    
            self.btn_bar_height = 42
    
            self.btn_32x32_size = 42
    
            self.row_height = 28
            self.btn_row_height = 32
    
            self.frm_space = 10
    
            self.parent = parent
            self.CreateDialog(root)
    
            root.wait_window(root)
    
            #root.mainloop()
    
        def CreateDialog(self,root):
    
            W = 0
            H = 1
    
            if self.parent != None:
                self.parent.update_idletasks()
                ww=self.parent.winfo_screenwidth()
                wh=self.parent.winfo_screenheight()
                x=self.parent.winfo_rootx()
                y=self.parent.winfo_rooty()
    
                parent_w = self.parent.winfo_width()
                parent_h = self.parent.winfo_height()
                parent_x = self.parent.winfo_x()
                parent_y = self.parent.winfo_y()
            else:
                root.update_idletasks()
                ww=root.winfo_screenwidth()
                wh=root.winfo_screenheight()
                x=root.winfo_rootx()
                y=root.winfo_rooty()
    
                parent_w = root.winfo_width()
                parent_h = root.winfo_height()
                parent_x = root.winfo_x()
                parent_y = root.winfo_y()
    
    
            self.dev_dialog = root
            dialog = self.dev_dialog
            dialog.overrideredirect(True)
    
            dlg_x = int((parent_x+parent_w) - (self.dlg_size[W]/2))
            dlg_y = int((parent_y+parent_h) - (self.dlg_size[H]/2))
    
            if dlg_x < 0 : dlg_x = 0 
            if dlg_y < 0 : dlg_y = 0 
    
            dialog.geometry('{}x{}+{}+{}'.format(self.dlg_size[W],self.dlg_size[H],dlg_x,dlg_y))
    
    
            self.Title_Bar = tk.Frame(
                dialog,            
                relief='flat',
                bg = self.title_bar_color ,
                )
            self.Title_Label = tk.Label(
                self.Title_Bar,
                bg = self.title_bar_color ,
                text = self.box_title,
            )
    
            dialog.bind('<Button-1>', self.dialog_left_click)
            dialog.bind('<B1-Motion>', self.dialog_mouse_move_on)
            dialog.bind('<ButtonRelease-1>',self.dialog_mouse_release)
    
            self.MsgArea_frame = tk.Frame(
                dialog,            
                relief='flat',
                bg = self.select_bar_color,
                )
            self.message_frame = tk.Frame(
                self.MsgArea_frame,
                relief='flat',
                bg = self.item_ground_color ,
                )
            self.label_message = tk.Label(
                self.message_frame,
                bg = self.item_ground_color ,
                text = self.box_message,
            )
    
            self.BtnArea_frame = tk.Frame(
                dialog,            
                relief='flat',
                bg = self.item_ground_color,
                )
    
            self.btn_ok = tk.Button(
                self.BtnArea_frame,            
                bg = self.item_ground_color,
                text = 'OK',
                command = lambda:self.btn_msgbox_clicked(1),
                )
    
            self.btn_yes = tk.Button(
                self.BtnArea_frame,            
                bg = self.item_ground_color,
                text = 'YES',
                command = lambda:self.btn_msgbox_clicked(1),
                )
    
            self.btn_no = tk.Button(
                self.BtnArea_frame,            
                bg = self.item_ground_color,
                text = 'NO',
                command = lambda:self.btn_msgbox_clicked(2),
                )
    
            self.btn_cancel = tk.Button(
                self.BtnArea_frame,            
                bg = self.item_ground_color,
                text = 'CANCEL',
                command = lambda:self.btn_msgbox_clicked(3),
                )
    
            frm_space = self.frm_space
            msg_frm_w = 4
            btn_fram_h = 36
    
            message_area_h = self.dlg_size[H] - self.title_bar_height - frm_space *2 - btn_fram_h
    
            # Frame
            self.Title_Bar.place(
                x = 0, y = 0, 
                width = self.title_bar_width, height = self.title_bar_height
                )
            self.MsgArea_frame.place(
                x = frm_space, y = self.title_bar_height + frm_space, 
                width = self.title_bar_width - frm_space*2, height = message_area_h
                )
            self.BtnArea_frame.place(
                x = 0, y = self.title_bar_height + frm_space + message_area_h, 
                width = self.title_bar_width, height = btn_fram_h
                )
    
            self.Title_Label.grid(row = 0, column = 1,sticky = tk.W+tk.N+tk.S)
            self.Title_Bar.columnconfigure(0,minsize = self.frm_space)
            self.Title_Bar.rowconfigure(0,minsize = self.title_bar_height)
    
            self.MsgArea_frame.columnconfigure(0,minsize = self.frm_space)
            self.MsgArea_frame.rowconfigure(0,minsize = message_area_h)
    
            self.BtnArea_frame.rowconfigure(0,minsize = btn_fram_h)
    
            self.message_frame.place(
                x = msg_frm_w, y = msg_frm_w,
                width = self.title_bar_width - frm_space*2 - msg_frm_w*2, height = message_area_h - msg_frm_w*2,
                )
    
            # self.message_frame
            self.label_message.grid(row = 0, column = 1,sticky = tk.W+tk.N+tk.S)
    
            if self.box_state == 1:
                self.btn_ok.place(
                    x = (self.title_bar_width/2) - 80/2 , y = btn_fram_h/2 - 24/2,
                    )            
            if self.box_state == 2:
                self.btn_yes.place(
                    x = (self.title_bar_width/2) - (80 + frm_space) , y = btn_fram_h/2 - 24/2,
                    )            
                self.btn_no.place(
                    x = (self.title_bar_width/2) + frm_space , y = btn_fram_h/2 - 24/2,
                    )            
            if self.box_state == 3:
                self.btn_yes.place(
                    x = (self.title_bar_width/2) - (80*1.5 + frm_space*2) , y = btn_fram_h/2 - 24/2,
                    )            
                self.btn_no.place(
                    x = (self.title_bar_width/2) - 80/2 , y = btn_fram_h/2 - 24/2,
                    )            
                self.btn_cancel.place(
                    x = (self.title_bar_width/2) + 80/2 + frm_space*2 , y = btn_fram_h/2 - 24/2,
                    )            
    
            #dialog.grab_set()
            dialog.grab_set_global()
    
        def btn_msgbox_clicked(self,state):
            self.return_state = state
            self.isDestroy = True
    
        def get_return_state(self):
            return self.return_state
    
        def dialog_mouse_release(self,event):
            if self.isDrag_DlgMotion:
                self.isDrag_DlgMotion = False
    
            if self.isDestroy:
                self._quit()
            return
    
        def _quit(self):
            self.dev_dialog.grab_release()
            self.dev_dialog.destroy()
    
    
    class CreateScreen(object):
        def __init__(self):
            self.cnt = 0
            W = 0
            H = 1
            self.dlg_size = [400,200]
    
            geo_string = '{}x{}'.format(self.dlg_size[W],self.dlg_size[H])
    
            self.MainWindow_obj = ttk.tkinter.Tk()
            self.MainWindow_obj.geometry(geo_string) 
    
            self.CntSting = tk.StringVar()
            self.CntSting.set(str(self.cnt))
    
            Label_Conter_text = tk.Label(
                self.MainWindow_obj,
                textvariable = self.CntSting,
            )
    
            self.MsgSting = tk.StringVar()
            self.MsgSting.set('...')
    
            Label_Message_text = tk.Label(
                self.MainWindow_obj,
                textvariable = self.MsgSting,
            )
    
            Btn_Messagebox = tk.Button(
                self.MainWindow_obj,
                text = 'Push',
                command = self.Btn_Messagebox_clicked
            )
            Label_Conter_text.pack()
            Label_Message_text.pack()
            Btn_Messagebox.pack()
    
            self.MainWindow_obj.after(1000,self.loop_msg)
    
            self.MainWindow_obj.mainloop()
    
        def Btn_Messagebox_clicked(self):
            self.dlg = CommonMessageBoxDialog(title='Test',message='Do you remember ?',state=3,parent =self.MainWindow_obj)        
            ret = self.dlg.get_return_state()
    
            if ret == 1:
                self.MsgSting.set('Yes')
            if ret == 2:
                self.MsgSting.set('No')
            if ret == 3:
                self.MsgSting.set('Cancel')
    
            return
    
        def loop_msg(self):
            self.cnt += 1
            self.CntSting.set(str(self.cnt))
    
            self.MainWindow_obj.after(1000,self.loop_msg)
    
    if __name__ == '__main__':
        screen_obj = CreateScreen()