summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2019-07-07 20:45:05 +0200
committeremkael <emkael@tlen.pl>2019-07-07 20:45:05 +0200
commit4f55701e1b291a9a6da9eb7aef5802e6bc20cbf0 (patch)
tree8468abc56148f0abd27ac3e2bc40961ddd8d4c11
parente563236fb07628dfec57f7cd887b63f4d87e2067 (diff)
Numeric values and spinboxes handled in custom widget
-rw-r--r--jfr_playoff/gui/frames/__init__.py33
-rw-r--r--jfr_playoff/gui/frames/match.py75
-rw-r--r--jfr_playoff/gui/frames/network.py29
-rw-r--r--jfr_playoff/gui/frames/team.py43
-rw-r--r--jfr_playoff/gui/frames/translations.py6
-rw-r--r--jfr_playoff/gui/frames/visual.py81
-rw-r--r--jfr_playoff/gui/tabs.py15
-rw-r--r--jfr_playoff/gui/variables.py24
8 files changed, 177 insertions, 129 deletions
diff --git a/jfr_playoff/gui/frames/__init__.py b/jfr_playoff/gui/frames/__init__.py
index 89e0155..e50231d 100644
--- a/jfr_playoff/gui/frames/__init__.py
+++ b/jfr_playoff/gui/frames/__init__.py
@@ -7,11 +7,7 @@ import tkinter as tk
from tkinter import ttk
import tkMessageBox
-def getIntVal(widget, default=0):
- try:
- return int(widget.get().strip())
- except ValueError:
- return default
+from ..variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
def setPanelState(frame, state):
for child in frame.winfo_children():
@@ -175,7 +171,7 @@ class RepeatableFrame(tk.Frame):
class RepeatableEntry(RepeatableFrame):
def renderContent(self):
- self.value = tk.StringVar()
+ self.value = NotifyStringVar()
self.field = ttk.Entry(self, textvariable=self.value)
self.field.pack(expand=True, fill=tk.BOTH)
@@ -262,7 +258,7 @@ class WidgetSelectionFrame(ScrollableFrame):
addBtn.pack(side=tk.BOTTOM)
def renderContent(self, container):
- self.value = tk.IntVar()
+ self.value = NotifyIntVar()
for idx, widget in enumerate(self.widgets):
(ttk.Radiobutton(
container, variable=self.value, value=idx,
@@ -359,7 +355,7 @@ class SelectionFrame(ScrollableFrame):
self.renderHeader(container)
for idx, option in enumerate(self.options):
key = self._mapValue(idx, option)
- self.values[key] = tk.IntVar()
+ self.values[key] = NotifyIntVar()
self.renderOption(container, option, idx)
if self.selected and key in self.selected:
self.values[key].set(True)
@@ -369,7 +365,7 @@ class RefreshableOptionMenu(ttk.OptionMenu):
self._valueVariable = variable
self._valueVariable.trace('w', self._valueSet)
self._lastValue = variable.get()
- newVar = tk.StringVar()
+ newVar = NotifyStringVar()
ttk.OptionMenu.__init__(self, master, newVar, *args, **kwargs)
self._valueLock = False
self.refreshOptions()
@@ -457,4 +453,21 @@ class TraceableText(tk.Text):
self._variableLock = False
return result
-# TODO: NumericSpinBox instead of getIntVal
+class NumericSpinbox(tk.Spinbox):
+ def __init__(self, *args, **kwargs):
+ kwargs['justify'] = tk.RIGHT
+ self._variable = None
+ if 'textvariable' in kwargs:
+ self._variable = kwargs['textvariable']
+ self._default = kwargs['from_'] if 'from_' in kwargs else 0
+ tk.Spinbox.__init__(self, *args, **kwargs)
+ if self._variable is not None:
+ if not isinstance(self._variable, NotifyNumericVar):
+ raise AttributeError(
+ 'NumericSpinbox variable must be NotifyNumericVar')
+ self._variable.trace('w', self._onChange)
+
+ def _onChange(self, *args):
+ val = self._variable.get()
+ if val is None:
+ self._variable.set(self._default)
diff --git a/jfr_playoff/gui/frames/match.py b/jfr_playoff/gui/frames/match.py
index 99eb1b3..4c8736c 100644
--- a/jfr_playoff/gui/frames/match.py
+++ b/jfr_playoff/gui/frames/match.py
@@ -5,23 +5,24 @@ from tkinter.font import Font
from tkinter import ttk
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
-from ..frames import WidgetRepeater, RepeatableEntry, getIntVal
+from ..frames import WidgetRepeater, RepeatableEntry, NumericSpinbox
from ..frames import SelectionFrame, SelectionButton, RefreshableOptionMenu
from ..frames.team import DBSelectionField, TeamSelectionFrame
from ..frames.team import TeamSelectionButton
from ..frames.visual import PositionsSelectionFrame
+from ..variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
class SwissSettingsFrame(RepeatableFrame):
SOURCE_LINK = 0
SOURCE_DB = 1
def _setPositionInfo(self, *args):
- tournamentFrom = getIntVal(self.setFrom, default=1)
+ tournamentFrom = self.setFrom.get(default=1)
tournamentTo = min(
- getIntVal(self.setTo, default=1) \
+ self.setTo.get(default=1) \
if self.setToEnabled.get() else 9999,
len(self.winfo_toplevel().getTeams()))
- swissFrom = getIntVal(self.fetchFrom, default=1)
+ swissFrom = self.fetchFrom.get(default=1)
swissTo = swissFrom + tournamentTo - tournamentFrom
if tournamentTo < tournamentFrom:
self.positionsInfo.configure(text='brak miejsc do ustawienia')
@@ -44,16 +45,16 @@ class SwissSettingsFrame(RepeatableFrame):
else tk.DISABLED)
def renderContent(self):
- self.source = tk.IntVar()
- self.fetchDB = tk.StringVar()
- self.fetchLink = tk.StringVar()
- self.setFrom = tk.StringVar()
- self.setToEnabled = tk.IntVar()
- self.setTo = tk.StringVar()
- self.fetchFromEnabled = tk.IntVar()
- self.fetchFrom = tk.StringVar()
- self.linkLabel = tk.StringVar()
- self.linkRelPath = tk.StringVar()
+ self.source = NotifyIntVar()
+ self.fetchDB = NotifyStringVar()
+ self.fetchLink = NotifyStringVar()
+ self.setFrom = NotifyNumericVar()
+ self.setToEnabled = NotifyIntVar()
+ self.setTo = NotifyNumericVar()
+ self.fetchFromEnabled = NotifyIntVar()
+ self.fetchFrom = NotifyNumericVar()
+ self.linkLabel = NotifyStringVar()
+ self.linkRelPath = NotifyStringVar()
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
@@ -81,7 +82,7 @@ class SwissSettingsFrame(RepeatableFrame):
(ttk.Label(
self, text='Ustaw od miejsca: ')).grid(
row=4, column=0, sticky=tk.W, padx=18)
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.setFrom,
from_=1, to=999, width=5)).grid(
row=4, column=1, sticky=tk.W)
@@ -89,7 +90,7 @@ class SwissSettingsFrame(RepeatableFrame):
self, variable=self.setToEnabled,
text='Ustaw do miejsca: ')).grid(
row=5, column=0, sticky=tk.W)
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.setTo,
from_=1, to=999, width=5)).grid(
row=5, column=1, sticky=tk.W)
@@ -97,7 +98,7 @@ class SwissSettingsFrame(RepeatableFrame):
self, variable=self.fetchFromEnabled,
text='Pobierz od miejsca: ')).grid(
row=6, column=0, sticky=tk.W)
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.fetchFrom,
from_=1, to=999, width=5)).grid(
row=6, column=1, sticky=tk.W)
@@ -279,12 +280,12 @@ class BracketMatchSettingsFrame(GuiFrame):
self.teams = [allTeams[idx-1] for idx in teams]
def renderContent(self):
- self.source = tk.IntVar()
+ self.source = NotifyIntVar()
self.source.trace('w', self._enablePanels)
self.source.trace('w', self._configChangeNotify)
- self.selected = tk.IntVar()
+ self.selected = NotifyIntVar()
self.selected.trace('w', self._enablePanels)
- self.selectedIndex = tk.StringVar()
+ self.selectedIndex = NotifyStringVar()
self.positions = []
self.winners = []
self.losers = []
@@ -436,23 +437,23 @@ class MatchSettingsFrame(RepeatableFrame):
def renderContent(self):
self.nameLabel = ttk.Label(self)
- self.matchID = tk.IntVar()
+ self.matchID = NotifyIntVar()
self.matchID.trace('w', self._updateName)
self.matchID.set(self.winfo_toplevel().getNewMatchID(self))
self.winfo_toplevel().bind(
'<<PhaseRenamed>>', self._updateName, add='+')
- self.link = tk.StringVar()
+ self.link = NotifyStringVar()
- self.source = tk.IntVar()
+ self.source = NotifyIntVar()
self.source.trace('w', self._enablePanels)
- self.scoreDB = tk.StringVar()
- self.scoreRound = tk.IntVar()
- self.scoreTable = tk.IntVar()
- self.scoreCustom = [tk.StringVar(), tk.StringVar()]
- self.scoreNotFinished = tk.IntVar()
+ self.scoreDB = NotifyStringVar()
+ self.scoreRound = NotifyNumericVar()
+ self.scoreTable = NotifyNumericVar()
+ self.scoreCustom = [NotifyStringVar(), NotifyStringVar()]
+ self.scoreNotFinished = NotifyIntVar()
self.scoreNotFinished.trace('w', self._enablePanels)
- self.scoreBoards = tk.IntVar()
+ self.scoreBoards = NotifyNumericVar()
self.winnerPositions = []
self.loserPositions = []
@@ -493,11 +494,11 @@ class MatchSettingsFrame(RepeatableFrame):
self.SCORE_SOURCE_DB: [
DBSelectionField(scoreGroup, self.scoreDB, self.scoreDB.get()),
ttk.Label(scoreGroup, text='Runda:'),
- tk.Spinbox(
+ NumericSpinbox(
scoreGroup, width=3,
textvariable=self.scoreRound, from_=1, to=999),
ttk.Label(scoreGroup, text='Stół:'),
- tk.Spinbox(
+ NumericSpinbox(
scoreGroup, width=3,
textvariable=self.scoreTable, from_=1, to=999)
],
@@ -505,15 +506,15 @@ class MatchSettingsFrame(RepeatableFrame):
ttk.Entry(scoreGroup, textvariable=self.link),
# TODO: TC support (Round/Session)
#ttk.Label(scoreGroup, text='Sesja:'),
- #tk.Spinbox(
+ #NumericSpinbox(
# scoreGroup,
#textvariable=self.scoreSession, from_=1, to=999),
#ttk.Label(scoreGroup, text='Runda:'),
- #tk.Spinbox(
+ #NumericSpinbox(
# scoreGroup,
#textvariable=self.scoreRound, from_=1, to=999),
ttk.Label(scoreGroup, text='Stół:'),
- tk.Spinbox(
+ NumericSpinbox(
scoreGroup, width=3,
textvariable=self.scoreTable, from_=1, to=999)
],
@@ -528,7 +529,7 @@ class MatchSettingsFrame(RepeatableFrame):
ttk.Checkbutton(
scoreGroup, variable=self.scoreNotFinished,
text='mecz nie został zakończony, rozegrano:'),
- tk.Spinbox(
+ NumericSpinbox(
scoreGroup, width=3,
textvariable=self.scoreBoards, from_=0, to=999),
ttk.Label(scoreGroup, text='rozdań')
@@ -684,8 +685,8 @@ class MatchPhaseFrame(ScrollableFrame):
self.winfo_toplevel().event_generate('<<PhaseRenamed>>', when='tail')
def renderContent(self, container):
- self.name = tk.StringVar()
- self.link = tk.StringVar()
+ self.name = NotifyStringVar()
+ self.link = NotifyStringVar()
self.previousLink = ''
headerFrame = tk.Frame(container)
diff --git a/jfr_playoff/gui/frames/network.py b/jfr_playoff/gui/frames/network.py
index 7112171..d44ff49 100644
--- a/jfr_playoff/gui/frames/network.py
+++ b/jfr_playoff/gui/frames/network.py
@@ -7,8 +7,9 @@ from tkinter import ttk
import tkMessageBox as tkmb
from ...db import PlayoffDB
-from ..frames import RepeatableEntry, WidgetRepeater
-from ..frames import GuiFrame, ScrollableFrame, getIntVal
+from ..frames import RepeatableEntry, WidgetRepeater, NumericSpinbox
+from ..frames import GuiFrame, ScrollableFrame
+from ..variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
def network_test(connFunction, testLabel):
try:
@@ -28,7 +29,7 @@ class MySQLConfigurationFrame(GuiFrame):
if len(self.host.get().strip()):
return {
'host': self.host.get().strip(),
- 'port': getIntVal(self.port, default=3306),
+ 'port': self.port.get(default=3306),
'user': self.user.get().strip(),
'pass': self.pass_.get().strip()
}
@@ -51,13 +52,13 @@ class MySQLConfigurationFrame(GuiFrame):
'<<DBSettingsChanged>>', when='tail')
def renderContent(self):
- self.host = tk.StringVar()
+ self.host = NotifyStringVar()
self.host.trace('w', self._changeNotify)
- self.port = tk.StringVar()
+ self.port = NotifyNumericVar()
self.port.trace('w', self._changeNotify)
- self.user = tk.StringVar()
+ self.user = NotifyStringVar()
self.user.trace('w', self._changeNotify)
- self.pass_ = tk.StringVar()
+ self.pass_ = NotifyStringVar()
self.pass_.trace('w', self._changeNotify)
self.columnconfigure(0, weight=1)
@@ -72,7 +73,7 @@ class MySQLConfigurationFrame(GuiFrame):
(ttk.Label(frame, text='Port:')).grid(
row=0, column=2, sticky=tk.E)
- (tk.Spinbox(
+ (NumericSpinbox(
frame, textvariable=self.port, width=5,
from_=0, to=65535)).grid(row=0, column=3, sticky=tk.W)
@@ -116,8 +117,8 @@ class GoniecConfigurationFrame(GuiFrame):
def test():
goniec = socket.socket()
goniec.connect(
- (self.host.get().strip(), getIntVal(
- self.port, self.DEFAULT_PORT)))
+ (self.host.get().strip(),
+ self.port.get(default=self.DEFAULT_PORT)))
goniec.close()
self.testError = network_test(test, self.testLabel)
@@ -126,10 +127,10 @@ class GoniecConfigurationFrame(GuiFrame):
tkmb.showerror('Błąd połączenia z Gońcem', self.testError)
def renderContent(self):
- self.enable = tk.IntVar()
+ self.enable = NotifyIntVar()
self.enable.trace('w', self._enableWidgets)
- self.host = tk.StringVar()
- self.port = tk.StringVar()
+ self.host = NotifyStringVar()
+ self.port = NotifyNumericVar()
self.columnconfigure(0, weight=1)
@@ -144,7 +145,7 @@ class GoniecConfigurationFrame(GuiFrame):
self.hostField.grid(row=1, column=1)
(ttk.Label(frame, text='Port:')).grid(row=1, column=2)
- self.portField = tk.Spinbox(
+ self.portField = NumericSpinbox(
frame, textvariable=self.port, width=5)
self.portField.grid(row=1, column=3)
diff --git a/jfr_playoff/gui/frames/team.py b/jfr_playoff/gui/frames/team.py
index 90394d0..2a19866 100644
--- a/jfr_playoff/gui/frames/team.py
+++ b/jfr_playoff/gui/frames/team.py
@@ -5,31 +5,34 @@ from tkinter.font import Font
from tkinter import ttk
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
-from ..frames import WidgetRepeater, RepeatableEntry
+from ..frames import WidgetRepeater, RepeatableEntry, NumericSpinbox
from ..frames import SelectionButton, SelectionFrame, RefreshableOptionMenu
-from ..frames import getIntVal, setPanelState
+from ..frames import setPanelState
+from ..variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
class ManualTeamRow(RepeatableFrame):
def renderContent(self):
- self.fullname = tk.StringVar()
+ self.fullname = NotifyStringVar()
+ self.shortname = NotifyStringVar()
+ self.flag = NotifyStringVar()
+ self.position = NotifyNumericVar()
+ for var in [self.fullname, self.shortname, self.flag, self.position]:
+ var.trace('w', self._changeNotify)
+
fullnameField = ttk.Entry(self, width=20, textvariable=self.fullname)
fullnameField.grid(row=0, column=0)
- self.shortname = tk.StringVar()
shortnameField = ttk.Entry(self, width=20, textvariable=self.shortname)
shortnameField.grid(row=0, column=1)
- self.flag = tk.StringVar()
flagField = ttk.Entry(self, width=10, textvariable=self.flag)
flagField.grid(row=0, column=2)
- self.position = tk.StringVar()
positionField = ttk.Entry(self, width=10, textvariable=self.position)
positionField.grid(row=0, column=3)
- for var in [self.fullname, self.shortname, self.flag, self.position]:
- var.trace('w', self._changeNotify)
+
self._changeNotify(None)
def getValue(self):
flag = self.flag.get().strip()
- position = getIntVal(self.position, None)
+ position = self.position.get()
return [
self.fullname.get().strip(), self.shortname.get().strip(),
flag if len(flag) else None, position
@@ -162,7 +165,7 @@ class TeamFetchSettingsFrame(GuiFrame):
teams['database'] = self.fetchDB.get()
if len(self.finishingPositions):
teams['final_positions'] = self.finishingPositions
- maxTeams = getIntVal(self.fetchLimit)
+ maxTeams = self.fetchLimit.get()
if maxTeams:
teams['max_teams'] = maxTeams
return teams
@@ -176,14 +179,14 @@ class TeamFetchSettingsFrame(GuiFrame):
self.fetchDBField.configure(state=tk.NORMAL)
def renderContent(self):
- self.fetchSource = tk.IntVar()
+ self.fetchSource = NotifyIntVar()
self.fetchSource.trace('w', self._sourceChange)
self.fetchSource.trace('w', self._changeNotify)
- self.fetchDB = tk.StringVar()
+ self.fetchDB = NotifyStringVar()
self.fetchDB.trace('w', self._changeNotify)
- self.link = tk.StringVar()
+ self.link = NotifyStringVar()
self.link.trace('w', self._changeNotify)
- self.fetchLimit = tk.StringVar()
+ self.fetchLimit = NotifyNumericVar()
self.fetchLimit.trace('w', self._changeNotify)
self.columnconfigure(3, weight=1)
@@ -207,7 +210,7 @@ class TeamFetchSettingsFrame(GuiFrame):
(ttk.Label(self, text='Pobierz do ')).grid(
row=2, column=0, columnspan=2, sticky=tk.W)
- (tk.Spinbox(
+ (NumericSpinbox(
self, from_=0, to=9999, width=5, justify=tk.RIGHT,
textvariable=self.fetchLimit)).grid(
row=2, column=2, sticky=tk.W)
@@ -259,7 +262,7 @@ class TeamSettingsFrame(ScrollableFrame):
self.teams = self.winfo_toplevel().getTeams()
def renderContent(self, container):
- self.teamFormat = tk.IntVar()
+ self.teamFormat = NotifyIntVar()
self.teamFormat.trace('w', self._enablePanels)
self.teamFormat.trace('w', self._changeNotify)
@@ -324,7 +327,7 @@ class TeamAliasRow(RepeatableFrame):
def renderContent(self):
self.columnconfigure(0, weight=0)
self.columnconfigure(1, weight=1)
- self.teamName = tk.StringVar()
+ self.teamName = NotifyStringVar()
list = TeamList(self, self.teamName, self.teamName.get())
list.configure(width=20)
list.grid(
@@ -384,10 +387,10 @@ class TeamPreviewFrame(ScrollableFrame):
team[2] = ''
self.teamList.insert('', tk.END, values=team, tag=idx)
if idx >= len(self.tieFields):
- self.tieValues.append(tk.StringVar())
+ self.tieValues.append(NotifyNumericVar())
self.tieValues[idx].trace('w', self._tieValueChangeNotify)
self.tieFields.append(
- tk.Spinbox(
+ NumericSpinbox(
container, from_=0, to=9999,
width=5, font=Font(size=10),
textvariable=self.tieValues[idx]))
@@ -429,7 +432,7 @@ class TeamPreviewFrame(ScrollableFrame):
def getTieConfig(self):
teams = self._getTeams()
- ties = [(teams[idx], getIntVal(val, 0))
+ ties = [(teams[idx], val.get(default=0))
for idx, val in enumerate(self.tieValues)]
return [team[0][0] for team
in sorted(ties, key=lambda t: t[1])
diff --git a/jfr_playoff/gui/frames/translations.py b/jfr_playoff/gui/frames/translations.py
index 2429bfe..3ba660f 100644
--- a/jfr_playoff/gui/frames/translations.py
+++ b/jfr_playoff/gui/frames/translations.py
@@ -7,13 +7,15 @@ from tkinter import ttk
from ..frames import RepeatableFrame, WidgetRepeater, ScrollableFrame
from ...i18n import PLAYOFF_I18N_DEFAULTS
+from ..variables import NotifyStringVar
class TranslationRow(RepeatableFrame):
def renderContent(self):
- self.key = tk.StringVar()
+ self.key = NotifyStringVar()
+ self.value = NotifyStringVar()
+
(ttk.Entry(self, textvariable=self.key, width=40)).pack(
side=tk.LEFT, fill=tk.BOTH, expand=True)
- self.value = tk.StringVar()
(ttk.Entry(self, textvariable=self.value, width=80)).pack(
side=tk.RIGHT, fill=tk.BOTH, expand=True)
diff --git a/jfr_playoff/gui/frames/visual.py b/jfr_playoff/gui/frames/visual.py
index 0762e37..3e09445 100644
--- a/jfr_playoff/gui/frames/visual.py
+++ b/jfr_playoff/gui/frames/visual.py
@@ -5,9 +5,10 @@ from tkinter import ttk
import tkColorChooser as tkcc
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
-from ..frames import WidgetRepeater, getIntVal
-from ..frames import SelectionFrame, RefreshableOptionMenu
+from ..frames import WidgetRepeater
+from ..frames import SelectionFrame, RefreshableOptionMenu, NumericSpinbox
from ..frames.team import TeamSelectionButton
+from ..variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
class VisualSettingsFrame(GuiFrame):
DEFAULT_VALUES = {
@@ -29,20 +30,20 @@ class VisualSettingsFrame(GuiFrame):
}
def renderContent(self):
- self.startingPositionIndicators = tk.IntVar()
- self.finishingPositionIndicators = tk.IntVar()
- self.boxWidth = tk.IntVar()
- self.boxHeight = tk.IntVar()
- self.boxMargin = tk.IntVar()
- self.shortenTeamNames = tk.IntVar()
- self.teamNameLength = tk.IntVar()
- self.teamNameEllipsis = tk.StringVar()
- self.teamNamePredict = tk.IntVar()
- self.teamNamePlaceholder = tk.StringVar()
- self.teamNameSortPredictions = tk.IntVar()
- self.teamLabelSeparator = tk.StringVar()
- self.teamNameSeparator = tk.StringVar()
- self.teamNamePrefix = tk.StringVar()
+ self.startingPositionIndicators = NotifyIntVar()
+ self.finishingPositionIndicators = NotifyIntVar()
+ self.boxWidth = NotifyNumericVar()
+ self.boxHeight = NotifyNumericVar()
+ self.boxMargin = NotifyNumericVar()
+ self.shortenTeamNames = NotifyIntVar()
+ self.teamNameLength = NotifyNumericVar()
+ self.teamNameEllipsis = NotifyStringVar()
+ self.teamNamePredict = NotifyIntVar()
+ self.teamNamePlaceholder = NotifyStringVar()
+ self.teamNameSortPredictions = NotifyIntVar()
+ self.teamLabelSeparator = NotifyStringVar()
+ self.teamNameSeparator = NotifyStringVar()
+ self.teamNamePrefix = NotifyStringVar()
indicatorsFrame = ttk.LabelFrame(self, text='Znaczniki pozycji:')
indicatorsFrame.grid(row=0, column=0, sticky=tk.W+tk.E+tk.N+tk.S)
@@ -64,19 +65,19 @@ class VisualSettingsFrame(GuiFrame):
variable=self.finishingPositionIndicators)).grid(
row=1, column=0, sticky=tk.W)
- (tk.Spinbox(
- dimensionsFrame, width=5, justify=tk.RIGHT, from_=1, to=999,
+ (NumericSpinbox(
+ dimensionsFrame, width=5, from_=1, to=999,
textvariable=self.boxWidth)).grid(
row=0, column=0, sticky=tk.W)
(ttk.Label(dimensionsFrame, text='x')).grid(row=0, column=1)
- (tk.Spinbox(
- dimensionsFrame, width=5, justify=tk.RIGHT, from_=1, to=999,
+ (NumericSpinbox(
+ dimensionsFrame, width=5, from_=1, to=999,
textvariable=self.boxHeight)).grid(
row=0, column=2, sticky=tk.W)
(ttk.Label(dimensionsFrame, text='odstępy')).grid(
row=1, column=0, columnspan=2, sticky=tk.E)
- (tk.Spinbox(
- dimensionsFrame, width=5, justify=tk.RIGHT, from_=1, to=999,
+ (NumericSpinbox(
+ dimensionsFrame, width=5, from_=1, to=999,
textvariable=self.boxMargin)).grid(
row=1, column=2, sticky=tk.W)
@@ -84,8 +85,8 @@ class VisualSettingsFrame(GuiFrame):
teamNamesFrame, text='skracaj do',
variable=self.shortenTeamNames)).grid(
row=0, column=0, columnspan=2)
- nameLength = tk.Spinbox(
- teamNamesFrame, width=5, justify=tk.RIGHT, from_=1, to=999,
+ nameLength = NumericSpinbox(
+ teamNamesFrame, width=5, from_=1, to=999,
textvariable=self.teamNameLength)
nameLength.grid(row=0, column=2, sticky=tk.W)
lengthLabel = ttk.Label(teamNamesFrame, text='znaków')
@@ -197,22 +198,23 @@ class MatchList(RefreshableOptionMenu):
class BoxPositionFrame(RepeatableFrame):
def renderContent(self):
- self.match = tk.StringVar()
- self.vertical = tk.IntVar()
- self.horizontal = tk.IntVar()
+ self.match = NotifyStringVar()
+ self.vertical = NotifyNumericVar()
+ self.horizontal = NotifyNumericVar()
self.matchBox = MatchList(self, self.match)
self.matchBox.configure(width=20)
self.matchBox.grid(row=0, column=0)
+
(ttk.Label(self, text=' w pionie:')).grid(row=0, column=1)
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.vertical, from_=0, to=9999,
- width=5, justify=tk.RIGHT)).grid(
+ width=5)).grid(
row=0, column=2)
(ttk.Label(self, text=' w poziomie (-1 = automatyczna):')).grid(
row=0, column=3)
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.horizontal, from_=-1, to=9999,
- width=5, justify=tk.RIGHT)).grid(
+ width=5)).grid(
row=0, column=4)
self.setValue([])
@@ -262,19 +264,20 @@ class LineStyle(GuiFrame):
self.colourBtn.configure(bg=colour)
def renderContent(self):
+ self.hOffset = NotifyNumericVar()
+ self.vOffset = NotifyNumericVar()
+
(ttk.Label(self, text='kolor:')).grid(row=0, column=0)
self.colourBtn = tk.Button(self, width=2, command=self._selectColour)
self.colourBtn.grid(row=0, column=1)
(ttk.Label(self, text='margines w poziomie:')).grid(row=0, column=2)
- self.hOffset = tk.StringVar()
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.hOffset, from_=-50, to=50,
- width=5, justify=tk.RIGHT)).grid(row=0, column=3)
+ width=5)).grid(row=0, column=3)
(ttk.Label(self, text='margines w pionie:')).grid(row=0, column=4)
- self.vOffset = tk.StringVar()
- (tk.Spinbox(
+ (NumericSpinbox(
self, textvariable=self.vOffset, from_=-50, to=50,
- width=5, justify=tk.RIGHT)).grid(row=0, column=5)
+ width=5)).grid(row=0, column=5)
def setValue(self, value):
self._setColour(value[0])
@@ -345,8 +348,8 @@ class PositionStyleFrame(RepeatableFrame):
self.positions = values
def renderContent(self):
- self.name = tk.StringVar()
- self.description = tk.StringVar()
+ self.name = NotifyStringVar()
+ self.description = NotifyStringVar()
self.columnconfigure(1, weight=1)
self.columnconfigure(5, weight=1)
diff --git a/jfr_playoff/gui/tabs.py b/jfr_playoff/gui/tabs.py
index 1656fc7..a12a993 100644
--- a/jfr_playoff/gui/tabs.py
+++ b/jfr_playoff/gui/tabs.py
@@ -7,12 +7,13 @@ from tkinter import ttk
import tkFileDialog as tkfd
import tkMessageBox as tkmb
-from .frames import TraceableText
+from .frames import TraceableText, NumericSpinbox
from .frames.match import *
from .frames.network import *
from .frames.team import *
from .frames.translations import *
from .frames.visual import *
+from .variables import NotifyStringVar, NotifyIntVar, NotifyNumericVar
from ..data import PlayoffData
from ..db import PlayoffDB
@@ -46,12 +47,12 @@ class MainSettingsTab(PlayoffTab):
return 'Główne ustawienia'
def initData(self):
- self.outputPath = tk.StringVar()
- self.pageTitle = tk.StringVar()
- self.pageLogoh = tk.StringVar()
- self.refresh = tk.IntVar()
+ self.outputPath = NotifyStringVar()
+ self.pageTitle = NotifyStringVar()
+ self.pageLogoh = NotifyStringVar()
+ self.refresh = NotifyIntVar()
self.refresh.trace('w', self._updateRefreshFields)
- self.refreshInterval = tk.StringVar()
+ self.refreshInterval = NotifyNumericVar()
def _chooseOutputPath(self):
currentPath = self.outputPath.get()
@@ -135,7 +136,7 @@ class MainSettingsTab(PlayoffTab):
command=self._updateRefreshFields, variable=self.refresh)).grid(
row=0, column=0)
(ttk.Label(refreshPanel, text='co:')).grid(row=0, column=1)
- self.intervalField = tk.Spinbox(
+ self.intervalField = NumericSpinbox(
refreshPanel, from_=30, to=3600, width=5, justify=tk.RIGHT,
textvariable=self.refreshInterval)
self.intervalField.grid(row=0, column=2)
diff --git a/jfr_playoff/gui/variables.py b/jfr_playoff/gui/variables.py
new file mode 100644
index 0000000..abb3cc1
--- /dev/null
+++ b/jfr_playoff/gui/variables.py
@@ -0,0 +1,24 @@
+#coding=utf-8
+
+import tkinter as tk
+
+class NotifyVar(tk.Variable):
+ def __init__(self, *args, **kwargs):
+ tk.Variable.__init__(self, *args, **kwargs)
+ self.trace('w', self._onChange)
+
+ def _onChange(self, *args):
+ self._root.event_generate('<<ValueChanged>>', when='tail')
+
+class NotifyStringVar(NotifyVar, tk.StringVar):
+ pass
+
+class NotifyIntVar(NotifyVar, tk.IntVar):
+ pass
+
+class NotifyNumericVar(NotifyStringVar):
+ def get(self, default=None):
+ try:
+ return int(str(NotifyStringVar.get(self)).strip())
+ except ValueError:
+ return default