# 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)