DwightFromTheOffice
DwightFromTheOffice

Reputation: 520

Formatting text in a tkinter messagebox in two columns

Normally I format text in a console with fixed-length characters. Now I want to do something similar in a tkinter messagebox, but this messes up the indentation. For example this

from tkinter import messagebox

    info = {'Everything': 'first one', 'should be': 'second one', 'evenly outlined': 'another one', 'ms are really long':'previous to the last', 'mmmmmmmmmmmmmmm': "you see?"}
    infostring = (f"{k: <20}:{v}" for k, v in info.items())
    messagebox.askokcancel(
        title="outlining",
        icon=messagebox.QUESTION,
        message=("Is this your outlined well?\n\n" + "\n".join(infostring)),
    )

results in

enter image description here

whereas in a console it would be:

Everything          :first one
should be           :second one
evenly outlined     :another one
ms are really long  :previous to the last
mmmmmmmmmmmmmmm     :you see?

And this is how I want it in the messagebox.

Upvotes: 3

Views: 1811

Answers (2)

astqx
astqx

Reputation: 2096

You could use the simpledialog module and build one yourself.

from tkinter import *
from tkinter import simpledialog

class Dialog(simpledialog.Dialog):
    def __init__(self,master,title=None):
        root.bell()
        simpledialog.Dialog.__init__(self,master,title)

    def body(self,frame):
        icon_label=Label(frame,image='::tk::icons::question')
        icon_label.pack(side='left',anchor='n',padx=(0,10))
        label=Label(frame,text="Is this your outlined well?\n\n" + "\n".join(infostring),
            justify='left',font='Consolas 11')
        label.pack(side='right')
        return label

def dialog():
    Dialog(root,title='outlining')

root=Tk()

info = {'Everything': 'first one', 'should be': 'second one', 'evenly outlined': 'another one',
    'ms are really long':'previous to the last', 'mmmmmmmmmmmmmmm': "you see?"}
infostring = (f"{k: <20}:{v}" for k, v in info.items())

button=Button(root,text='Dialog',command=dialog)
button.pack(padx=100,pady=100)

root.mainloop()

You can also make the following changes to the Dialog class to make it look closer to the native.

def body(self,frame):
    frame.config(bg='white')
    frame.master.config(bg=frame['bg'])
    icon_label=Label(frame,image='::tk::icons::question',bg=frame['bg'])
    icon_label.pack(side='left',anchor='n',padx=(0,10))
    label=Label(frame,text="Is this your outlined well?\n\n" + "\n".join(infostring),
        justify='left',font='Consolas 11',bg=frame['bg'])
    label.pack(side='right')
    return label

def buttonbox(self):

    box = Frame(self)

    w = ttk.Button(box, text="Cancel", width=10, command=self.cancel)
    w.pack(side=RIGHT, padx=5, pady=5)
    w = ttk.Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
    w.pack(side=RIGHT, padx=5, pady=5)

    self.bind("<Return>", self.ok)
    self.bind("<Escape>", self.cancel)

    box.pack(fill='x')

Upvotes: 0

0rdinal
0rdinal

Reputation: 661

I don't think this is possible using the normal MessageBox as a result of OS level restrictions. However, you can do it in a label by setting justify to tkinter.LEFT.

Here's some example code:

import tkinter
msg = """Everything          :first one
should be           :second one
evenly outlined     :another one
ms are really long  :previous to the last
mmmmmmmmmmmmmmm     :you see?"""
r = tkinter.Tk()

label1 = tkinter.Label(r, text=msg, font=("Consolas", 12), justify=tkinter.LEFT)
label1.place(x=0,y=0)
r.mainloop()

Which outputs this:

Message Box

I apreciate this isn't an exact answer, and I'm not super well versed with Tkinter, but hopefully this will provide some help. Good Luck!

Edit:

I also used a monospace font, which will most likely be required to ensure the text is always a consistent width.

Upvotes: 1

Related Questions