#!/usr/bin/env python
"""
Widget functions for ncvue.
Convenience functions for adding Tkinter widgets.
This module was written by Matthias Cuntz while at Institut National de
Recherche pour l'Agriculture, l'Alimentation et l'Environnement (INRAE), Nancy,
France.
Copyright (c) 2020-2021 Matthias Cuntz - mc (at) macu (dot) de
Released under the MIT License; see LICENSE file for details.
History:
* Written Nov-Dec 2020 by Matthias Cuntz (mc (at) macu (dot) de)
* Added tooltips to all widgets with class Tooltip, Jan 2021, Matthias Cuntz
* Added add_tooltip widget, Jan 2021, Matthias Cuntz
* add_spinbox returns also label widget, Jan 2021, Matthias Cuntz
.. moduleauthor:: Matthias Cuntz
The following functions are provided:
.. autosummary::
Tooltip
add_checkbutton
add_combobox
add_entry
add_imagemenu
add_menu
add_scale
add_spinbox
add_tooltip
"""
from __future__ import absolute_import, division, print_function
import tkinter as tk
try:
import tkinter.ttk as ttk
except Exception:
import sys
print('Using the themed widget set introduced in Tk 8.5.')
print('Try to use mcview.py, which uses wxpython instead.')
sys.exit()
from idlelib.tooltip import Hovertip
__all__ = ['Tooltip',
'add_checkbutton', 'add_combobox', 'add_entry',
'add_imagemenu', 'add_menu', 'add_scale', 'add_spinbox',
'add_tooltip']
[docs]def add_combobox(frame, label="", values=[], command=None, tooltip="",
**kwargs):
"""
Add a left-aligned ttk.Combobox with a ttk.Label before.
Parameters
----------
frame : tk widget
Parent widget
label : str, optional
Text that appears in front of the combobox (default: "")
values : list of str, optional
The choices that will appear in the drop-down menu (default: [])
command : function, optional
Handler function to be bound to the combobox for the event
<<ComboboxSelected>> (default: None).
tooltip : str, optional
Tooltip appearing after one second when hovering over
the combobox (default: "" = no tooltip)
**kwargs : option=value pairs, optional
All other options will be passed to ttk.Combobox
Returns
-------
tk.StringVar, ttk.Combobox
variable for the text before the combobox, combobox widget
tk.StringVar
variable for the text of the tooltip, if given.
Examples
--------
>>> self.rowzxy = ttk.Frame(self)
>>> self.rowzxy.pack(side=tk.TOP, fill=tk.X)
>>> self.xlbl, self.x = add_combobox(
... self.rowzxy, label="x", values=columns, command=self.selected)
"""
width = kwargs.pop('width', 25)
cb_label = tk.StringVar()
cb_label.set(label)
label = ttk.Label(frame, textvariable=cb_label)
label.pack(side=tk.LEFT)
cb = ttk.Combobox(frame, values=values, width=width, **kwargs)
# long = len(max(values, key=len))
# cb.configure(width=(max(20, long//2)))
if command is not None:
cb.bind("<<ComboboxSelected>>", command)
cb.pack(side=tk.LEFT)
if tooltip:
ttip = tk.StringVar()
ttip.set(tooltip)
cbtip = Tooltip(cb, ttip)
return cb_label, cb, ttip
else:
return cb_label, cb
[docs]def add_entry(frame, label="", text="", command=None, tooltip="", **kwargs):
"""
Add a left-aligned ttk.Entry with a ttk.Label before.
Parameters
----------
frame : tk widget
Parent widget
label : str, optional
Text that appears in front of the entry (default: "")
text : str, optional
Initial text in the entry area (default: "")
command : function, optional
Handler function to be bound to the entry for the events
<Return>, '<Key-Return>', <KP_Enter>, and '<FocusOut>' (default: None).
tooltip : str, optional
Tooltip appearing after one second when hovering over
the entry (default: "" = no tooltip)
**kwargs : option=value pairs, optional
All other options will be passed to ttk.Entry
Returns
-------
tk.StringVar, tk.StringVar
variable for the text before the entry,
variable for the text in the entry area
tk.StringVar
variable for the text of the tooltip, if given.
Examples
--------
>>> self.rowxyopt = ttk.Frame(self)
>>> self.rowxyopt.pack(side=tk.TOP, fill=tk.X)
>>> self.lslbl, self.ls = add_entry(
... self.rowxyopt, label="ls", text='-',
... width=4, command=self.selected_y)
"""
entry_label = tk.StringVar()
entry_label.set(label)
label = ttk.Label(frame, textvariable=entry_label)
label.pack(side=tk.LEFT)
entry_text = tk.StringVar()
entry_text.set(text)
entry = ttk.Entry(frame, textvariable=entry_text, **kwargs)
if command is not None:
entry.bind('<Return>', command) # return
entry.bind('<Key-Return>', command) # return
entry.bind('<KP_Enter>', command) # return of numeric keypad
entry.bind('<FocusOut>', command) # tab or click
entry.pack(side=tk.LEFT)
if tooltip:
ttip = tk.StringVar()
ttip.set(tooltip)
etip = Tooltip(entry, ttip)
return entry_label, entry_text, ttip
else:
return entry_label, entry_text
[docs]def add_scale(frame, label="", ini=0, tooltip="", **kwargs):
"""
Add a left-aligned ttk.Scale with a ttk.Label before.
Parameters
----------
frame : tk widget
Parent widget
label : str, optional
Text that appears in front of the scale (default: "")
ini : float, optional
Initial value of scale (default: 0)
tooltip : str, optional
Tooltip appearing after one second when hovering over
the scale (default: "" = no tooltip)
**kwargs : option=value pairs, optional
All other options will be passed to ttk.Scale
Returns
-------
tk.StringVar, tk.DoubleVar, ttk.Scale
variable for the text before the scale,
value of scale,
scale widget
tk.StringVar
variable for the text of the tooltip, if given.
Examples
--------
>>> self.rowzxy = ttk.Frame(self)
>>> self.rowzxy.pack(side=tk.TOP, fill=tk.X)
>>> self.xlbl, self.x = add_scale(
... self.rowzxy, label="x", values=columns, command=self.selected)
"""
s_label = tk.StringVar()
s_label.set(label)
label = ttk.Label(frame, textvariable=s_label)
label.pack(side=tk.LEFT)
s_val = tk.DoubleVar()
s_val.set(ini)
s = ttk.Scale(frame, variable=s_val, **kwargs)
s.pack(side=tk.LEFT)
if tooltip:
ttip = tk.StringVar()
ttip.set(tooltip)
stip = Tooltip(s, ttip)
return s_label, s_val, s, ttip
else:
return s_label, s_val, s
[docs]def add_spinbox(frame, label="", values=[], command=None, tooltip="",
**kwargs):
"""
Add a left-aligned tk.Spinbox with a ttk.Label before.
Parameters
----------
frame : tk widget
Parent widget
label : str, optional
Text that appears in front of the spinbox (default: "")
values : list of str, optional
The list of choices on the spinbox (default: [])
command : function, optional
Handler function bound to
<Return>, '<Key-Return>', <KP_Enter>, and '<FocusOut>' (default: None).
tooltip : str, optional
Tooltip appearing after one second when hovering over
the spinbox (default: "" = no tooltip)
**kwargs : option=value pairs, optional
All other options will be passed to tk.Spinbox
Returns
-------
tk.StringVar, ttk.Label, tk.StringVar, tk.Spinbox
variable for the text before the spinbox,
label widget,
variable for the text in the spinbox area,
spinbox widget
tk.StringVar
variable for the text of the tooltip, if given.
Examples
--------
>>> self.rowlev = ttk.Frame(self)
>>> self.rowlev.pack(side=tk.TOP, fill=tk.X)
>>> self.dlval, self.dl, self.dval, self.d = add_spinbox(
... self.rowlev, label="dim", values=range(0,10),
... command=self.spinned)
"""
width = kwargs.pop('width', 1)
sbl_val = tk.StringVar()
sbl_val.set(label)
sbl = ttk.Label(frame, textvariable=sbl_val)
sbl.pack(side=tk.LEFT)
sb_val = tk.StringVar()
if len(values) > 0:
sb_val.set(str(values[0]))
sb = tk.Spinbox(frame, values=values, command=command, width=width,
textvariable=sb_val, **kwargs)
if command is not None:
sb.bind('<Return>', command) # return
sb.bind('<Key-Return>', command) # return
sb.bind('<KP_Enter>', command) # return of numeric keypad
sb.bind('<FocusOut>', command) # tab or click
sb.pack(side=tk.LEFT)
if tooltip:
ttip = tk.StringVar()
ttip.set(tooltip)
sbtip = Tooltip(sb, ttip)
return sbl_val, sbl, sb_val, sb, ttip
else:
return sbl_val, sbl, sb_val, sb