Welcome, guest | Sign In | My Account | Store | Cart
# encoding: utf-8
# Author: Miguel Martínez López

try:
    from Tkinter import Tk, Label
    from ttk import Frame
    from Tkconstants import *
except ImportError:
    from tkinter import Tk, Label
    from tkinter.ttk import Frame
    from tkinter.constants import *

class PageLabel(Label):
    def __init__(self, master, is_selected, is_active, **kwargs):
        Label.__init__(self, master, **kwargs)
        self.is_selected = is_selected
        self.is_active = is_active


class Pagination(Frame):

    def __init__(self, master, first_page, last_page, padding=3, command =None):
        if not hasattr(self, "pagination_style"):
            raise Exception("No pagination style defined")
        
        Frame.__init__(self, master)

        self._command = command

        self._list_of_buttons = []

        button = self._build_page_label(first_page)
        button.pack(side=LEFT)

        for page_number in range(first_page+1, last_page+1):
            button = self._build_page_label(page_number)
            button.pack(side=LEFT, padx=(padding, 0))
        
        self._selected_label = None

    def _build_page_label(self, page_number):
        label = PageLabel(self, text=page_number, is_selected=False, is_active=False, width=0)
        
        self._config_style(label)
        label.bind("<1>", lambda event, label=label: self._on_button_selected(label))
        
        label.bind("<Enter>", lambda event, label=label: self._on_focus_in(label))
        label.bind("<Leave>", lambda event, label=label: self._on_focus_out(label))
        
        self._list_of_buttons.append(label)

        return label

    def _on_focus_in(self, label):
        label.is_active = True
        self._config_style(label)

    def _on_focus_out(self, label):
        label.is_active = False
        self._config_style(label)

    def _config_style(self, label):
        
        font = self.pagination_style.get("font")
        padx = self.pagination_style.get("padx")
        pady = self.pagination_style.get("pady")

        if label.is_selected:
            style_config = self.pagination_style["selected_button"]
        else:
            style_config = self.pagination_style["normal_button"]
            
        config = {}
        
        if label.is_active:
            if "activebackground" in style_config:
                config["background"] = style_config["activebackground"]
            if "activeforeground" in style_config:
                config["foreground"] = style_config["activeforeground"]
        else:
            if "background" in style_config:
                config["background"] = style_config["background"]
            if "foreground" in style_config:
                config["foreground"] = style_config["foreground"]

        if "padx" in style_config:
            config["padx"] = style_config["padx"]
        else:
            if padx is not None:
                config["padx"] = padx

        if "pady" in style_config:
            config["pady"] = style_config["pady"]
        else:
            if pady is not None:
                config["pady"] = pady 
        
        if "font" in style_config:
            config["font"] = style_config["font"]
        else:
            if padx is not None:
                config["font"] = padx
        

        label.configure(**config)

    def _on_button_selected(self, label):

        if self._selected_label is not None:
            self._selected_label.is_selected = False
            self._config_style(self._selected_label)

        label.is_selected = True
        self._selected_label = label

        self._config_style(self._selected_label)

        if self._command is not None:
            self._command(self.selected_page)

    def select_page(self, page_number):
        page_number = int(page_number)
        for label in self._list_of_buttons:
            if int(label["text"]) == page_number:
                self._selected_label = label
                return

    @property
    def selected_page(self):
        return int(self._selected_label["text"])

    page = selected_page


