Skip to content

Commit 0324156

Browse files
committed
I04 1-172: I've added a button to start/stop the scan
1 parent 12e9bc6 commit 0324156

File tree

8 files changed

+137
-96
lines changed

8 files changed

+137
-96
lines changed

dls_barcode/camera/camera_switch.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ def __init__(self, camera_scanner, timeout_config):
1111
self._reset_top_scan_timer()
1212
self._switch_to_side()
1313

14-
def stop_live_capture(self):
14+
def _stop_live_capture(self):
1515
self._scanner.stop_scan()
1616
self._reset_top_scan_timer()
1717

1818
def restart_live_capture_from_side(self):
19-
self.stop_live_capture()
19+
self._stop_live_capture()
2020
self._switch_to_side()
2121
self._scanner.start_scan(CameraPosition.SIDE)
2222

2323
def restart_live_capture_from_top(self):
24-
self.stop_live_capture()
24+
self._stop_live_capture()
2525
self._switch_to_top()
2626
self._start_top_scan_timer()
2727
self._scanner.start_scan(CameraPosition.TOP)

dls_barcode/config/barcode_config_dialog.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ class BarcodeConfigDialog(ConfigDialog):
99
"""
1010
def __init__(self, config, to_run_before_test_camera):
1111
ConfigDialog.__init__(self, config)
12-
12+
self._to_run_before_test_camera = to_run_before_test_camera
1313
self._init_ui(to_run_before_test_camera)
1414
self.finalize_layout()
1515

1616
def _init_ui(self, to_run_before_test_camera):
1717
self.setGeometry(100, 100, 450, 400)
1818

19+
self._to_run_before_test_camera()
20+
1921
cfg = self._config
2022
add = self.add_item
2123

22-
camera_top = CameraConfigControl(cfg.get_top_camera_config(), to_run_before_test_camera)
23-
camera_side = CameraConfigControl(cfg.get_side_camera_config(), to_run_before_test_camera)
24+
camera_top = CameraConfigControl(cfg.get_top_camera_config())
25+
camera_side = CameraConfigControl(cfg.get_side_camera_config())
2426

2527
self.start_group("Colors")
2628
add(cfg.color_ok)

dls_barcode/config/camera_config_control.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ class CameraConfigControl(ConfigControl):
99
RES_TEXT_WIDTH = 50
1010
BUTTON_WIDTH = 100
1111

12-
def __init__(self, camera_config, to_run_before_test_camera):
12+
def __init__(self, camera_config):
1313
ConfigControl.__init__(self, camera_config)
1414
self._number_item = camera_config.camera_number
1515
self._width_item = camera_config.width
1616
self._height_item = camera_config.height
17-
self._to_run_before_test_camera = to_run_before_test_camera
1817
self._init_ui()
1918

2019
def _init_ui(self):
@@ -87,8 +86,6 @@ def _test_camera(self):
8786
QMessageBox.critical(self, "Camera Error", "Camera number, width, and height must be integers")
8887
return
8988

90-
self._to_run_before_test_camera()
91-
9289
# Check that we can connect to the camera
9390
try:
9491
stream = CameraStream(camera_num, camera_width, camera_height, use_default_as_backup=False)
@@ -130,6 +127,5 @@ def _test_camera(self):
130127

131128
def _open_camera_controls(self):
132129
camera_num = int(self.txt_number.text())
133-
self._to_run_before_test_camera()
134130
CameraStream.open_camera_controls(camera_num)
135131

dls_barcode/gui/image_frame.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,18 @@
77
class ImageFrame(QGroupBox):
88
""" GUI component. Displays an image of the currently selected barcode.
99
"""
10-
def __init__(self, width_item, height_item, title):
10+
def __init__(self, title):
1111
super(ImageFrame, self).__init__()
1212

1313
self.setTitle(title)
14-
self._width_item = width_item
15-
self._height_item = height_item
1614
self._init_ui()
1715

1816
def _init_ui(self):
1917
# Image frame - displays image of the currently selected scan record
2018
self._frame = QLabel()
2119
self._frame.setStyleSheet("background-color: black; color: red; font-size: 30pt; text-align: center")
22-
self._frame.setFixedWidth(self._width_item)
23-
self._frame.setFixedHeight(self._height_item)
20+
self._frame.setFixedWidth(500)
21+
self._frame.setFixedHeight(500)
2422
self._frame.setAlignment(Qt.AlignCenter)
2523

2624
vbox = QVBoxLayout()

dls_barcode/gui/main_window.py

Lines changed: 33 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@
66

77
from dls_barcode.config import BarcodeConfig, BarcodeConfigDialog
88
from dls_barcode.camera import CameraScanner, CameraSwitch, NoNewBarcodeMessage
9+
from dls_barcode.gui.scan_button import ScanButton
910
from dls_util import Beeper
1011
from dls_util.file import FileManager
1112
from .barcode_table import BarcodeTable
1213
from .image_frame import ImageFrame
1314
from .record_table import ScanRecordTable
1415
from .message_box import MessageBox
1516
from .message_factory import MessageFactory
17+
from .menu_bar import MenuBar
1618

17-
18-
RESULT_TIMER_PERIOD = 1000 # ms
19-
VIEW_TIMER_PERIOD = 1 # ms
20-
MESSAGE_TIMER_PERIOD = 1 # ms
19+
RESULT_TIMER_PERIOD = 1000 # ms
20+
VIEW_TIMER_PERIOD = 1 # ms
21+
MESSAGE_TIMER_PERIOD = 1 # ms
2122

2223

2324
class DiamondBarcodeMainWindow(QtGui.QMainWindow):
@@ -33,6 +34,7 @@ def __init__(self, config_file, version):
3334
self._record_table = None
3435
self._barcode_table = None
3536
self._image_frame = None
37+
self._scan_button = None
3638

3739
# Scan elements
3840
self._camera_scanner = None
@@ -71,29 +73,35 @@ def _init_ui(self):
7173
self.setWindowTitle('Diamond Puck Barcode Scanner')
7274
self.setWindowIcon(self._window_icon)
7375

74-
self.init_menu_bar()
76+
self._menu_bar = MenuBar(self.menuBar(), self._version, self._cleanup, self._on_options_action_clicked,
77+
self._on_about_action_clicked, self._exit_icon, self._config_icon, self._about_icon)
7578

7679
# Barcode table - lists all the barcodes in a record
7780
self._barcode_table = BarcodeTable(self._config)
7881

82+
# Scan button - start/stop scan
83+
self._scan_button = ScanButton('Start/stop scan', self._stop_capture_icon, self._start_capture_icon,
84+
self._on_scan_action_clicked)
85+
7986
# Image frame - displays image of the currently selected scan record
80-
self._image_frame = ImageFrame(500, 500, "Plate Image")
87+
self._image_frame = ImageFrame("Plate Image")
8188

8289
# Scan record table - lists all the records in the store
83-
self._record_table = ScanRecordTable(self._barcode_table, self._image_frame, self._config, self.on_record_table_clicked)
90+
self._record_table = ScanRecordTable(self._barcode_table, self._image_frame, self._config, self._cleanup)
8491

8592
# Message display
8693
self._message_box = MessageBox()
87-
self._message_box.setFixedHeight(64)
88-
89-
# Open options first to make sure the cameras are set up correctly.
90-
# Start live capture of the side as soon as the dialog box is closed
91-
self._open_options_dialog()
9294

9395
# Create layout
96+
9497
hbox = QtGui.QHBoxLayout()
9598
hbox.setSpacing(10)
96-
hbox.addWidget(self._record_table)
99+
100+
table_vbox = QtGui.QVBoxLayout()
101+
table_vbox.addWidget(self._record_table)
102+
table_vbox.addWidget(self._scan_button)
103+
104+
hbox.addLayout(table_vbox)
97105
hbox.addWidget(self._barcode_table)
98106

99107
img_vbox = QtGui.QVBoxLayout()
@@ -113,74 +121,26 @@ def _init_ui(self):
113121
def _init_icons(self):
114122
self._window_icon = QtGui.QIcon("..\\resources\\icons\\qr_code_32.png")
115123
self._start_capture_icon = self.style().standardIcon(QtGui.QStyle.SP_MediaPlay)
124+
self._stop_capture_icon = self.style().standardIcon(QtGui.QStyle.SP_MediaStop)
116125
self._exit_icon = self.style().standardIcon(QtGui.QStyle.SP_DialogCloseButton)
117126
self._config_icon = self.style().standardIcon(QtGui.QStyle.SP_FileDialogDetailedView)
118127
self._about_icon = self.style().standardIcon(QtGui.QStyle.SP_FileDialogInfoView)
119128

120-
def init_menu_bar(self):
121-
"""Create and populate the menu bar.
122-
"""
123-
# Continuous scanner mode
124-
live_action = QtGui.QAction(self._start_capture_icon, '&Camera Capture', self)
125-
live_action.setShortcut('Ctrl+W')
126-
live_action.setStatusTip('Capture continuously from camera')
127-
live_action.triggered.connect(self._on_scan_action_clicked)
128-
129-
# Exit Application
130-
exit_action = QtGui.QAction(self._exit_icon, '&Exit', self)
131-
exit_action.setShortcut('Ctrl+Q')
132-
exit_action.setStatusTip('Exit application')
133-
exit_action.triggered.connect(self._cleanup)
134-
exit_action.triggered.connect(QtGui.qApp.quit)
135-
136-
# Open options dialog
137-
options_action = QtGui.QAction(self._config_icon, '&Config', self)
138-
options_action.setShortcut('Ctrl+O')
139-
options_action.setStatusTip('Open Options Dialog')
140-
options_action.triggered.connect(self._on_options_action_clicked)
141-
142-
# Show version number
143-
about_action = QtGui.QAction(self._about_icon, "About", self)
144-
about_action.triggered.connect(self._on_about_action_clicked)
145-
146-
# Create menu bar
147-
menu_bar = self.menuBar()
148-
file_menu = menu_bar.addMenu('&File')
149-
file_menu.addAction(exit_action)
150-
151-
scan_menu = menu_bar.addMenu('&Scan')
152-
scan_menu.addAction(live_action)
153-
154-
option_menu = menu_bar.addMenu('&Options')
155-
option_menu.addAction(options_action)
156-
157-
help_menu = menu_bar.addMenu('?')
158-
help_menu.addAction(about_action)
159-
160129
def _on_about_action_clicked(self):
161130
QtGui.QMessageBox.about(self, 'About', "Version: " + self._version)
162131

163132
def _on_scan_action_clicked(self):
164133
print("MAIN: Scan menu clicked")
165134
if not self._camera_capture_alive():
166135
self._initialise_scanner()
167-
168-
self._restart_live_capture_from_side()
136+
self._restart_live_capture_from_side()
137+
else:
138+
self._cleanup()
169139

170140
def _on_options_action_clicked(self):
171-
result_ok = self._open_options_dialog()
172-
if not result_ok:
173-
return
174-
175-
self._cleanup()
176-
self._initialise_scanner()
177-
self._restart_live_capture_from_side()
178-
179-
def _open_options_dialog(self):
180-
dialog = BarcodeConfigDialog(self._config, self._before_test_camera)
141+
dialog = BarcodeConfigDialog(self._config, self._cleanup)
181142
dialog.setWindowIcon(self._config_icon)
182-
result_ok = dialog.exec_()
183-
return result_ok
143+
dialog.exec_()
184144

185145
def closeEvent(self, event):
186146
"""This overrides the method from the base class.
@@ -195,19 +155,12 @@ def _cleanup(self):
195155
self._camera_scanner.kill()
196156
self._camera_scanner = None
197157
self._camera_switch = None
158+
self._scan_button.setStartLayout()
198159

