Python Forum
[Tkinter] Open tkinter colorchooser at toplevel (so I can select/focus on either window)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Open tkinter colorchooser at toplevel (so I can select/focus on either window)
#5
It is unusual for a dialog to stay open, and generally considered bad user interface design. If you have something that should be always available it should be part of the main interface, not a popup.

If you want to make a color picker with sliders, here's a starting point.
import tkinter as tk
from tkinter import ttk
import random

class Slider(ttk.Frame):
    def __init__(self, parent, text, max=100, min=0, command=None):
        super().__init__(parent)
        top = ttk.Frame(self)
        bottom = ttk.Frame(self)
        self.label = ttk.Label(top, text=text, justify=tk.LEFT)
        self.display_value = tk.StringVar(self, "0")
        self.display_value.trace("w", lambda a, b, c: self.display_changed(self.display_value.get()))
        self.display = ttk.Entry(top, width=10, textvariable=self.display_value)
        self.scale_value = tk.DoubleVar(self, 0.0)
        self.scale = ttk.Scale(bottom, from_=min, to=max, variable=self.scale_value, command=self.scale_changed)
        self.min = min
        self.max = max
        self.command = command

        self.label.pack(side=tk.LEFT)
        self.display.pack(side=tk.RIGHT)
        self.scale.pack(expand=True, fill=tk.BOTH)
        top.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
        bottom.pack(side=tk.TOP, expand=True, fill=tk.BOTH)

    def scale_changed(self, value):
        self.display_value.set(int(round(float(value))))

    def display_changed(self, value):
        try:
            value = int(value)
        except ValueError:
            pass
        else:
            value = max(self.min, min(self.max, value))
            self.display_value.set(value)
            self.scale_value.set(value)
            if self.command is not None:
                self.command(value)

    @property
    def value(self):
        return int(self.scale_value.get())

    @value.setter
    def value(self, new_value):
        self.display_changed(new_value)

class ColorChooser(tk.Toplevel):
    def __init__(self, command=None):
        super().__init__()
        self.title("Colors")
        self.red = Slider(self, text="Red", max=255, command=self.color_changed)
        self.green = Slider(self, text="Green", max=255, command=self.color_changed)
        self.blue = Slider(self, text="Blue", max=255, command=self.color_changed)
        self._color = "#000000"
        self.apply = tk.Button(self, text="Apply", fg="white", bg=self._color, command=self.apply_pressed)
        self.red.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)
        self.green.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)
        self.blue.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)
        self.apply.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)
        self.command = command

    def color_changed(self, _):
        r = self.red.value
        g = self.green.value
        b = self.blue.value
        self._color = f"#{r:02x}{g:02x}{b:02x}"
        fg = "white" if r + g + b < 300 else "black"
        self.apply.config(fg=fg, bg=self.color)

    def apply_pressed(self):
        if self.command is not None:
            self.command(self.color)

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, new_value):
        try:
            r = int(new_value[1:3], base=16)
            g = int(new_value[3:5], base=16)
            b = int(new_value[5:7], base=16)
            print(r, g, b)
        except (ValueError, IndexError) as msg:
            print(msg)
        else:
            self.red.value = r
            self.green.value = g
            self.blue.value = b

class MainPanel(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Main Panel")
        self.style = ttk.Style()
        themes = self.style.theme_names()
        self.theme = tk.StringVar(self, themes[0])
        self.theme.trace("w", lambda a, b, c: self.style.theme_use(self.theme.get()))
        theme_slector = ttk.Combobox(self, values=themes, textvariable=self.theme)
        theme_slector.pack(padx=40, pady=20)

        chooser = ColorChooser(command=print)
        chooser.color = "#a0b0c0"

MainPanel().mainloop()
Reply


Messages In This Thread
RE: Open tkinter colorchooser at toplevel (so I can select/focus on either window) - by deanhystad - Jul-06-2022, 01:03 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Tkinter multiple windows in the same window hosierycouch 1 1,220 May-30-2024, 04:28 AM
Last Post: deanhystad
  Interaction between Matplotlib window, Python prompt and TKinter window NorbertMoussy 3 2,513 Mar-17-2024, 09:37 AM
Last Post: deanhystad
  Tkinter multiple windows in the same window tomro91 1 2,157 Oct-30-2023, 02:59 PM
Last Post: Larz60+
  pass a variable between tkinter and toplevel windows janeik 9 6,144 Oct-05-2023, 04:22 AM
Last Post: janeik
  Centering and adding a push button to a grid window, TKinter Edward_ 15 14,198 May-25-2023, 07:37 PM
Last Post: deanhystad
  Now if window is open or not delcencen 5 4,103 Mar-25-2023, 07:26 PM
Last Post: deanhystad
  [PyQt] Hover over highlighted text and open popup window DrakeSoft 2 2,919 Oct-29-2022, 04:30 PM
Last Post: DrakeSoft
  RGB() <> colorchooser.askcolor KennethHobson 9 4,044 Aug-24-2022, 06:43 PM
Last Post: woooee
  [Tkinter] Toplevel window menator01 5 5,567 Apr-18-2022, 06:01 PM
Last Post: menator01
  [Tkinter] Background inactivity timer when tkinter window is not active DBox 4 4,937 Apr-16-2022, 04:04 PM
Last Post: DBox

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020