if __name__ == "__main__":
    class My_Pagination1(Pagination):
        pagination_style = {
            "padx":12,
            "pady": 6,
            "normal_button": {
                "font": ("Verdana", 12),
                "foreground": "#337ab7", 
                "activeforeground":"#23527c",
                "background": "white", 
                "activebackground": "#eee"
            }, 
            "selected_button": {
                "font":("Verdana", 12, "bold"),
                "foreground":"#fff",
                "activeforeground":"#fff", 
                "background":"#337ab7", 
                "activebackground":"#337ab7"
            }
        }

    class My_Pagination2(Pagination):
        pagination_style = {
            "padx":12,
            "pady":6,
            "normal_button": {
                "font": ("Verdana", 12),
                "foreground": "black", 
                "activeforeground":"black",
                "background": "white", 
                "activebackground": "#ccc"
            }, 
            "selected_button": {
                "font":("Verdana", 12, "bold"),
                "foreground":"white",
                "activeforeground":"#fff", 
                "background":"#f44336", 
                "activebackground":"#f44336"
            }
        }

    class My_Pagination3(Pagination):
        pagination_style = {
            "padx":12,
            "pady":6,
            "normal_button": {
                "font": ("Verdana", 12),
                "foreground": "#717171", 
                "activeforeground":"#717171",
                "background": "#e9e9e9", 
                "activebackground": "#fefefe"
            }, 
            "selected_button": {
                "font":("Verdana", 12, "bold"),
                "foreground":"#f0f0f0",
                "activeforeground":"#f0f0f0", 
                "background":"#616161", 
                "activebackground":"#616161"
            }
        }
        
    class My_Pagination4(Pagination):
        pagination_style = {
            "padx":12,
            "pady":6,
            "normal_button": {
                "font": ("Verdana", 12),
                "foreground": "#feffff", 
                "activeforeground":"#feffff",
                "background": "#3e4347", 
                "activebackground": "#3d4f5d"
            }, 
            "selected_button": {
                "font":("Verdana", 12, "bold"),
                "foreground":"#feffff",
                "activeforeground":"#feffff", 
                "background":"#2f3237", 
                "activebackground":"#2f3237"
            }
        }

    class My_Pagination5(Pagination):
        pagination_style = {
            "padx":12,
            "pady":6,
            "normal_button": {
                "font": ("Verdana", 12),
                "foreground": "#2E4057", 
                "activeforeground":"#2E4057",
                "background": "white", 
                "activebackground": "white"
            }, 
            "selected_button": {
                "font":("Verdana", 12, "bold"),
                "foreground":"white",
                "activeforeground":"white", 
                "background":"#64a281", 
                "activebackground":"#64a281"
            }
        }


    def print_page(page_number):
        print("page number %s"%page_number)

    root = Tk()

    Label(root, text="Style 1:").pack(padx=20, anchor=W)
        
    pagination = My_Pagination1(root, 1, 5, command=print_page)
    pagination.pack(pady=(5,20), padx=20)
    
    Label(root, text="Style 2:").pack(padx=20, anchor=W)
    pagination = My_Pagination2(root, 1, 5, command=print_page)
    pagination.pack(pady=(5,20), padx=20)
    
    Label(root, text="Style 3:").pack(padx=20, anchor=W)
    pagination = My_Pagination3(root, 1,5, command=print_page)
    pagination.pack(pady=(5,20), padx=20)
    
    Label(root, text="Style 4:").pack(padx=20, anchor=W)
    pagination = My_Pagination4(root, 1,5, command=print_page)
    pagination.pack(pady=(5,20), padx=20)
    
    Label(root, text="Style 5:").pack(padx=20, anchor=W)
    pagination = My_Pagination5(root, 1,5, command=print_page)
    pagination.pack(pady=(5,20), padx=20)

    root.mainloop()

Diff to Previous Revision

--- revision 8 2016-11-25 15:44:15
+++ revision 9 2016-11-26 15:38:10
@@ -2,17 +2,24 @@
 # Author: Miguel Martínez López
 
 try:
-    from Tkinter import Tk
-    from ttk import Frame, Button, Style
+    from Tkinter import Tk, Label
+    from ttk import Frame
     from Tkconstants import *
 except ImportError:
-    from tkinter import Tk
-    from tkinter.ttk import Frame, Button, Style
+    from tkinter import Tk, Label
+    from tkinter.ttk import Frame
     from tkinter.constants import *
 
+class PageLabel(Label):
+    def __init__(self, master, is_selected, is_active, **kwargs):
+        Label.__init__(self, master, **kwargs)
+        self.is_selected = is_selected
+        self.is_active = is_active
+
+
 class Pagination(Frame):
-    _new_index = 0
-    def __init__(self, master, first_page, last_page, command =None):
+
+    def __init__(self, master, first_page, last_page, padding=3, command =None):
         if not hasattr(self, "pagination_style"):
             raise Exception("No pagination style defined")
         
@@ -20,64 +27,107 @@
 
         self._command = command
 
-        self._style_name_of_selected = 'SelectedPage%s.TButton'%Pagination._new_index
-        self._style_name_of_normal = 'Page%s.TButton'%Pagination._new_index
-
-        Pagination._new_index += 1      
-
-        s = Style()
-
-        padding = self.pagination_style.get("padding")
+        self._list_of_buttons = []
+
+        button = self._build_page_label(first_page)
+        button.pack(side=LEFT)
+
+        for page_number in range(first_page+1, last_page+1):
+            button = self._build_page_label(page_number)
+            button.pack(side=LEFT, padx=(padding, 0))
+        
+        self._selected_label = None
+
+    def _build_page_label(self, page_number):
+        label = PageLabel(self, text=page_number, is_selected=False, is_active=False, width=0)
+        
+        self._config_style(label)
+        label.bind("<1>", lambda event, label=label: self._on_button_selected(label))
+        
+        label.bind("<Enter>", lambda event, label=label: self._on_focus_in(label))
+        label.bind("<Leave>", lambda event, label=label: self._on_focus_out(label))
+        
+        self._list_of_buttons.append(label)
+
+        return label
+
+    def _on_focus_in(self, label):
+        label.is_active = True
+        self._config_style(label)
+
+    def _on_focus_out(self, label):
+        label.is_active = False
+        self._config_style(label)
+
+    def _config_style(self, label):
+        
         font = self.pagination_style.get("font")
