Open youstanzr opened 2 years ago
@Is there any way to center the message box, can't get the real size of message box. error like
_tkinter.TclError: bad window path name ".!mesaagebox"@israel-dryer
@funchan24, @youstanzr, if you want to show the popup over a particular widget or parent window, make sure you give the dialog a parent (see example below). If you do this, it will display on top of the window or widget you are initiating the dialog for.
I'll consider adding some kind of positioning in the future to the constructor. One reason I do not automatically center the windows is because tkinter does not handle multiple screens well, and it was putting it in between two screens.
import ttkbootstrap as ttk
from ttkbootstrap.dialogs import Messagebox
window = ttk.Window()
btn = ttk.Button(window, text='Show message')
btn.configure(command=lambda: Messagebox.show_info(parent=btn, message="Hello"))
btn.pack(padx=20, pady=20)
window.mainloop()
@israel-dryer I really want to know if I can get the size of the MessageDialog so that I can center it by myself. I have only one screen. I got a error _tkinter.TclError: bad window path name ".!messagedialog" with below code.
from ttkbootstrap import *
from ttkbootstrap.dialogs import MessageDialog
root = Window()
m = MessageDialog('test', parent=root)
width, height = m.winfo_width(), m.winfo_height()
m.show()
root.mainloop()
@israel-dryer I really want to know if I can get the size of the MessageDialog so that I can center it by myself. I have only one screen. I got a error _tkinter.TclError: bad window path name ".!messagedialog" with below code.
from ttkbootstrap import * from ttkbootstrap.dialogs import MessageDialog root = Window() m = MessageDialog('test', parent=root) width, height = m.winfo_width(), m.winfo_height() m.show() root.mainloop()
@youstanzr, Hmm... apparently I did add a position
parameter to the show
method. I had forgotten that I did that... so you could technically pass an (x, y) coordinate to anchor the messagebox.
@funchan24, you can't get the position of the messagebox as it is now because it is not actually created until you call the show
method. This allows you to keep calling it as needed without it having to exist in the background when not used. However, you could override the show method and access the ._toplevel
property to use the position methods you are using now by inserting the following into your show method:
root.update_idletasks()
width = self._toplevel.winfo_width()
height = self._toplevel.winfo_height()
Notice that you need to call update_idletasks
if you try to get the width and height before actually showing the widget because it hasn't actually been drawn yet.
I was having trouble getting a solution for this to work w/ the combo of update_idletasks() and self._toplevel.winfo_width / height, so I ended up going a different route. This override of MessageDialog / Dialog._locate() worked really well though, and instead uses values derived from self._toplevel.winfo_reqwidth / reqheight. P.S. A big 'thank you' to israel-dryer for making the awesome GUI-enhancement module of ttkbootstrap.
# DEFINE METHOD THAT DETERMINES WHERE ON SCREEN
# TO PLACE MessageDialog INSTANCE (by default), IF NO EXPLICIT
# VALUES ARE PASSED FOR 'POSITION' COORDINATES.
#
# MessageDialog is a child class of the Dialog class,
# both of which are defined in the ttkbootstrap module.
# The method below is an override of the Dialog._locate()
# method (which is inherited by the MessageDialog class).
#
# By default, the original version of this method would place
# the Dialog instance in the upper-left corner of the parent
# widget. This override sets the default Dialog instance placement
# in the center of the widget instead.
def _locate(self):
# IF PARENT OBJECT WAS PASSED...
if self._parent != None:
# Define values for parent widget width & height.
parent_width = self._parent.winfo_width()
parent_height = self._parent.winfo_height()
# Define values for center x & y coordinates of
# parent widget.
parent_center_x = math.trunc(self._parent.winfo_x() + (parent_width / 2))
parent_center_y = math.trunc(self._parent.winfo_y() + (parent_height / 2))
# Define values for MessageDialog instance width & height
# based on its _toplevel instance.
widget_width = self._toplevel.winfo_reqwidth()
widget_height = self._toplevel.winfo_reqheight()
# Calculate the center_x & center_y coordinates where
# the MessageDialog will need to be situated in order
# to be placed at the center of its parent widget.
center_x = math.trunc(parent_center_x - (widget_width / 2))
center_y = math.trunc(parent_center_y - (widget_height / 2))
# Then, set the x & y coordinates used
# by the geometry() method below to use
# center_x & center_y instead.
x = center_x
y = center_y
#
# ELSE NO PARENT OBJECT WAS PASSED...
else:
# Define values as in original method,
# using top-left x & y coordinates of
# root Tk instance.
x = self._toplevel.master.winfo_rootx()
y = self._toplevel.master.winfo_rooty()
# SET X & Y COORDINATES FOR MessageDialog INSTANCE
# PLACEMENT.
self._toplevel.geometry(f"+{x}+{y}")
Is your feature request related to a problem? Please describe.
It seemed to me a little bit confusing when you're dealing with large app screen and the app suddenly stops cause some entry got wrong error for example and you did not notice the Messagebox showing up at the top left corner of your app.
Describe the solution you'd like
I did a wrapper around Messagebox to show it in the center of the screen and thought it might be useful to have this in ttkbootstrap.dialogs directly as a boolean parameter passed to the show message static method like below
Describe alternatives you've considered
Here is the wrapper that I created:
Additional context
No response