0

I want to create a search box in Python 3. I am aware of entry widget and buttons, but I just want something more elegant like this. Is it even possible to create something closer to the one in the image? If yes, kindly throw some light on this topic. TIA

Dee
  • 51
  • 1
  • 2
  • 12
  • I believe the following would come somewhat close: a Frame with border (blue if allowed, not sure. Inside a dropdown list, entry box, button, button, all with no borders or padding. The buttons get image labels rather than text. – Terry Jan Reedy Oct 10 '15 at 05:43

1 Answers1

1

You can do this using ttk if you create a new element using an image for the search icon you could embed it into a text widget using the following code. In this case we add a theme provided 'pin' icon but this element could be easily replaced. The demo looks like this with the original entry on top and the new style below:

example image

The vsapi element engine is only available on Windows but by using the image element engine to define your custom element this would work on all Tk platforms.

import tkinter as tk
import tkinter.ttk as ttk

class SearchEntry(ttk.Widget):
    """
    Customized version of a ttk Entry widget with an element included in the
    text field. Custom elements can be created using either the vsapi engine
    to obtain system theme provided elements (like the pin used here) or by using
    the "image" element engine to create an element using Tk images.

    Note: this class needs to be registered with the Tk interpreter before it gets
    used by calling the "register" static method.
    """
    def __init__(self, master, **kw):
        kw["style"] = "Search.Entry"
        ttk.Widget.__init__(self, master, 'ttk::entry', kw)
    def get(self):
        return self.tk.call(self._w, 'get')
    def set(self, value):
        self.tk.call(self._w, 'set', value)
    @staticmethod
    def register(root):
        style = ttk.Style()
        # There seems to be some argument parsing bug in tkinter.ttk so cheat and eval
        # the raw Tcl code to add the vsapi element for a pin.
        root.eval('''ttk::style element create pin vsapi EXPLORERBAR 3 {
            {pressed !selected} 3
            {active !selected} 2
            {pressed selected} 6
            {active selected} 5
            {selected} 4
            {} 1
        }''')
        #style.element_create("pin", "vsapi", "EXPLORERBAR", "3", [(["selected"], 4),([], 1)])
        style.layout("Search.Entry", [
            ("Search.Entry.field", {'sticky': 'nswe', 'children': [
                ("Search.Entry.background", {'sticky':'nswe', 'children': [
                    ("Search.Entry.padding", {'sticky':'nswe', 'children': [
                        ("Search.Entry.textarea", {'sticky':'nswe'})
                    ]})
                ]}),
                ("Search.Entry.pin", {'sticky': 'e'})
            ]})
        ])
        style.configure("Search.Entry", padding=(1, 1, 14, 1))
        style.map("Search.Entry", **style.map("TEntry"))

if __name__ == '__main__':
    root = tk.Tk()
    text = tk.StringVar()
    SearchEntry.register(root)
    frame = ttk.Frame(root)
    text.set("some example text ...")
    e1 = ttk.Entry(frame, textvariable=text)
    e2 = SearchEntry(frame, textvariable=text)
    e1.grid(sticky="news", padx=2, pady=2)
    e2.grid(sticky="news", padx=2, pady=2)
    frame.grid(sticky = "news", padx=2, pady=2)
    root.grid_columnconfigure(0, weight = "1")
    root.grid_rowconfigure(0, weight = "1")
    root.mainloop()
patthoyts
  • 32,320
  • 3
  • 62
  • 93