-        
-        for style_name, style_config in ((self._style_name_of_normal, self.pagination_style["normal_button"]), (self._style_name_of_selected, self.pagination_style["selected_button"])):
-            if "padding" in style_config:
-                s.configure(style_name, padding=style_config["padding"])
-            elif padding is not None:
-                s.configure(style_name, padding=padding)
-
-            if "font" in style_config:
-                s.configure(style_name, font=style_config["font"])
-            elif font is not None:
-                s.configure(style_name, font=font)
-
-            if "background" in style_config and "activebackground" in style_config:
-                s.map(style_name, background=[('active', style_config["activebackground"]), ('!active', style_config["background"])])
-                
-            if "foreground" in style_config and "activeforeground" in style_config:
-                s.map(style_name, foreground=[('active', style_config["activeforeground"]), ('!active', style_config["foreground"])])
-
-        self._list_of_buttons = []
-
-        for page_number in range(first_page, last_page+1):
-            button = Button(self, text=page_number, style=self._style_name_of_normal, width=0)
-            button.configure(command=lambda button=button: self._on_button_selected(button))
-            button.pack(side=LEFT)
-
-            self._list_of_buttons.append(button)
-        
-        self._selected_button = None
-
-    def _on_button_selected(self, button):
-        if self._selected_button is not None:
-            self._selected_button.configure(style = self._style_name_of_normal)
-
-        self._selected_button = button
-        button.configure(style=self._style_name_of_selected)
-        
+        padx = self.pagination_style.get("padx")
+        pady = self.pagination_style.get("pady")
+
+        if label.is_selected:
+            style_config = self.pagination_style["selected_button"]
+        else:
+            style_config = self.pagination_style["normal_button"]
+            
+        config = {}
+        
+        if label.is_active:
+            if "activebackground" in style_config:
+                config["background"] = style_config["activebackground"]
+            if "activeforeground" in style_config:
+                config["foreground"] = style_config["activeforeground"]
+        else:
+            if "background" in style_config:
+                config["background"] = style_config["background"]
+            if "foreground" in style_config:
+                config["foreground"] = style_config["foreground"]
+
+        if "padx" in style_config:
+            config["padx"] = style_config["padx"]
+        else:
+            if padx is not None:
+                config["padx"] = padx
+
+        if "pady" in style_config:
+            config["pady"] = style_config["pady"]
+        else:
+            if pady is not None:
+                config["pady"] = pady 
+        
+        if "font" in style_config:
+            config["font"] = style_config["font"]
+        else:
+            if padx is not None:
+                config["font"] = padx
+        
+
+        label.configure(**config)
+
+    def _on_button_selected(self, label):
+
+        if self._selected_label is not None:
+            self._selected_label.is_selected = False
+            self._config_style(self._selected_label)
+
+        label.is_selected = True
+        self._selected_label = label
+
+        self._config_style(self._selected_label)
+
         if self._command is not None:
             self._command(self.selected_page)
 
     def select_page(self, page_number):
         page_number = int(page_number)
-        for button in self._list_of_buttons:
-            if int(button["text"]) == page_number:
-                self._selected_button = button
+        for label in self._list_of_buttons:
+            if int(label["text"]) == page_number:
+                self._selected_label = label
                 return
 
     @property
     def selected_page(self):
-        return int(self._selected_button["text"])
+        return int(self._selected_label["text"])
 
     page = selected_page
 
@@ -85,7 +135,8 @@
 if __name__ == "__main__":
     class My_Pagination1(Pagination):
         pagination_style = {
-            "padding":(12,6, 12,6),
+            "padx":12,
+            "pady": 6,
             "normal_button": {
                 "font": ("Verdana", 12),
                 "foreground": "#337ab7", 
@@ -104,7 +155,8 @@
 
     class My_Pagination2(Pagination):
         pagination_style = {
-            "padding":(12,6, 12,6),
+            "padx":12,
+            "pady":6,
             "normal_button": {
                 "font": ("Verdana", 12),
                 "foreground": "black", 
@@ -123,7 +175,8 @@
 
     class My_Pagination3(Pagination):
         pagination_style = {
-            "padding":(12,6, 12,6),
+            "padx":12,
+            "pady":6,
             "normal_button": {
                 "font": ("Verdana", 12),
                 "foreground": "#717171", 
@@ -142,7 +195,8 @@
         
     class My_Pagination4(Pagination):
         pagination_style = {
-            "padding":(12,6, 12,6),
+            "padx":12,
+            "pady":6,
             "normal_button": {
                 "font": ("Verdana", 12),
                 "foreground": "#feffff", 
@@ -161,7 +215,8 @@
 
     class My_Pagination5(Pagination):
         pagination_style = {
-            "padding":(12,6, 12,6),
+            "padx":12,
+            "pady":6,
             "normal_button": {
                 "font": ("Verdana", 12),
                 "foreground": "#2E4057", 
@@ -179,13 +234,6 @@
         }
 
 
-
-    try:
-        from ttk import Label
-    except ImportError:
-        from tkinter.ttk import Label
-
-
     def print_page(page_number):
         print("page number %s"%page_number)
 

History