199160
def _initialise_scanner(self):
200161
self._camera_scanner = CameraScanner(self._result_queue, self._view_queue, self._message_queue, self._config)
201162
self._camera_switch = CameraSwitch(self._camera_scanner, self._config.top_camera_timeout)
202163

203-
def on_record_table_clicked(self):
204-
if self._camera_capture_alive():
205-
self._camera_switch.stop_live_capture()
206-
207-
def _before_test_camera(self):
208-
# We need to stop the cameras otherwise the Test Camera button won't be able to open them
209-
self._cleanup()
210-
211164
def _camera_capture_alive(self):
212165
return self._camera_scanner is not None and self._camera_switch is not None
213166

@@ -242,17 +195,17 @@ def _read_message_queue(self):
242195
self._message_box.display(MessageFactory.from_scanner_message(scanner_msg))
243196

244197
def _reset_msg_timer(self):
245-
self._duplicate_record_msg_timer = None
198+
self._record_msg_timer = None
246199

247200
def _start_msg_timer(self):
248-
self._duplicate_record_msg_timer = time.time()
201+
self._record_msg_timer = time.time()
249202

250203
def _msg_timer_is_running(self):
251-
return self._duplicate_record_msg_timer is not None
204+
return self._record_msg_timer is not None
252205

253206
def _has_msg_timer_timeout(self):
254207
timeout = 2 * RESULT_TIMER_PERIOD / 1000
255-
return self._msg_timer_is_running() and time.time() - self._duplicate_record_msg_timer > timeout
208+
return self._msg_timer_is_running() and time.time() - self._record_msg_timer > timeout
256209

