Python Tk:如何创建自定义消息框
请给我一些建议 自定义消息框要求包括:Python Tk:如何创建自定义消息框,python,tkinter,messagebox,Python,Tkinter,Messagebox,请给我一些建议 自定义消息框要求包括: 是模态的(实现的) 当显示消息框时,消息框位于前面,无法操作其他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()