summaryrefslogtreecommitdiff
path: root/src/bidding_data_gui.py
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2015-10-27 19:26:40 +0100
committeremkael <emkael@tlen.pl>2015-10-27 19:26:40 +0100
commitb7a229b74d02fbfb291d2c32a3a3f134cae26de3 (patch)
treec4815d0026bc48939a84efdeb846bfe3339c64d2 /src/bidding_data_gui.py
parent74148e918eb7876883e268e95ba8902516acc47b (diff)
* background thread-enabled GUI
Diffstat (limited to 'src/bidding_data_gui.py')
-rw-r--r--src/bidding_data_gui.py68
1 files changed, 43 insertions, 25 deletions
diff --git a/src/bidding_data_gui.py b/src/bidding_data_gui.py
index 298ae1b..ad1fe59 100644
--- a/src/bidding_data_gui.py
+++ b/src/bidding_data_gui.py
@@ -10,6 +10,7 @@ files generated by JFR Pary.
import Tkinter as tk
import tkFileDialog
import tkMessageBox
+import Queue
import logging as log
import os
@@ -17,7 +18,6 @@ import threading
class BiddingGUI(tk.Frame):
-
"""GUI frame class."""
# Tk variable to store tournament result file path
@@ -33,7 +33,7 @@ class BiddingGUI(tk.Frame):
Sanitizes input parameters, handles warning/error messages,
imports main module (from CLI script) and runs it.
"""
- self.run_btn['state'] = tk.DISABLED
+ self.queue(self.run_btn.__setitem__, 'state', tk.DISABLED)
try:
# reset error/warning count and log output field
self.__gui_logger.reset_counts()
@@ -55,26 +55,28 @@ class BiddingGUI(tk.Frame):
# inform of any warnings/errors that might have occuerd
if self.__gui_logger.errors():
- tkMessageBox.showerror(
- 'Błąd!',
- ('Podczas wykonywania programu wystąpiły błędy ' +
- 'w liczbie: %d\n' +
- 'Sprawdź dziennik logów') % self.__gui_logger.errors())
+ self.queue(tkMessageBox.showerror,
+ 'Błąd!',
+ ('Podczas wykonywania programu wystąpiły błędy ' +
+ 'w liczbie: %d\n' +
+ 'Sprawdź dziennik logów')
+ % self.__gui_logger.errors())
elif self.__gui_logger.warnings():
- tkMessageBox.showwarning(
- 'Błąd!',
- ('Podczas wykonywania programu wystąpiły ostrzeżenia ' +
- 'w liczbie: %d\n' +
- 'Sprawdź dziennik logów') % self.__gui_logger.warnings())
+ self.queue(tkMessageBox.showwarning,
+ 'Błąd!',
+ ('Podczas wykonywania programu wystąpiły ' +
+ 'ostrzeżenia w liczbie: %d\n' +
+ 'Sprawdź dziennik logów')
+ % self.__gui_logger.warnings())
except Exception as ex:
# JFRBidding errors are logged
# (and notified of after entire execution),
# other exceptions should halt execution and display error message
log.getLogger('root').error(ex)
- tkMessageBox.showerror('Błąd!', ex)
+ self.queue(tkMessageBox.showerror, 'Błąd!', ex)
raise
finally:
- self.run_btn['state'] = tk.NORMAL
+ self.queue(self.run_btn.__setitem__, 'state', tk.NORMAL)
def tour_select(self):
"""
@@ -100,6 +102,26 @@ class BiddingGUI(tk.Frame):
title='Wybierz plik z danymi licytacji',
filetypes=[('BWS files', '.bws'), ('all files', '.*')]))
+ __queue = None
+
+ def queue(self, callback, *args, **kwargs):
+ """Add message (function call) to GUI interaction queue."""
+ if self.__queue is None:
+ self.__queue = Queue.Queue()
+ self.__queue.put((callback, args, kwargs))
+
+ def process_queue(self):
+ """Process GUI interaction queue from other threads."""
+ if self.__queue is None:
+ self.__queue = Queue.Queue()
+ try:
+ callback, args, kwargs = self.__queue.get_nowait()
+ except Queue.Empty:
+ self.master.after(100, self.process_queue)
+ else:
+ callback(*args, **kwargs)
+ self.master.after(10, self.process_queue)
+
def __init__(self, master=None):
"""
Construct the frame.
@@ -122,6 +144,8 @@ class BiddingGUI(tk.Frame):
self.pack(expand=1, fill=tk.BOTH)
# finally, set logging up
self.__configure_logging()
+ # fire up interthread queue
+ self.after(100, self.process_queue)
def __configure_grid_cells(self, columns, rows):
"""Set expand with window resize for cells of layout grid."""
@@ -211,7 +235,6 @@ class BiddingGUI(tk.Frame):
def __configure_logging(self):
"""Set up logging facility, bound to log output field."""
class GUILogHandler(log.Handler):
-
"""Log handler which allows output to Tk Text widget."""
def __init__(self, text):
@@ -222,15 +245,10 @@ class BiddingGUI(tk.Frame):
def emit(self, record):
"""Output the message."""
msg = self.format(record)
-
- def append():
- """Append message to the Text widget, at the end."""
- self.text.insert(tk.END, msg + '\n')
- # scroll to the bottom, afterwards
- self.text.yview(tk.END)
-
- # call log output asynchronously
- self.text.after(0, append)
+ # Append message to the Text widget, at the end."""
+ self.text.master.queue(self.text.insert, tk.END, msg + '\n')
+ # scroll to the bottom, afterwards
+ self.text.master.queue(self.text.yview, tk.END)
def handle(self, record):
"""Handle log message record (count errors/warnings)."""
@@ -256,7 +274,7 @@ class BiddingGUI(tk.Frame):
"""Reset stats and log output."""
self.__warning_count = 0
self.__error_count = 0
- self.text.delete(1.0, tk.END)
+ self.text.master.queue(self.text.delete, 1.0, tk.END)
# disable default logging limits/thresholds
log.basicConfig(