개정판 a4707ffe
modified issue #663:
- 심볼, 텍스트, 라인을 사용자가 선택하여 선별적으로 인식할 수 있도록 한다
DTI_PID/DTI_PID/App.py | ||
---|---|---|
12 | 12 |
from PyQt5.QtSvg import * |
13 | 13 |
from PyQt5 import QtWidgets |
14 | 14 |
|
15 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) |
|
15 | 16 |
from AppDocData import AppDocData |
16 | 17 |
|
17 | 18 |
class App(QApplication): |
19 |
""" |
|
20 |
This is App class inherits from QApplication |
|
21 |
""" |
|
18 | 22 |
def __init__(self, args): |
19 | 23 |
super(App, self).__init__(args) |
20 | 24 |
appStyle = AppDocData.instance().loadAppStyle() |
... | ... | |
73 | 77 |
AppDocData.instance().setCurrentProject(selectedProject) |
74 | 78 |
app._mainWnd = MainWindow.instance() |
75 | 79 |
app._mainWnd.show() |
80 |
sys.exit(app.exec_()) |
|
76 | 81 |
except Exception as ex: |
77 |
print('에러가 발생했습니다.\n', ex) |
|
78 |
|
|
79 |
sys.exit(app.exec_()) |
|
82 |
print('에러가 발생했습니다.\n', ex) |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
2 | 2 |
|
3 | 3 |
import sys |
4 | 4 |
import os |
5 |
|
|
6 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) |
|
5 | 7 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands') |
6 | 8 |
import CreateCommand |
7 | 9 |
import CropCommand |
... | ... | |
48 | 50 |
from TextItemFactory import TextItemFactory |
49 | 51 |
|
50 | 52 |
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane): |
53 |
""" |
|
54 |
This is MainWindow class |
|
55 |
""" |
|
51 | 56 |
addMessage = pyqtSignal(Enum, str) |
52 | 57 |
|
53 | 58 |
''' |
... | ... | |
1710 | 1715 |
AppDocData.instance().setCurrentProject(selectedProject) |
1711 | 1716 |
app._mainWnd = MainWindow.instance() |
1712 | 1717 |
app._mainWnd.show() |
1718 |
sys.exit(app.exec_()) |
|
1713 | 1719 |
except Exception as ex: |
1714 |
print('에러가 발생했습니다.\n', ex)
|
|
1715 |
|
|
1716 |
sys.exit(app.exec_())
|
|
1720 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
|
|
1721 |
finally: |
|
1722 |
pass
|
DTI_PID/DTI_PID/RecognitionDialog.py | ||
---|---|---|
77 | 77 |
''' |
78 | 78 |
def procCounter(self): # A slot takes no params |
79 | 79 |
try: |
80 |
if self.isSymbolTextChecked: |
|
81 |
Worker.executeRecognition(self.drawDetectedItems, self.path, self.listWidget, self.isSymbolTextChecked, self) |
|
80 |
if self.isSymbolChecked or self.isTextChecked: |
|
81 |
Worker.executeRecognition(self.drawDetectedItems, self.path, self.listWidget, self) |
|
82 |
|
|
83 |
if self.isLineChecked: |
|
82 | 84 |
Worker.recognizeLine(self.drawDetectedLines, self.path, self.listWidget, self.graphicsView, self) |
83 |
elif self.isLineChecked: |
|
84 |
Worker.recognizeLine(self.path, self.listWidget, self.graphicsView, self) |
|
85 |
else: |
|
86 |
self.finished.emit() |
|
87 | 85 |
except Exception as ex: |
88 | 86 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
89 | 87 |
self.displayLog.emit(MessageType.Error, message) |
88 |
finally: |
|
89 |
self.finished.emit() |
|
90 | 90 |
|
91 | 91 |
''' |
92 | 92 |
@brief remove small objects from given image |
... | ... | |
167 | 167 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
168 | 168 |
MainWindow.instance().displayMessage.emit(MessageType.Error, message) |
169 | 169 |
|
170 |
''' |
|
170 |
@staticmethod |
|
171 |
def executeRecognition(drawDetectedItems, path, listWidget, worker): |
|
172 |
""" |
|
171 | 173 |
@brief Main function |
172 | 174 |
@author Jeongwoo |
173 | 175 |
@date |
... | ... | |
183 | 185 |
Jeongwoo 2018.06.21 If noteTextInfoList is None, change from None to empty list |
184 | 186 |
humkyung 2018.08.20 remove alreay existing symbol and text item before recognizing |
185 | 187 |
block until drawing reconized objects |
186 |
''' |
|
187 |
@staticmethod |
|
188 |
def executeRecognition(drawDetectedItems, path, listWidget, isSymbolTextChecked, worker): |
|
188 |
""" |
|
189 | 189 |
import re |
190 | 190 |
from TextDetector import TextDetector |
191 | 191 |
|
... | ... | |
248 | 248 |
if area is not None: |
249 | 249 |
area.img = appDocData.imgSrc[round(area.y):round(area.y+area.height), round(area.x):round(area.x+area.width)] |
250 | 250 |
|
251 |
maxProgressValue = 0 |
|
251 | 252 |
listWidget.addItem("Start recognition : " + mainRes) |
252 |
worker.displayTitle.emit('심볼 인식 중...') |
|
253 |
if isSymbolTextChecked: |
|
254 |
threadLock.acquire() |
|
255 |
offset = (area.x, area.y) if area is not None else (0,0) |
|
253 |
threadLock.acquire() |
|
254 |
offset = (area.x, area.y) if area is not None else (0,0) |
|
255 |
if worker.isTextChecked: |
|
256 | 256 |
textAreas = textDetector.detectTextAreas(area.img if area is not None else appDocData.imgSrc, offset) |
257 |
### calculate total count of symbol |
|
258 | 257 |
maxProgressValue = len(textAreas) + 1 |
258 |
|
|
259 |
if worker.isSymbolChecked: |
|
260 |
### calculate total count of symbol |
|
259 | 261 |
for targetItem in targetSymbolList: |
260 | 262 |
if type(targetItem) is list: |
261 | 263 |
maxProgressValue += len(targetItem) |
262 | 264 |
else: |
263 | 265 |
maxProgressValue += 1 |
264 | 266 |
### up to here |
265 |
threadLock.release()
|
|
267 |
threadLock.release() |
|
266 | 268 |
|
269 |
if worker.isSymbolChecked: |
|
270 |
worker.displayTitle.emit('심볼 인식 중...') |
|
271 |
|
|
267 | 272 |
# detect equipments |
268 | 273 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
269 | 274 |
for symbol in targetSymbolList[0]: |
... | ... | |
285 | 290 |
cv2.imwrite(os.path.join(project.getTempPath(), 'Tile', item.getName()+'.png'), _img) |
286 | 291 |
## up to here |
287 | 292 |
|
293 |
if worker.isTextChecked: |
|
288 | 294 |
worker.displayTitle.emit('텍스트 인식 중...') |
289 | 295 |
textDetector.recognizeText(appDocData.imgSrc, offset, textAreas, searchedSymbolList, worker, listWidget, maxProgressValue) |
290 | 296 |
textInfoList = textDetector.textInfoList.copy() if textDetector.textInfoList is not None else None |
... | ... | |
299 | 305 |
|
300 | 306 |
appDocData.imgName = os.path.splitext(os.path.basename(mainRes))[0] |
301 | 307 |
|
302 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
303 |
for sym in searchedSymbolList: |
|
304 |
pool.submit(Worker.removeDetectedSymbol, sym, appDocData.imgSrc) |
|
305 |
pool.shutdown(wait = True) |
|
306 |
|
|
307 |
## Remove Noise |
|
308 |
kernel1 = np.ones((2, 2), np.uint8) |
|
309 |
appDocData.imgSrc = cv2.dilate(appDocData.imgSrc, kernel1) |
|
310 |
appDocData.imgSrc = cv2.erode(appDocData.imgSrc, kernel1) |
|
308 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
309 |
for sym in searchedSymbolList: |
|
310 |
pool.submit(Worker.removeDetectedSymbol, sym, appDocData.imgSrc) |
|
311 |
pool.shutdown(wait = True) |
|
311 | 312 |
|
312 |
removedSymbolImgPath = os.path.join(project.getTempPath(), os.path.basename(path))
|
|
313 |
cv2.imwrite(removedSymbolImgPath, appDocData.imgSrc)
|
|
314 |
|
|
315 |
area = AppDocData.instance().getArea('Drawing')
|
|
316 |
if area is not None: |
|
317 |
area.img = appDocData.imgSrc[round(area.y+1):round(area.y+area.height), round(area.x+1):round(area.x+area.width)]
|
|
318 |
cv2.imwrite(os.path.join(project.getTempPath(), "RECT_" + os.path.basename(path)), appDocData.imgSrc)
|
|
313 |
## Remove Noise
|
|
314 |
kernel1 = np.ones((2, 2), np.uint8)
|
|
315 |
appDocData.imgSrc = cv2.dilate(appDocData.imgSrc, kernel1) |
|
316 |
appDocData.imgSrc = cv2.erode(appDocData.imgSrc, kernel1)
|
|
317 |
|
|
318 |
removedSymbolImgPath = os.path.join(project.getTempPath(), os.path.basename(path))
|
|
319 |
cv2.imwrite(removedSymbolImgPath, appDocData.imgSrc)
|
|
319 | 320 |
|
320 |
listWidget.addItem("Recognized symbol count : " + str(len(searchedSymbolList))) |
|
321 |
area = AppDocData.instance().getArea('Drawing') |
|
322 |
if area is not None: |
|
323 |
area.img = appDocData.imgSrc[round(area.y+1):round(area.y+area.height), round(area.x+1):round(area.x+area.width)] |
|
324 |
cv2.imwrite(os.path.join(project.getTempPath(), "RECT_" + os.path.basename(path)), appDocData.imgSrc) |
|
325 |
|
|
326 |
listWidget.addItem("Recognized symbol count : " + str(len(searchedSymbolList))) |
|
321 | 327 |
|
322 |
# get difference between original and recognized image
|
|
323 |
foundFilePath = os.path.join(project.getTempPath(), "FOUND_" + os.path.basename(path))
|
|
324 |
Worker.getDifference(path, foundFilePath)
|
|
325 |
# up to here
|
|
328 |
# get difference between original and recognized image |
|
329 |
foundFilePath = os.path.join(project.getTempPath(), "FOUND_" + os.path.basename(path)) |
|
330 |
Worker.getDifference(path, foundFilePath) |
|
331 |
# up to here |
|
326 | 332 |
|
327 |
## block until drawing recognized objects
|
|
328 |
loop = QEventLoop()
|
|
329 |
listWidget.addItem('인식 정보 생성 중...')
|
|
330 |
worker.displayTitle.emit('인식 정보 생성 중...')
|
|
331 |
drawDetectedItems.emit(searchedSymbolList, textInfoList, otherTextInfoList if otherTextInfoList is not None else [], loop)
|
|
332 |
loop.exec_()
|
|
333 |
## up to here
|
|
333 |
## block until drawing recognized objects |
|
334 |
loop = QEventLoop() |
|
335 |
listWidget.addItem('인식 정보 생성 중...') |
|
336 |
worker.displayTitle.emit('인식 정보 생성 중...') |
|
337 |
drawDetectedItems.emit(searchedSymbolList, textInfoList, otherTextInfoList if otherTextInfoList is not None else [], loop) |
|
338 |
loop.exec_() |
|
339 |
## up to here |
|
334 | 340 |
except Exception as ex: |
335 | 341 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
336 | 342 |
worker.displayLog.emit(MessageType.Error, message) |
... | ... | |
1267 | 1273 |
self.isAccepted = True |
1268 | 1274 |
QDialog.accept(self) |
1269 | 1275 |
|
1270 |
''' |
|
1271 |
@brief start recognization |
|
1272 |
@author humkyung |
|
1273 |
''' |
|
1274 | 1276 |
def recognizeButtonClicked(self, event): |
1275 |
if self.ui.symbolTextCheckBox.isChecked() or self.ui.lineCheckBox.isChecked(): |
|
1277 |
""" |
|
1278 |
@brief start recognization |
|
1279 |
@author humkyung |
|
1280 |
@history humkyung 2018.10.05 clear imgSrc before recognizing |
|
1281 |
""" |
|
1282 |
if self.ui.checkBoxSymbol.isChecked() or self.ui.checkBoxText.isChecked() or self.ui.lineCheckBox.isChecked(): |
|
1283 |
appDocData = AppDocData.instance() |
|
1284 |
appDocData.imgSrc = None |
|
1285 |
|
|
1276 | 1286 |
self.ui.recognizeButton.setEnabled(False) |
1277 | 1287 |
self.ui.buttonBox.setEnabled(False) |
1278 | 1288 |
self.ui.progressBar.setValue(0) |
... | ... | |
1303 | 1313 |
def displayTitle(self, title): |
1304 | 1314 |
self.ui.labelTitle.setText(title) |
1305 | 1315 |
|
1306 |
''' |
|
1316 |
def startThread(self): |
|
1317 |
""" |
|
1307 | 1318 |
@brief start thread |
1308 | 1319 |
@author humkyung |
1309 | 1320 |
@date 2018.04.?? |
... | ... | |
1311 | 1322 |
2018.05.28 Jeongwoo Add connects (self.loadRecognitionResult, recognizeLine) |
1312 | 1323 |
2018.05.30 Jeongwoo Change signal name (drawDetectedItems) |
1313 | 1324 |
humkyung 2018.06.08 connect signal to self.updateProgress |
1314 |
''' |
|
1315 |
def startThread(self): |
|
1325 |
""" |
|
1316 | 1326 |
import timeit |
1317 | 1327 |
from PyQt5 import QtWidgets |
1318 | 1328 |
from App import App |
... | ... | |
1324 | 1334 |
self.obj.path = self.path |
1325 | 1335 |
self.obj.listWidget = self.ui.listWidget |
1326 | 1336 |
self.obj.graphicsView = self.graphicsView |
1327 |
self.obj.isSymbolTextChecked = self.ui.symbolTextCheckBox.isChecked() |
|
1337 |
self.obj.isSymbolChecked = self.ui.checkBoxSymbol.isChecked() |
|
1338 |
self.obj.isTextChecked = self.ui.checkBoxText.isChecked() |
|
1328 | 1339 |
self.obj.isLineChecked = self.ui.lineCheckBox.isChecked() |
1329 | 1340 |
self.thread = QThread() # no parent! |
1330 | 1341 |
|
DTI_PID/DTI_PID/Recognition_UI.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
|
3 |
# Form implementation generated from reading ui file '.\ui\dlgRecognition.ui'
|
|
3 |
# Form implementation generated from reading ui file '.\UI\Recognition.ui'
|
|
4 | 4 |
# |
5 |
# Created by: PyQt5 UI code generator 5.10.1
|
|
5 |
# Created by: PyQt5 UI code generator 5.11.3
|
|
6 | 6 |
# |
7 | 7 |
# WARNING! All changes made in this file will be lost! |
8 | 8 |
|
... | ... | |
25 | 25 |
self.gridLayout_2.setObjectName("gridLayout_2") |
26 | 26 |
self.lineCheckBox = QtWidgets.QCheckBox(Recognition) |
27 | 27 |
self.lineCheckBox.setMaximumSize(QtCore.QSize(47, 16777215)) |
28 |
self.lineCheckBox.setChecked(True)
|
|
28 |
self.lineCheckBox.setChecked(False)
|
|
29 | 29 |
self.lineCheckBox.setObjectName("lineCheckBox") |
30 |
self.gridLayout_2.addWidget(self.lineCheckBox, 0, 1, 1, 1)
|
|
31 |
self.symbolTextCheckBox = QtWidgets.QCheckBox(Recognition)
|
|
32 |
self.symbolTextCheckBox.setMaximumSize(QtCore.QSize(103, 16777215))
|
|
33 |
self.symbolTextCheckBox.setChecked(True)
|
|
34 |
self.symbolTextCheckBox.setObjectName("symbolTextCheckBox")
|
|
35 |
self.gridLayout_2.addWidget(self.symbolTextCheckBox, 0, 0, 1, 1)
|
|
30 |
self.gridLayout_2.addWidget(self.lineCheckBox, 0, 2, 1, 1)
|
|
31 |
self.checkBoxSymbol = QtWidgets.QCheckBox(Recognition)
|
|
32 |
self.checkBoxSymbol.setMaximumSize(QtCore.QSize(103, 16777215))
|
|
33 |
self.checkBoxSymbol.setChecked(True)
|
|
34 |
self.checkBoxSymbol.setObjectName("checkBoxSymbol")
|
|
35 |
self.gridLayout_2.addWidget(self.checkBoxSymbol, 0, 0, 1, 1)
|
|
36 | 36 |
self.recognizeButton = QtWidgets.QPushButton(Recognition) |
37 | 37 |
self.recognizeButton.setObjectName("recognizeButton") |
38 |
self.gridLayout_2.addWidget(self.recognizeButton, 0, 4, 1, 1, QtCore.Qt.AlignRight)
|
|
38 |
self.gridLayout_2.addWidget(self.recognizeButton, 0, 5, 1, 1, QtCore.Qt.AlignRight)
|
|
39 | 39 |
self.labelTitle = QtWidgets.QLabel(Recognition) |
40 | 40 |
palette = QtGui.QPalette() |
41 | 41 |
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255)) |
... | ... | |
55 | 55 |
self.labelTitle.setText("") |
56 | 56 |
self.labelTitle.setAlignment(QtCore.Qt.AlignCenter) |
57 | 57 |
self.labelTitle.setObjectName("labelTitle") |
58 |
self.gridLayout_2.addWidget(self.labelTitle, 0, 3, 1, 1)
|
|
58 |
self.gridLayout_2.addWidget(self.labelTitle, 0, 4, 1, 1)
|
|
59 | 59 |
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) |
60 |
self.gridLayout_2.addItem(spacerItem, 0, 2, 1, 1) |
|
60 |
self.gridLayout_2.addItem(spacerItem, 0, 3, 1, 1) |
|
61 |
self.checkBoxText = QtWidgets.QCheckBox(Recognition) |
|
62 |
self.checkBoxText.setMaximumSize(QtCore.QSize(103, 16777215)) |
|
63 |
self.checkBoxText.setChecked(True) |
|
64 |
self.checkBoxText.setObjectName("checkBoxText") |
|
65 |
self.gridLayout_2.addWidget(self.checkBoxText, 0, 1, 1, 1) |
|
61 | 66 |
self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1) |
62 | 67 |
self.horizontalLayout = QtWidgets.QHBoxLayout() |
63 | 68 |
self.horizontalLayout.setObjectName("horizontalLayout") |
... | ... | |
86 | 91 |
_translate = QtCore.QCoreApplication.translate |
87 | 92 |
Recognition.setWindowTitle(_translate("Recognition", "설계정보 인식")) |
88 | 93 |
self.lineCheckBox.setText(_translate("Recognition", "라인")) |
89 |
self.symbolTextCheckBox.setText(_translate("Recognition", "심볼 및 텍스트"))
|
|
94 |
self.checkBoxSymbol.setText(_translate("Recognition", "심볼"))
|
|
90 | 95 |
self.recognizeButton.setText(_translate("Recognition", "정보 인식")) |
96 |
self.checkBoxText.setText(_translate("Recognition", "텍스트")) |
|
91 | 97 |
|
92 | 98 |
|
93 | 99 |
if __name__ == "__main__": |
DTI_PID/DTI_PID/TextDetector.py | ||
---|---|---|
172 | 172 |
appDocData = AppDocData.instance() |
173 | 173 |
|
174 | 174 |
try: |
175 |
configs = appDocData.getConfigs('Text Recognition', 'Remove White Space') |
|
176 |
removeWhiteSpace = 'True' == configs[0].value if len(configs) == 1 else False |
|
177 |
configs = appDocData.getConfigs('Text Recognition', 'OldStr') |
|
178 |
oldStr = configs[0].value if len(configs) == 1 else '' |
|
179 |
configs = appDocData.getConfigs('Text Recognition', 'NewStr') |
|
180 |
newStr = configs[0].value if len(configs) == 1 else '' |
|
181 |
|
|
182 | 175 |
x = tInfo.getX() - round(offset[0]) |
183 | 176 |
y = tInfo.getY() - round(offset[1]) |
184 | 177 |
img = imgOCR[y:y+tInfo.getH(), x:x+tInfo.getW()] |
... | ... | |
197 | 190 |
for result in resultTextInfo: |
198 | 191 |
result.setX(result.getX() + round(offset[0])) |
199 | 192 |
result.setY(result.getY() + round(offset[1])) |
200 |
if removeWhiteSpace: result.setText(result.getText().replace(' ', '')) # remove white space - 2018.07.03 added by humkyung |
|
201 |
if oldStr != '': result.setText(result.getText().replace(oldStr, newStr)) # replace oldStr with newStr - 2018.07.03 added by humkyung |
|
202 | 193 |
if 'Instrumentation' == category: |
203 | 194 |
text = re.sub('[^a-zA-Z0-9]+', '', result.getText()) |
204 | 195 |
result.setText(text) |
DTI_PID/DTI_PID/UI/Recognition.ui | ||
---|---|---|
27 | 27 |
</item> |
28 | 28 |
<item row="0" column="0"> |
29 | 29 |
<layout class="QGridLayout" name="gridLayout_2"> |
30 |
<item row="0" column="1">
|
|
30 |
<item row="0" column="2">
|
|
31 | 31 |
<widget class="QCheckBox" name="lineCheckBox"> |
32 | 32 |
<property name="maximumSize"> |
33 | 33 |
<size> |
... | ... | |
39 | 39 |
<string>라인</string> |
40 | 40 |
</property> |
41 | 41 |
<property name="checked"> |
42 |
<bool>true</bool>
|
|
42 |
<bool>false</bool>
|
|
43 | 43 |
</property> |
44 | 44 |
</widget> |
45 | 45 |
</item> |
46 | 46 |
<item row="0" column="0"> |
47 |
<widget class="QCheckBox" name="symbolTextCheckBox">
|
|
47 |
<widget class="QCheckBox" name="checkBoxSymbol">
|
|
48 | 48 |
<property name="maximumSize"> |
49 | 49 |
<size> |
50 | 50 |
<width>103</width> |
... | ... | |
52 | 52 |
</size> |
53 | 53 |
</property> |
54 | 54 |
<property name="text"> |
55 |
<string>심볼 및 텍스트</string>
|
|
55 |
<string>심볼</string> |
|
56 | 56 |
</property> |
57 | 57 |
<property name="checked"> |
58 | 58 |
<bool>true</bool> |
59 | 59 |
</property> |
60 | 60 |
</widget> |
61 | 61 |
</item> |
62 |
<item row="0" column="4" alignment="Qt::AlignRight">
|
|
62 |
<item row="0" column="5" alignment="Qt::AlignRight">
|
|
63 | 63 |
<widget class="QPushButton" name="recognizeButton"> |
64 | 64 |
<property name="text"> |
65 | 65 |
<string>정보 인식</string> |
66 | 66 |
</property> |
67 | 67 |
</widget> |
68 | 68 |
</item> |
69 |
<item row="0" column="3">
|
|
69 |
<item row="0" column="4">
|
|
70 | 70 |
<widget class="QLabel" name="labelTitle"> |
71 | 71 |
<property name="palette"> |
72 | 72 |
<palette> |
... | ... | |
119 | 119 |
</property> |
120 | 120 |
</widget> |
121 | 121 |
</item> |
122 |
<item row="0" column="2">
|
|
122 |
<item row="0" column="3">
|
|
123 | 123 |
<spacer name="horizontalSpacer"> |
124 | 124 |
<property name="orientation"> |
125 | 125 |
<enum>Qt::Horizontal</enum> |
... | ... | |
132 | 132 |
</property> |
133 | 133 |
</spacer> |
134 | 134 |
</item> |
135 |
<item row="0" column="1"> |
|
136 |
<widget class="QCheckBox" name="checkBoxText"> |
|
137 |
<property name="maximumSize"> |
|
138 |
<size> |
|
139 |
<width>103</width> |
|
140 |
<height>16777215</height> |
|
141 |
</size> |
|
142 |
</property> |
|
143 |
<property name="text"> |
|
144 |
<string>텍스트</string> |
|
145 |
</property> |
|
146 |
<property name="checked"> |
|
147 |
<bool>true</bool> |
|
148 |
</property> |
|
149 |
</widget> |
|
150 |
</item> |
|
135 | 151 |
</layout> |
136 | 152 |
</item> |
137 | 153 |
<item row="4" column="0"> |
내보내기 Unified diff