hytos / DTI_PID / DTI_PID / TrainingSymbolEditorDialog.py @ a64f92c8
이력 | 보기 | 이력해설 | 다운로드 (20.2 KB)
1 |
# coding: utf-8
|
---|---|
2 |
import sys |
3 |
import os, time, datetime |
4 |
from PyQt5.QtCore import * |
5 |
from PyQt5.QtGui import * |
6 |
from PyQt5.QtWidgets import * |
7 |
from AppDocData import * |
8 |
import TrainingSymbolEditor_UI |
9 |
import QtImageViewer |
10 |
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
11 |
from TrainingBoxItem import QTrainingBoxItem |
12 |
import cv2 |
13 |
import numpy as np |
14 |
from PIL import Image |
15 |
import AreaZoomCommand |
16 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
17 |
|
18 |
class QTrainingSymbolEditorDialog(QDialog): |
19 |
def __init__(self, parent, trainingImgPath, trainingLabelPath, boundaryLabelData, dateItem, boxItem): |
20 |
self.spinBoxFlag = False |
21 |
QDialog.__init__(self, parent)
|
22 |
self.setWindowFlag(Qt.WindowMinMaxButtonsHint)
|
23 |
|
24 |
self.trainingImgPath = trainingImgPath
|
25 |
self.trainingLabelPath = trainingLabelPath
|
26 |
self.boundaryLabelData = boundaryLabelData
|
27 |
self.dateItem = dateItem
|
28 |
self.boxItem = boxItem
|
29 |
self.isChanged = False |
30 |
|
31 |
appDocData = AppDocData.instance() |
32 |
project = appDocData.getCurrentProject() |
33 |
|
34 |
self.ui = TrainingSymbolEditor_UI.Ui_TrainingSymbolEditorDialog()
|
35 |
self.ui.setupUi(self) |
36 |
|
37 |
self.graphicsViewTrainingDrawing = QtImageViewer.QtImageViewer(self) |
38 |
self.graphicsViewTrainingDrawing.setParent(self.ui.centralWidget) |
39 |
self.graphicsViewTrainingDrawing.useDefaultCommand()
|
40 |
self.ui.verticalLayoutTrainingDrawing.addWidget(self.graphicsViewTrainingDrawing) |
41 |
|
42 |
self.graphicsViewZoomDrawing = QGraphicsView(self) |
43 |
self.graphicsViewZoomDrawing.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
44 |
self.graphicsViewZoomDrawing.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
45 |
self.graphicsViewZoomDrawing.setParent(self.ui.leftSideWidget) |
46 |
self.ui.horizontalLayoutZoomDrawing.addWidget(self.graphicsViewZoomDrawing) |
47 |
|
48 |
|
49 |
# 학습 이미지 읽어서 메인 뷰에 그림, 사이드 뷰에 추가
|
50 |
try:
|
51 |
#trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif')
|
52 |
cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY) |
53 |
cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
54 |
bytesPerLine = cvImg.shape[1]
|
55 |
image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8) |
56 |
|
57 |
self.graphicsViewTrainingDrawing.setImage(image)
|
58 |
|
59 |
# 사이드 뷰
|
60 |
if type(image) is QPixmap: |
61 |
pixmap = image |
62 |
elif type(image) is QImage: |
63 |
pixmap = QPixmap.fromImage(image) |
64 |
scene = QGraphicsScene() |
65 |
self.graphicsViewZoomDrawing.setScene(scene)
|
66 |
self._pixmapHandle = self.graphicsViewZoomDrawing.scene().addPixmap(pixmap) |
67 |
self.graphicsViewZoomDrawing.scene().setSceneRect(0, 0, pixmap.width(), pixmap.height()) |
68 |
self.graphicsViewZoomDrawing.fitInView(self.graphicsViewZoomDrawing.scene().sceneRect(), Qt.KeepAspectRatioByExpanding) |
69 |
rect = QGraphicsRectItem(0, 0, 0, 0) |
70 |
pen = QPen(Qt.SolidLine) |
71 |
pen.setColor(Qt.green) |
72 |
pen.setWidthF(1)
|
73 |
pen.setJoinStyle(Qt.MiterJoin) |
74 |
rect.setPen(pen) |
75 |
rect.setOpacity(0.7)
|
76 |
self.graphicsViewZoomDrawing.scene().addItem(rect)
|
77 |
|
78 |
except Exception as ex: |
79 |
from App import App |
80 |
from AppDocData import MessageType |
81 |
|
82 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
83 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
84 |
|
85 |
# 박스 읽어서 메인 뷰에 그림
|
86 |
try:
|
87 |
boxList = [] |
88 |
if self.boundaryLabelData is None: # already exist label file |
89 |
xml = parse(trainingLabelPath) |
90 |
root = xml.getroot() |
91 |
objects = list(root.iter('object')) |
92 |
for object_node in objects: |
93 |
name = object_node.find('name').text
|
94 |
boxNode = object_node.find('bndbox')
|
95 |
xMin = int(boxNode.find('xmin').text) |
96 |
yMin = int(boxNode.find('ymin').text) |
97 |
xMax = int(boxNode.find('xmax').text) |
98 |
yMax = int(boxNode.find('ymax').text) |
99 |
boxList.append([xMin, yMin, xMax - xMin, yMax - yMin, name]) |
100 |
else:
|
101 |
for data in boundaryLabelData: |
102 |
boxList.append([data[0], data[1], data[2], data[3], 'None']) |
103 |
|
104 |
for label in boxList: |
105 |
singleBox = QTrainingBoxItem(label[4], int(label[0]), int(label[1]), int(label[2]), int(label[3])) |
106 |
singleBox.transfer.onRemoved.connect(self.itemRemoved)
|
107 |
singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
108 |
except Exception as ex: |
109 |
from App import App |
110 |
from AppDocData import MessageType |
111 |
|
112 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
113 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
114 |
|
115 |
# label table
|
116 |
self.ui.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
|
117 |
self.ui.tableWidget.setColumnCount(1) |
118 |
self.ui.tableWidget.setSortingEnabled(True) |
119 |
|
120 |
self.ui.tableWidget.setHorizontalHeaderLabels([self.tr('Labels')]) |
121 |
self.ui.tableWidget.horizontalHeaderItem(0).setSizeHint(QSize(30, 30)) |
122 |
self.ui.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) |
123 |
self.ui.tableWidget.resizeColumnsToContents()
|
124 |
self.ui.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
125 |
self.ui.tableWidget.verticalHeader().hide()
|
126 |
|
127 |
self.ui.tableWidget.setRowCount(len(parent.labelList)) |
128 |
row = 0
|
129 |
for label in parent.labelList: |
130 |
textWidget = QTableWidgetItem(label[0])
|
131 |
self.ui.tableWidget.setItem(row, 0, textWidget) |
132 |
row += 1
|
133 |
|
134 |
self.ui.tableWidget.cellClicked.connect(self.listCellClicked) |
135 |
self.ui.pushButtonZoom.clicked.connect(self.onAreaZoom) |
136 |
self.ui.pushButtonSave.clicked.connect(self.pushButtonSaveClicked) |
137 |
self.ui.pushButtonCancel.clicked.connect(self.pushButtonCancelClicked) |
138 |
self.ui.pushButtonDelete.clicked.connect(self.pushButtonDeleteClicked) |
139 |
self.ui.pushButtonAdd.clicked.connect(self.pushButtonAddClicked) |
140 |
self.ui.pushButtonSplit.clicked.connect(self.pushButtonSplitClicked) |
141 |
self.ui.spinBoxLeft.valueChanged.connect(self.spinBoxChangedEvent) |
142 |
self.ui.spinBoxTop.valueChanged.connect(self.spinBoxChangedEvent) |
143 |
self.ui.spinBoxWidth.valueChanged.connect(self.spinBoxChangedEvent) |
144 |
self.ui.spinBoxHeight.valueChanged.connect(self.spinBoxChangedEvent) |
145 |
self.ui.lineEditChar.returnPressed.connect(self.pushButtonChangeClicked) |
146 |
|
147 |
self.removedItems = []
|
148 |
|
149 |
def listCellClicked(self, row, col): |
150 |
self.isChanged = True |
151 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
152 |
label = self.ui.tableWidget.item(row, col).text()
|
153 |
self.onCharChanged(label)
|
154 |
|
155 |
'''
|
156 |
@brief split boxitem by button click
|
157 |
@author euisung
|
158 |
@date 2018.10.31
|
159 |
'''
|
160 |
def pushButtonSplitClicked(self): |
161 |
self.isChanged = True |
162 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
163 |
if len(items) == 1: |
164 |
return
|
165 |
rect = items[0].rect()
|
166 |
secondBox = QTrainingBoxItem('', rect.x() + round(rect.width() / 2), rect.y(), round(rect.width() / 2), rect.height()) |
167 |
secondBox.transfer.onRemoved.connect(self.itemRemoved)
|
168 |
secondBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
169 |
items[0].setRect(rect.x(), rect.y(), round(rect.width() / 2), rect.height()) |
170 |
|
171 |
'''
|
172 |
@brief add boxitem by button click
|
173 |
@author euisung
|
174 |
@date 2018.10.17
|
175 |
'''
|
176 |
def pushButtonAddClicked(self): |
177 |
self.isChanged = True |
178 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
179 |
allItems = self.graphicsViewTrainingDrawing.scene().items()
|
180 |
totalWidth = 0
|
181 |
totalHeight = 0
|
182 |
count = 0
|
183 |
if len(items) == 1: |
184 |
rect = items[0].rect()
|
185 |
elif len(allItems) > 1: |
186 |
for item in allItems: |
187 |
if type(item) is QGraphicsPixmapItem: |
188 |
x = int(item.boundingRect().width() / 2) |
189 |
y = int(item.boundingRect().height()/ 2) |
190 |
elif hasattr(item, 'rect'): |
191 |
count += 1
|
192 |
totalWidth += item.rect().width() |
193 |
totalHeight += item.rect().height() |
194 |
|
195 |
rect = QRectF(x, y, round(totalWidth / count), round(totalHeight / count)) |
196 |
else:
|
197 |
for item in allItems: |
198 |
if type(item) is QGraphicsPixmapItem: |
199 |
x = int(item.boundingRect().width() / 2) |
200 |
y = int(item.boundingRect().height()/ 2) |
201 |
rect = QRectF(x, y, 5, 10) |
202 |
singleBox = QTrainingBoxItem('', rect.x() + 3, rect.y(), rect.width(), rect.height()) |
203 |
singleBox.transfer.onRemoved.connect(self.itemRemoved)
|
204 |
singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
205 |
|
206 |
'''
|
207 |
@brief delete boxitem by button click
|
208 |
@author euisung
|
209 |
@date 2018.10.17
|
210 |
'''
|
211 |
def pushButtonDeleteClicked(self): |
212 |
self.isChanged = True |
213 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
214 |
for item in items: |
215 |
item.transfer.onRemoved.emit(item) |
216 |
|
217 |
def onCharChanged(self, text): |
218 |
"""
|
219 |
change lineedit's text with given text
|
220 |
"""
|
221 |
if text:
|
222 |
self.ui.lineEditChar.setText(text)
|
223 |
self.pushButtonChangeClicked()
|
224 |
|
225 |
'''
|
226 |
@brief change boxitem char by button click
|
227 |
@author euisung
|
228 |
@date 2018.10.17
|
229 |
'''
|
230 |
def pushButtonChangeClicked(self): |
231 |
self.isChanged = True |
232 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
233 |
|
234 |
label = self.ui.lineEditChar.text()
|
235 |
if label == '' or label == 'None': |
236 |
return
|
237 |
|
238 |
for box in [box for box in items if type(box) is QTrainingBoxItem]: |
239 |
box.char = label |
240 |
box.textShowBox.setHtml(label) |
241 |
|
242 |
rowCount = self.ui.tableWidget.rowCount()
|
243 |
for index in range(rowCount): |
244 |
if self.ui.tableWidget.item(index, 0).text() == label: |
245 |
return
|
246 |
|
247 |
self.ui.tableWidget.setRowCount(rowCount + 1) |
248 |
textWidget = QTableWidgetItem(label) |
249 |
self.ui.tableWidget.setItem(rowCount, 0, textWidget) |
250 |
|
251 |
'''
|
252 |
@brief close dialog by button click
|
253 |
@author euisung
|
254 |
@date 2018.10.17
|
255 |
'''
|
256 |
def pushButtonCancelClicked(self): |
257 |
if self.isChanged: |
258 |
reply = QMessageBox.question(self, self.tr('Continue?'), self.tr('Changes may not have been saved.'), QMessageBox.Ignore, QMessageBox.Cancel) |
259 |
if reply == QMessageBox.Ignore:
|
260 |
QDialog.reject(self)
|
261 |
else:
|
262 |
QDialog.reject(self)
|
263 |
|
264 |
'''
|
265 |
@brief save box item by button click
|
266 |
@author euisung
|
267 |
@date 2018.10.16
|
268 |
'''
|
269 |
def pushButtonSaveClicked(self): |
270 |
xml = Element('annotation')
|
271 |
SubElement(xml, 'folder').text = 'None' |
272 |
SubElement(xml, 'filename').text = os.path.basename(self.trainingImgPath) |
273 |
|
274 |
pathNode = Element('path')
|
275 |
pathNode.text = self.trainingImgPath.replace('/', '\\') |
276 |
xml.append(pathNode) |
277 |
|
278 |
sourceNode = Element('source')
|
279 |
databaseNode = Element('database')
|
280 |
databaseNode.text = 'Unknown'
|
281 |
sourceNode.append(databaseNode) |
282 |
xml.append(sourceNode) |
283 |
|
284 |
items = self.graphicsViewTrainingDrawing.scene().items()
|
285 |
for item in items: |
286 |
if type(item) is QGraphicsPixmapItem: |
287 |
back = item |
288 |
break
|
289 |
|
290 |
sizeNode = Element('size')
|
291 |
widthNode = Element('width')
|
292 |
widthNode.text = str(int(back.boundingRect().width())) |
293 |
sizeNode.append(widthNode) |
294 |
heightNode = Element('height')
|
295 |
heightNode.text = str(int(back.boundingRect().height())) |
296 |
sizeNode.append(heightNode) |
297 |
depthNode = Element('depth')
|
298 |
depthNode.text = '3'
|
299 |
sizeNode.append(depthNode) |
300 |
xml.append(sizeNode) |
301 |
|
302 |
segmentedNode = Element('segmented')
|
303 |
segmentedNode.text = '0'
|
304 |
xml.append(segmentedNode) |
305 |
|
306 |
labelContent = [] |
307 |
counts = {} |
308 |
for item in items: |
309 |
if type(item) is QTrainingBoxItem: |
310 |
rect = item.rect() |
311 |
label, xMin, yMin, xMax, yMax = item.char, int(rect.x()), int(rect.y()), int(rect.x()) + int(rect.width()), int(rect.y()) + int(rect.height()) |
312 |
|
313 |
if label == 'None' or label == '': |
314 |
continue
|
315 |
if label not in labelContent: |
316 |
labelContent.append(label) |
317 |
counts[label] = 1
|
318 |
else:
|
319 |
counts[label] = counts[label] + 1
|
320 |
|
321 |
objectNode = Element('object')
|
322 |
nameNode = Element('name')
|
323 |
nameNode.text = label |
324 |
objectNode.append(nameNode) |
325 |
poseNode = Element('pose')
|
326 |
poseNode.text = 'Unspecified'
|
327 |
objectNode.append(poseNode) |
328 |
truncatedNode = Element('truncated')
|
329 |
truncatedNode.text = '0'
|
330 |
objectNode.append(truncatedNode) |
331 |
difficultNode = Element('difficult')
|
332 |
difficultNode.text = '0'
|
333 |
objectNode.append(difficultNode) |
334 |
|
335 |
bndboxNode = Element('bndbox')
|
336 |
xminNode = Element('xmin')
|
337 |
xminNode.text = str(xMin)
|
338 |
bndboxNode.append(xminNode) |
339 |
yminNode = Element('ymin')
|
340 |
yminNode.text = str(yMin)
|
341 |
bndboxNode.append(yminNode) |
342 |
xmaxNode = Element('xmax')
|
343 |
xmaxNode.text = str(xMax)
|
344 |
bndboxNode.append(xmaxNode) |
345 |
ymaxNode = Element('ymax')
|
346 |
ymaxNode.text = str(yMax)
|
347 |
bndboxNode.append(ymaxNode) |
348 |
objectNode.append(bndboxNode) |
349 |
|
350 |
xml.append(objectNode) |
351 |
|
352 |
ElementTree(xml).write(self.trainingLabelPath)
|
353 |
|
354 |
modifiedTime = str(datetime.datetime.strptime(time.ctime(os.path.getmtime(self.trainingLabelPath)), "%a %b %d %H:%M:%S %Y")) |
355 |
self.dateItem.setText(modifiedTime)
|
356 |
|
357 |
labelCount = [label + ':' + str(counts[label]) for label in labelContent] |
358 |
labels = ','.join(labelCount)
|
359 |
self.boxItem.setText(labels)
|
360 |
|
361 |
self.isChanged = False |
362 |
reply = QMessageBox.information(self, self.tr('Information'), self.tr('Save Success!'), QMessageBox.Ok, QMessageBox.Cancel) |
363 |
if reply == QMessageBox.Ok:
|
364 |
QDialog.reject(self)
|
365 |
|
366 |
'''
|
367 |
@brief chane box item's rect by button click
|
368 |
@author euisung
|
369 |
@date 2018.10.16
|
370 |
'''
|
371 |
def spinBoxChangedEvent(self, event): |
372 |
self.isChanged = True |
373 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
374 |
if (len(items) != 1) or self.spinBoxFlag: |
375 |
return
|
376 |
spinBoxName = self.sender().objectName()
|
377 |
rect = items[0].rect()
|
378 |
bound = self.graphicsViewZoomDrawing.scene().items()[0] |
379 |
|
380 |
if spinBoxName == 'spinBoxLeft': |
381 |
spinBoxValue = self.ui.spinBoxLeft.value()
|
382 |
items[0].setRect(QRectF(spinBoxValue, rect.y(), rect.width(), rect.height()))
|
383 |
items[0].setPosCustom()
|
384 |
elif spinBoxName == 'spinBoxTop': |
385 |
spinBoxValue = self.ui.spinBoxTop.value()
|
386 |
items[0].setRect(QRectF(rect.x(), spinBoxValue, rect.width(), rect.height()))
|
387 |
items[0].setPosCustom()
|
388 |
elif spinBoxName == 'spinBoxWidth': |
389 |
spinBoxValue = self.ui.spinBoxWidth.value()
|
390 |
items[0].setRect(QRectF(rect.x(), rect.y(), spinBoxValue, rect.height()))
|
391 |
items[0].setPosCustom()
|
392 |
elif spinBoxName == 'spinBoxHeight': |
393 |
spinBoxValue = self.ui.spinBoxHeight.value()
|
394 |
items[0].setRect(QRectF(rect.x(), rect.y(), rect.width(), spinBoxValue))
|
395 |
items[0].setPosCustom()
|
396 |
|
397 |
rect = items[0].rect()
|
398 |
bound.setRect(rect) |
399 |
rectSide = QRectF(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6) |
400 |
self.graphicsViewZoomDrawing.fitInView(rectSide)
|
401 |
self.graphicsViewTrainingDrawing.scene().update()
|
402 |
|
403 |
def onAreaZoom(self, action): |
404 |
if self.ui.pushButtonZoom.isChecked(): |
405 |
cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsViewTrainingDrawing)
|
406 |
cmd.onRejected.connect(self.onCommandRejected)
|
407 |
self.graphicsViewTrainingDrawing.command = cmd
|
408 |
|
409 |
def onCommandRejected(self, cmd): |
410 |
try:
|
411 |
if type(cmd) is AreaZoomCommand.AreaZoomCommand: |
412 |
self.ui.pushButtonZoom.setChecked(False) |
413 |
finally:
|
414 |
self.graphicsViewTrainingDrawing.useDefaultCommand()
|
415 |
|
416 |
def itemRemoved(self, item): |
417 |
try:
|
418 |
if type(item) is QTrainingBoxItem: |
419 |
self.removedItems.append(str(item.uid)) |
420 |
|
421 |
if item.scene is not None: item.scene().removeItem(item) |
422 |
except Exception as ex: |
423 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
424 |
|
425 |
'''
|
426 |
@brief key pressed event
|
427 |
@author euisung
|
428 |
@date 2018.11.05
|
429 |
'''
|
430 |
def keyPressEvent(self, event): |
431 |
try:
|
432 |
items = self.graphicsViewTrainingDrawing.scene().selectedItems()
|
433 |
if items and type(items[0]) is not QTrainingBoxItem: |
434 |
return
|
435 |
|
436 |
selectedItem = items[0]
|
437 |
closestItem = None
|
438 |
x = selectedItem.rect().x() |
439 |
|
440 |
if event.key() == Qt.Key_Left:
|
441 |
dx = sys.maxsize |
442 |
for item in self.graphicsViewTrainingDrawing.scene().items(): |
443 |
if type(item) is QTrainingBoxItem: |
444 |
if x - item.rect().x() > 0 and x - item.rect().x() < dx: |
445 |
closestItem = item |
446 |
dx = x - item.rect().x() |
447 |
if closestItem is not None: |
448 |
closestItem.setSelected(True)
|
449 |
selectedItem.setSelected(False)
|
450 |
closestItem.mousePressEvent('arrow key')
|
451 |
elif event.key() == Qt.Key_Right:
|
452 |
dx = -sys.maxsize |
453 |
for item in self.graphicsViewTrainingDrawing.scene().items(): |
454 |
if type(item) is QTrainingBoxItem: |
455 |
if x - item.rect().x() < 0 and x - item.rect().x() > dx: |
456 |
closestItem = item |
457 |
dx = x - item.rect().x() |
458 |
if closestItem is not None: |
459 |
closestItem.setSelected(True)
|
460 |
selectedItem.setSelected(False)
|
461 |
closestItem.mousePressEvent('arrow key')
|
462 |
elif event.key() == Qt.Key_Up:
|
463 |
self.ui.spinBoxWidth.setValue(self.ui.spinBoxWidth.value() + 1) |
464 |
elif event.key() == Qt.Key_Down:
|
465 |
self.ui.spinBoxWidth.setValue(self.ui.spinBoxWidth.value() - 1) |
466 |
elif event.key() == Qt.Key_Return and not self.ui.lineEditChar.hasFocus(): |
467 |
if self.ui.tableWidget.selectedItems(): |
468 |
self.isChanged = True |
469 |
self.onCharChanged(self.ui.tableWidget.selectedItems()[0].text()) |
470 |
except Exception as ex: |
471 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
472 |
from App import App |
473 |
from AppDocData import MessageType |
474 |
|
475 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
476 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
477 |
return None |