Jane Griscti | 24 Jul 2012 20:50
Picon

Fwd: Toggle buttons



---------- Forwarded message ----------
From: Jane Griscti <jgriscti <at> gmail.com>
Date: Tue, Jul 24, 2012 at 1:37 PM
Subject: Re: [Tkinter-discuss] Toggle buttons
To: Mark Summerfield <list <at> qtrac.plus.com>



On Tue, Jul 24, 2012 at 11:05 AM, Mark Summerfield <list <at> qtrac.plus.com> wrote:
Hi Jane,

On Tue, 24 Jul 2012 13:45:38 +0000 (UTC)
Jane <jgriscti <at> gmail.com> wrote:
> Mark Summerfield <list <at> qtrac.plus.com> writes:
>
> >
> > Hi,
> >
> > I want to create a toggle button, i.e., a button that when clicked goes
> > down (if it is up) and goes up (if it is down).
> >
> > One easy way to achieve this is to set the button's style to
> > "Toolbutton" (see self.toggle2). But unfortunately, that gets rid of
> > the button's relief so it looks out of place amongst other non-toggling
> > buttons.
> >
> > I solved if for Linux using a custom style (see self.toggle3). But this
> > doesn't work on Windows and I can't figure out how to solve it.
> >
> > Can anyone suggest a solution?
[snip]

> Hi ...
>
> Found that setting the ttk.Checkbutton style to 'TButton' forces it to
> appear as themed button; then, on selection, changing it to 'Toolbutton'
> gives it a 'sunken' appearance. Works ok under Windows 7.
>
>     cb1 = ttk.Checkbutton(f, style='Demo.TButton',
>                              image=(self.noletters, 'selected',
> self.letters), command=lambda: self._cb_value_changed(cb1))
>
>     def _cb_value_changed(self, cb):
>         # if a checkbutton is selected, use the 'Toolbutton'
>         # style to make it appear 'sunken'
>         if 'selected' in cb.state():
>             cb['style'] = 'Demo.Toolbutton'
>         else:
>             cb['style'] = 'Demo.TButton'

I tried your idea on Windows 7 & Linux (& a slightly simplified version
which did the same). Yes, it correctly changes the appearance between
raised and sunken: but in the sunken state the width of the button
shrinks to fit the text -- and there's no width property for styled
buttons:-(

Here's the code:

############################################################
import tkinter.ttk

class Window(tkinter.ttk.Frame):

    def __init__(self, master=None):
        super().__init__(master)
        self.toggle1 = tkinter.ttk.Button(self, text="Off (1)",
                command=lambda *args: self.toggle(self.toggle1, 1))
        self.toggle1.pack(padx=5, pady=5)
        self.toggle2 = tkinter.ttk.Button(self, text="Off (2)",
                style="Toolbutton",
                command=lambda *args: self.toggle(self.toggle2, 2))
        self.toggle2.pack(padx=5, pady=5)
        self.toggle3 = tkinter.ttk.Button(self, text="Off (3)",
                command=lambda *args: self.toggle(self.toggle3, 3))
        self.toggle3.pack(padx=5, pady=5)
        style = tkinter.ttk.Style()
        style.configure("Toggle.TButton")
        style.map("Toggle.TButton", relief=[("pressed", "sunken"),
            ("selected", "sunken"), ("!selected", "raised")])
        self.toggle3.config(style="Toggle.TButton")
        self.toggle4 = tkinter.ttk.Checkbutton(self,
                style="Toggle.TButton", text="Off (4)",
                command=lambda *args: self.toggle_style(self.toggle4, 4))
        self.toggle4.pack(padx=5, pady=5)
        tkinter.ttk.Button(self, text="Quit",
                command=self.master.destroy).pack(padx=5, pady=5)
        self.pack()

    def toggle_style(self, button, number):
        if button.instate(("selected",)):
            button.config(text="Off ({})".format(number))
            button.config(style="Toolbutton")
        else:
            button.config(text="On ({})".format(number))
            button.config(style="Toggle.TButton")

    def toggle(self, button, number):
        if button.instate(("!selected",)):
            button.state(("selected",))
            button.config(text="On ({})".format(number))
        else:
            button.state(("!selected",))
            button.config(text="Off ({})".format(number))

window = Window()
window.master.title("Toggle")
window.master.mainloop()
############################################################


--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "Programming in Go" - ISBN 0321774639
            http://www.qtrac.eu/gobook.html

Hi Mark ... there is a width value for ttk.Checkbutton.

I was able to get it work with the code below.  I just forced a width of 11 pixels (tried to use the winfo_reqwidth() of another button to get the right size but it returns 76 for some reason ... there must be a way to get a decent size??)


        tkinter.ttk.Style().configure('Toggle.Toolbutton', anchor='center')
        self.toggle4 = tkinter.ttk.Checkbutton(self,
                style='Toggle.TButton', text="Off (4)", width=-11,
                command=lambda *args: self.toggle_style(self.toggle4, 4))
        self.toggle4.pack(padx=5, pady=5)

    def toggle_style(self, button, number):
        if button.instate(("selected",)):
            button.config(text="Off ({})".format(number))
            button.config(style="Toggle.Toolbutton")
        else:
            button.config(text="On ({})".format(number))
            button.config(style="Toggle.TButton")

Jane

PS Apologies, thought I had sent this to the list
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Michael Lange | 24 Jul 2012 21:17
Picon

Re: Fwd: Toggle buttons

Hi,

Thus spoketh Jane Griscti <jgriscti <at> gmail.com> 
unto us on Tue, 24 Jul 2012 14:50:36 -0400:

> I was able to get it work with the code below.  I just forced a width
> of 11 pixels (tried to use the winfo_reqwidth() of another button to
> get the right size but it returns 76 for some reason ... there must be
> a way to get a decent size??)

Sounds like a tiny checkbutton ;)
I suspect that the "11" refers to character units rather than pixels and
the "76" looks like a reasonable pixel size for a button.

