개정판 000faa4d
Fit Image 기능 추가/TreeWidget,TableWidget,QSymbolEditor 연결
DTI_PID/DTI_PID/Commands/FitImageCommand.py | ||
---|---|---|
1 |
import os.path |
|
2 |
import AbstractCommand |
|
3 |
try: |
|
4 |
from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
|
5 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor, QColor |
|
6 |
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog |
|
7 |
except ImportError: |
|
8 |
try: |
|
9 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
|
10 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor, QColor |
|
11 |
except ImportError: |
|
12 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
|
13 |
import sys |
|
14 |
|
|
15 |
class FitImageCommand(AbstractCommand.AbstractCommand): |
|
16 |
WHITE_PIXEL = (255, 255, 255, 255) |
|
17 |
BLACK_PIXEL = (0, 0, 0, 255) |
|
18 |
|
|
19 |
def __init__(self, imageViewer): |
|
20 |
super(FitImageCommand, self).__init__(imageViewer) |
|
21 |
self.name = 'FitImage' |
|
22 |
self.imageViewer.setCursor(QCursor(Qt.CrossCursor)) |
|
23 |
|
|
24 |
boundingBox = self.getImageBoundingBox() |
|
25 |
croppedImage = self.imageViewer.image().copy(boundingBox) |
|
26 |
self.imageViewer.setImage(croppedImage) |
|
27 |
self.adjustX = boundingBox.left() |
|
28 |
self.adjustY = boundingBox.top() |
|
29 |
|
|
30 |
def getAdjust(self): |
|
31 |
return (self.adjustX, self.adjustY) |
|
32 |
|
|
33 |
def getImageBoundingBox(self): |
|
34 |
image = self.imageViewer.image() |
|
35 |
minX = sys.maxsize |
|
36 |
minY = sys.maxsize |
|
37 |
maxX = -1 |
|
38 |
maxY = -1 |
|
39 |
for xi in range(image.width()): |
|
40 |
for yi in range(image.height()): |
|
41 |
pixel = image.pixel(xi, yi) |
|
42 |
if QColor(pixel).getRgb() == self.BLACK_PIXEL: |
|
43 |
#if QColor(pixel).getRgb() != self.WHITE_PIXEL: |
|
44 |
if xi < minX: |
|
45 |
minX = xi |
|
46 |
if xi > maxX: |
|
47 |
maxX = xi |
|
48 |
if yi < minY: |
|
49 |
minY = yi |
|
50 |
if yi > maxY: |
|
51 |
maxY = yi |
|
52 |
return QRect(minX, minY, (maxX - minX) + 1, (maxY - minY) + 1) |
|
53 |
|
|
54 |
''' |
|
55 |
@brief DO NOTHING |
|
56 |
''' |
|
57 |
def execute(self, param): |
|
58 |
pass |
|
59 |
|
|
60 |
def undo(self): |
|
61 |
pass |
|
62 |
|
|
63 |
def redo(self): |
|
64 |
pass |
DTI_PID/DTI_PID/Commands/OriginalPointCommand.py | ||
---|---|---|
30 | 30 |
self.originalPointLineEdit.setText('') |
31 | 31 |
x = int(coords.split(",")[0]) |
32 | 32 |
y = int(coords.split(",")[1]) |
33 |
self.removeCircle(x, y)
|
|
33 |
OriginalPointCommand.removeCircle(self.imageViewer, x, y)
|
|
34 | 34 |
## Guideline |
35 | 35 |
self.showGuideline(self.initMinPoint) |
36 | 36 |
|
... | ... | |
75 | 75 |
def drawCircle(imageViewer, x, y): |
76 | 76 |
imageViewer.scene.addItem(imageViewer.scene.addEllipse(QRectF(int(x) - 0.5, int(y) - 0.5, 1, 1), QPen(QColor(255, 0, 0)), QBrush(QColor(255, 0, 0)))) |
77 | 77 |
|
78 |
def removeCircle(self, x, y): |
|
78 |
@staticmethod |
|
79 |
def removeCircle(imageViewer, x, y): |
|
79 | 80 |
scenePos = QPointF(x, y) |
80 |
item = self.imageViewer.scene.itemAt(QPointF(int(scenePos.x()), int(scenePos.y())), QTransform()) |
|
81 |
if item is not None and item.boundingRect() != QRectF(0, 0, self.imageWidth, self.imageHeight): |
|
82 |
self.imageViewer.scene.removeItem(item) |
|
81 |
imageWidth = imageViewer.image().width() |
|
82 |
imageHeight = imageViewer.image().height() |
|
83 |
item = imageViewer.scene.itemAt(QPointF(int(scenePos.x()), int(scenePos.y())), QTransform()) |
|
84 |
if item is not None and item.boundingRect() != QRectF(0, 0, imageWidth, imageHeight): |
|
85 |
imageViewer.scene.removeItem(item) |
|
83 | 86 |
|
84 | 87 |
def isOnImage(self, x, y): |
85 | 88 |
if (x >= 0 and x <= self.imageWidth) and (y >= 0 and y <= self.imageHeight): |
DTI_PID/DTI_PID/QDirTreeWidget.py | ||
---|---|---|
20 | 20 |
|
21 | 21 |
def __init__(self): |
22 | 22 |
QTreeWidget.__init__(self) |
23 |
self.project = AppDocData.instance().getCurrentProject() |
|
24 | 23 |
self.initDirTreeWidget() |
25 | 24 |
self.isDoubleClicked = False |
26 |
|
|
27 |
def initDirTreeWidget(self): |
|
28 | 25 |
self.itemDoubleClicked.connect(self.itemDoubleClickEvent) |
29 | 26 |
self.itemClicked.connect(self.itemClickEvent) |
30 |
if self.project is not None: |
|
27 |
|
|
28 |
def initDirTreeWidget(self): |
|
29 |
project = AppDocData.instance().getCurrentProject() |
|
30 |
if project is not None: |
|
31 | 31 |
self.clear() |
32 |
print("Project : " + self.project.getName())
|
|
33 |
projectPath = self.project.getPath().replace("\\", "/")
|
|
32 |
print("Project : " + project.getName()) |
|
33 |
projectPath = project.getPath().replace("\\", "/") |
|
34 | 34 |
self.makeChildDir(projectPath) |
35 | 35 |
self.loadDirectoryInfo(projectPath+"/image", self) |
36 | 36 |
|
... | ... | |
57 | 57 |
itemName = item.text(columnNo) |
58 | 58 |
print(itemName + " : Double Clicked") |
59 | 59 |
sym = self.getSymbolByItemName(item, columnNo) |
60 |
image = QImage(sym.getPath(), "PNG") |
|
61 |
symbolEditorDialog = QSymbolEditorDialog.QSymbolEditorDialog(self, image, self.project, sym) |
|
62 |
_ret = symbolEditorDialog.showDialog() |
|
63 |
self.initDirTreeWidget() |
|
60 |
if sym is not None: |
|
61 |
image = QImage(sym.getPath(), "PNG") |
|
62 |
print("after image") |
|
63 |
symbolEditorDialog = QSymbolEditorDialog.QSymbolEditorDialog(self, image, AppDocData.instance().getCurrentProject(), sym) |
|
64 |
_ret = symbolEditorDialog.showDialog() |
|
65 |
self.initDirTreeWidget() |
|
64 | 66 |
self.isDoubleClicked = False |
65 | 67 |
|
66 | 68 |
def itemClickEvent(self, item, columnNo): |
... | ... | |
80 | 82 |
while tmpItem.parent() is not None: |
81 | 83 |
path = tmpItem.parent().text(columnNo) + "/" + path |
82 | 84 |
tmpItem = tmpItem.parent() |
83 |
fullPath = self.project.getPath() + "/image/" + path
|
|
85 |
fullPath = AppDocData.instance().getCurrentProject().getPath() + "/image/" + path
|
|
84 | 86 |
|
85 | 87 |
sym = AppDocData.instance().getSymbolByQuery("path", fullPath) |
86 | 88 |
return sym |
DTI_PID/DTI_PID/QSymbolEditorDialog.py | ||
---|---|---|
15 | 15 |
|
16 | 16 |
|
17 | 17 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands') |
18 |
import CropCommand, HandCommand, ZoomCommand, PenCommand, EraserCommand, AreaEraserCommand, OriginalPointCommand, ConnectionPointCommand, AreaZoomCommand |
|
18 |
import CropCommand, HandCommand, ZoomCommand, PenCommand, EraserCommand, AreaEraserCommand, OriginalPointCommand, ConnectionPointCommand, AreaZoomCommand, FitImageCommand
|
|
19 | 19 |
|
20 | 20 |
|
21 | 21 |
class QSymbolEditorDialog(QDialog): |
... | ... | |
68 | 68 |
self.ui.eraserButton.clicked.connect(self.eraserToolClickEvent) |
69 | 69 |
self.ui.eraserSpinBox.valueChanged.connect(self.eraserWidthChangedEvent) |
70 | 70 |
self.ui.areaEraserButton.clicked.connect(self.areaEraserToolClickEvent) |
71 |
self.ui.fitImageButton.clicked.connect(self.fitImageToolClickEvent) |
|
71 | 72 |
self.ui.zoomButton.clicked.connect(self.zoomToolClickEvent) |
72 | 73 |
self.ui.areaZoomButton.clicked.connect(self.areaZoomToolClickEvent) |
73 | 74 |
self.ui.initZoomButton.clicked.connect(self.zoomInitToolClickEvent) |
... | ... | |
178 | 179 |
''' |
179 | 180 |
def showDialog(self): |
180 | 181 |
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) |
181 |
self.show() |
|
182 |
#self.show()
|
|
182 | 183 |
self.exec_() |
183 | 184 |
return self.isAccepted |
184 | 185 |
|
... | ... | |
435 | 436 |
def areaEraserToolClickEvent(self, event): |
436 | 437 |
print("area eraser") |
437 | 438 |
self.ui.imageView.command = AreaEraserCommand.AreaEraserCommand(self.ui.imageView) |
439 |
|
|
440 |
''' |
|
441 |
@brief Fit Image Tool Button Clicked |
|
442 |
''' |
|
443 |
def fitImageToolClickEvent(self, event): |
|
444 |
print("Fit Image") |
|
445 |
self.ui.imageView.command = FitImageCommand.FitImageCommand(self.ui.imageView) |
|
446 |
adjustX, adjustY = self.ui.imageView.command.getAdjust() |
|
447 |
self.adjustOriginalPoint(adjustX, adjustY) |
|
448 |
self.adjustConnectionPoint(adjustX, adjustY) |
|
438 | 449 |
|
439 | 450 |
''' |
440 | 451 |
@brief Guideline Check State Changed |
... | ... | |
491 | 502 |
def addConnectionPoint(self, event): |
492 | 503 |
print("addConnectionPoint") |
493 | 504 |
self.ui.imageView.command = ConnectionPointCommand.ConnectionPointCommand(self.ui.imageView, self.ui.connectionPointLineEdit, self.ui.connectionPointList) |
505 |
|
|
506 |
def adjustOriginalPoint(self, adjustX, adjustY): |
|
507 |
originalPoint = self.ui.originalPointLineEdit.text() |
|
508 |
if originalPoint and self.ui.imageView.isOriginalPointSelected: |
|
509 |
x = int(originalPoint.split(",")[0]) |
|
510 |
y = int(originalPoint.split(",")[1]) |
|
511 |
OriginalPointCommand.OriginalPointCommand.removeCircle(self.ui.imageView, x, y) |
|
512 |
x = x - adjustX |
|
513 |
y = y - adjustY |
|
514 |
self.ui.originalPointLineEdit.setText(str(x)+","+str(y)) |
|
515 |
OriginalPointCommand.OriginalPointCommand.drawCircle(self.ui.imageView, x, y) |
|
516 |
|
|
517 |
def adjustConnectionPoint(self, adjustX, adjustY): |
|
518 |
itemCount = self.ui.connectionPointList.count() |
|
519 |
for index in range(itemCount): |
|
520 |
item = self.ui.connectionPointList.item(index) |
|
521 |
text = item.text() |
|
522 |
x = int(text.split(",")[0]) |
|
523 |
y = int(text.split(",")[1]) |
|
524 |
self.removeConnectionPointCircle(QtCore.QPointF(x, y)) |
|
525 |
x = x - adjustX |
|
526 |
y = y - adjustY |
|
527 |
item.setText(str(x)+","+str(y)) |
|
528 |
ConnectionPointCommand.ConnectionPointCommand.drawCircle(self.ui.imageView, x, y) |
|
494 | 529 |
|
495 | 530 |
''' |
496 | 531 |
@brief Validation Check |
DTI_PID/DTI_PID/UI/SymbolEditor.ui | ||
---|---|---|
471 | 471 |
<rect> |
472 | 472 |
<x>0</x> |
473 | 473 |
<y>0</y> |
474 |
<width>871</width>
|
|
474 |
<width>919</width>
|
|
475 | 475 |
<height>41</height> |
476 | 476 |
</rect> |
477 | 477 |
</property> |
... | ... | |
528 | 528 |
</widget> |
529 | 529 |
</item> |
530 | 530 |
<item> |
531 |
<widget class="QPushButton" name="fitImageButton"> |
|
532 |
<property name="text"> |
|
533 |
<string>Fit Image</string> |
|
534 |
</property> |
|
535 |
</widget> |
|
536 |
</item> |
|
537 |
<item> |
|
531 | 538 |
<widget class="QPushButton" name="areaEraserButton"> |
532 | 539 |
<property name="text"> |
533 | 540 |
<string>Area Eraser</string> |
... | ... | |
590 | 597 |
</widget> |
591 | 598 |
</widget> |
592 | 599 |
<resources/> |
593 |
<connections/> |
|
600 |
<connections> |
|
601 |
<connection> |
|
602 |
<sender>buttonBox</sender> |
|
603 |
<signal>accepted()</signal> |
|
604 |
<receiver>Dialog</receiver> |
|
605 |
<slot>accept()</slot> |
|
606 |
<hints> |
|
607 |
<hint type="sourcelabel"> |
|
608 |
<x>1081</x> |
|
609 |
<y>699</y> |
|
610 |
</hint> |
|
611 |
<hint type="destinationlabel"> |
|
612 |
<x>639</x> |
|
613 |
<y>359</y> |
|
614 |
</hint> |
|
615 |
</hints> |
|
616 |
</connection> |
|
617 |
<connection> |
|
618 |
<sender>buttonBox</sender> |
|
619 |
<signal>rejected()</signal> |
|
620 |
<receiver>Dialog</receiver> |
|
621 |
<slot>reject()</slot> |
|
622 |
<hints> |
|
623 |
<hint type="sourcelabel"> |
|
624 |
<x>1081</x> |
|
625 |
<y>699</y> |
|
626 |
</hint> |
|
627 |
<hint type="destinationlabel"> |
|
628 |
<x>639</x> |
|
629 |
<y>359</y> |
|
630 |
</hint> |
|
631 |
</hints> |
|
632 |
</connection> |
|
633 |
</connections> |
|
594 | 634 |
</ui> |
DTI_PID/DTI_PID/UI_SymbolEditor.py | ||
---|---|---|
243 | 243 |
self.toolWidget.setMaximumSize(QtCore.QSize(869, 40)) |
244 | 244 |
self.toolWidget.setObjectName("toolWidget") |
245 | 245 |
self.horizontalLayoutWidget_3 = QtWidgets.QWidget(self.toolWidget) |
246 |
self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(0, 0, 871, 41))
|
|
246 |
self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(0, 0, 919, 41))
|
|
247 | 247 |
self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3") |
248 | 248 |
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3) |
249 | 249 |
self.horizontalLayout_3.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) |
... | ... | |
271 | 271 |
self.eraserSpinBox.setMaximum(5) |
272 | 272 |
self.eraserSpinBox.setObjectName("eraserSpinBox") |
273 | 273 |
self.horizontalLayout_3.addWidget(self.eraserSpinBox) |
274 |
self.fitImageButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_3) |
|
275 |
self.fitImageButton.setObjectName("fitImageButton") |
|
276 |
self.horizontalLayout_3.addWidget(self.fitImageButton) |
|
274 | 277 |
self.areaEraserButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_3) |
275 | 278 |
self.areaEraserButton.setObjectName("areaEraserButton") |
276 | 279 |
self.horizontalLayout_3.addWidget(self.areaEraserButton) |
... | ... | |
326 | 329 |
self.cropButton.setText(_translate("Dialog", "Crop")) |
327 | 330 |
self.penButton.setText(_translate("Dialog", "Pen")) |
328 | 331 |
self.eraserButton.setText(_translate("Dialog", "Eraser")) |
332 |
self.fitImageButton.setText(_translate("Dialog", "Fit Image")) |
|
329 | 333 |
self.areaEraserButton.setText(_translate("Dialog", "Area Eraser")) |
330 | 334 |
self.zoomButton.setText(_translate("Dialog", "Zoom")) |
331 | 335 |
self.areaZoomButton.setText(_translate("Dialog", "Area Zoom")) |
내보내기 Unified diff