257210
def _read_result_queue(self):
258211
""" Called every second; read any new results from the scan results queue, store them and display them.
@@ -314,4 +267,4 @@ def _restart_live_capture_from_top(self):
314267
def _restart_live_capture_from_side(self):
315268
self._reset_msg_timer()
316269
self._camera_switch.restart_live_capture_from_side()
317-
270+
self._scan_button.setStopLayout()

dls_barcode/gui/menu_bar.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from __future__ import division
2+
3+
from PyQt4.QtGui import qApp, QAction, QMainWindow
4+
5+
6+
class MenuBar(QMainWindow):
7+
""" GUI component. Displays a start/stop button
8+
"""
9+
10+
def __init__(self, mainMenu, version, clean_up, on_options_action_clicked, on_about_action_clicked, exit_icon, config_icon,
11+
about_icon):
12+
super(MenuBar, self).__init__()
13+
self._version = version
14+
self._cleanup = clean_up
15+
self._on_options_action_clicked = on_options_action_clicked
16+
self._on_about_action_clicked = on_about_action_clicked
17+
self._exit_icon = exit_icon
18+
self._config_icon = config_icon
19+
self._about_icon = about_icon
20+
self._mainMenu = mainMenu
21+
22+
self._init_ui()
23+
24+
def _init_ui(self):
25+
"""Create and populate the menu bar.
26+
"""
27+
# Exit Application
28+
exit_action = QAction(self._exit_icon, '&Exit', self)
29+
exit_action.setShortcut('Ctrl+Q')
30+
exit_action.setStatusTip('Exit application')
31+
exit_action.triggered.connect(self._cleanup)
32+
exit_action.triggered.connect(qApp.quit)
33+
34+
# Open options dialog
35+
options_action = QAction(self._config_icon, '&Config', self)
36+
options_action.setShortcut('Ctrl+O')
37+
options_action.setStatusTip('Open Options Dialog')
38+
options_action.triggered.connect(self._on_options_action_clicked)
39+
40+
# Show version number
41+
about_action = QAction(self._about_icon, "About", self)
42+
about_action.triggered.connect(self._on_about_action_clicked)
43+
44+
# Create menu bar
45+
file_menu = self._mainMenu.addMenu('&File')
46+
file_menu.addAction(exit_action)
47+
48+
option_menu = self._mainMenu.addMenu('&Options')
49+
option_menu.addAction(options_action)
50+
51+
help_menu = self._mainMenu.addMenu('?')
52+
help_menu.addAction(about_action)

dls_barcode/gui/message_box.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ def __init__(self):
1414

1515
self.setTitle("Information")
1616

17+
self.setMaximumHeight(100)
18+
1719
self._style_sheets = {MessageType.INFO: BASIC_STYLE_SHEET + BLACK,
1820
MessageType.WARNING: BASIC_STYLE_SHEET + RED}
1921
self._init_ui()

0 commit comments

Comments
 (0)