Regards

Michael

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

The sooner our happiness together begins, the longer it will last.
		-- Miramanee, "The Paradise Syndrome", stardate 4842.6
Mark Summerfield | 25 Jul 2012 09:03

Re: Fwd: Toggle buttons

Hi Jane,

On Tue, 24 Jul 2012 14:50:36 -0400
Jane Griscti <jgriscti <at> gmail.com> wrote:
[snip]
> Hi Mark ... there is a width value for ttk.Checkbutton.
> 
> I was able to get it work with the code below.  I just forced a width of
> 11 pixels (tried to use the winfo_reqwidth() of another button to get the
> right size but it returns 76 for some reason ... there must be a way to
> get a decent size??)
> 
> 
>         tkinter.ttk.Style().configure('Toggle.Toolbutton',
> anchor='center') self.toggle4 = tkinter.ttk.Checkbutton(self,
>                 style='Toggle.TButton', text="Off (4)", width=-11,
>                 command=lambda *args: self.toggle_style(self.toggle4, 4))
>         self.toggle4.pack(padx=5, pady=5)
> 
>     def toggle_style(self, button, number):
>         if button.instate(("selected",)):
>             button.config(text="Off ({})".format(number))
>             button.config(style="Toggle.Toolbutton")
>         else:
>             button.config(text="On ({})".format(number))
>             button.config(style="Toggle.TButton")
> 
> Jane

You're right about the width option (I was thinking of ttk.Button).

However, I've found two problems with this approach:
(1) button widths differ per platform (so on Windows 7 I need -11 and on
    Linux -9; and this may vary with DPI or other factors, so setting
    width may not be a good idea)
(2) the text is centered (like the other buttons) when in TButton style;
    but is left aligned in Toolbutton style. And there doesn't seem to
    be a justify option for ttk.Checkbuttons.

So, for now, I'm using the style approach for Linux since it works
perfectly there, and for Windows and Mac OS X I'm adding an image to the
button with one image for selected and one for deselected.

Thanks!

--

-- 
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "Programming in Go" - ISBN 0321774639
            http://www.qtrac.eu/gobook.html

Gmane