Skip to content

Commit

Permalink
Addressed Crosshair and MacOS support issues
Browse files Browse the repository at this point in the history
Issue with PySide 6.5.1 and MacOS 10.X, downgraded PySide6 dependency to 6.4.3 for extended MacOS support.

Updated features:
- Added Morphometrix version # to crash log
- Added option to change reticle shape from crosshair to dot
- Added opacity control for width reticles
- Fixed issue with exit button not exiting application
- Added value checking for input boxes
  • Loading branch information
ZappyMan committed Dec 23, 2023
1 parent 8fa069a commit 4308b5d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -845,3 +845,4 @@ morphometrix/__pycache__/graphicsview.cpython-310.pyc
morphometrix/__pycache__/graphicsview.cpython-310.pyc
morphometrix/__pycache__/graphicsview.cpython-310.pyc
*.pyc
*.pyc
52 changes: 39 additions & 13 deletions morphometrix/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
from graphicsview import imwin, resource_path

from PySide6 import QtGui, QtCore
from PySide6.QtWidgets import QSlider ,QColorDialog ,QComboBox, QMainWindow, QApplication, QWidget, QToolBar, QPushButton, QLabel, QLineEdit, QPlainTextEdit, QGridLayout, QFileDialog, QMessageBox, QInputDialog, QDockWidget, QSizePolicy, QRadioButton
from PySide6.QtGui import QShortcut, QIcon
from PySide6.QtWidgets import QTabWidget, QSlider ,QColorDialog ,QComboBox, QMainWindow, QApplication, QWidget, QToolBar, QPushButton, QLabel, QLineEdit, QPlainTextEdit, QGridLayout, QFileDialog, QMessageBox, QInputDialog, QDockWidget, QSizePolicy, QRadioButton
from PySide6.QtGui import QShortcut, QIcon, QIntValidator, QDoubleValidator
from PySide6.QtCore import Qt

# TODO: Update before every release
VERSION = "2.2.0"

# ------------------------------
# MorphoMetrix - Developed By:
# Walter Torres
Expand All @@ -19,7 +22,7 @@
# ------------------------------
# Packages (Used Universal2 Python install with universal2 Wheels for MacOS):
# Python 3.10.8
# PySide6 6.5.1
# PySide6 6.4.3
# Numpy 1.21.6
# Scipy 1.9.1
# ------------------------------
Expand All @@ -43,23 +46,28 @@ def __init__(self, iw):

self.label_id = QLabel("Image ID")
self.id = QLineEdit()
self.id.setValidator(QIntValidator())
self.id.setText('0000')

#Define custom attributes for pixel -> SI conversion
self.label_foc = QLabel("Focal Length (mm):")
self.focal = QLineEdit()
self.focal.setValidator(QDoubleValidator())
self.focal.setText('25')

self.label_alt = QLabel("Altitude (m):")
self.altitude = QLineEdit()
self.altitude.setValidator(QDoubleValidator())
self.altitude.setText('50')

self.label_pd = QLabel("Pixel Dimension (mm/pixel)")
self.pixeldim = QLineEdit()
self.pixeldim.setValidator(QDoubleValidator())
self.pixeldim.setText('0.0045')

self.label_widths = QLabel("# Width Segments:")
self.numwidths = QLineEdit()
self.numwidths.setValidator(QIntValidator())
self.numwidths.setText('10')

self.label_side = QLabel("Mirror Side:")
Expand All @@ -72,6 +80,16 @@ def __init__(self, iw):
self.scale_slider.setValue(10)
self.scale_slider.valueChanged.connect(self.slider_changed)

self.label_opacity = QLabel("Crosshair Opacity")
self.opacity_slider = QSlider(orientation=Qt.Orientation.Horizontal)
self.opacity_slider.setMaximum(10)
self.opacity_slider.setValue(10)
self.opacity_slider.valueChanged.connect(self.slider_changed)

self.label_widthtype = QLabel("Crosshair Type:")
self.width_tabs = QComboBox()
self.width_tabs.addItems(["Crosshair", "Dot"])

self.label_not = QLabel("Notes:")
self.notes = QPlainTextEdit()

Expand Down Expand Up @@ -101,12 +119,16 @@ def __init__(self, iw):
self.grid.addWidget(self.side_bias,6,1)
self.grid.addWidget(self.label_scale,7,0)
self.grid.addWidget(self.scale_slider,7,1)
self.grid.addWidget(self.label_not, 8, 0)
self.grid.addWidget(self.notes, 8, 1)
self.grid.addWidget(self.label_color,9,0)
self.grid.addWidget(self.button_color,9,1)
self.grid.addWidget(self.manual, 10, 3)
self.grid.addWidget(self.exit, 11, 3)
self.grid.addWidget(self.label_opacity,8,0)
self.grid.addWidget(self.opacity_slider,8,1)
self.grid.addWidget(self.label_widthtype,9,0)
self.grid.addWidget(self.width_tabs,9,1)
self.grid.addWidget(self.label_not, 10, 0)
self.grid.addWidget(self.notes, 10, 1)
self.grid.addWidget(self.label_color,11,0)
self.grid.addWidget(self.button_color,11,1)
self.grid.addWidget(self.manual, 12, 1)
self.grid.addWidget(self.exit, 13, 1)
self.setLayout(self.grid)

# Function used by color picker button
Expand All @@ -120,14 +142,17 @@ def color_changed(self):
# Passed new size to imwin function "slider_moved"
def slider_changed(self):
self.scale_slider.value() # Value grab lags behind actually value?
self.iw.slider_moved(self.scale_slider.value())
self.opacity_slider.value()
self.iw.slider_moved(self.scale_slider.value(),self.opacity_slider.value())


# Called when user clicks "Exit" button
def close_application(self):
choice = QMessageBox.question(self, 'exit', "Exit program?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
if choice == QMessageBox.StandardButton.Yes:
self.parent().deleteLater()
self.parent().close()
# self.parent().deleteLater()
# self.parent().close()
exit()

#references:
#https://stackoverflow.com/questions/26901540/arc-in-qgraphicsscene/26903599#26903599
Expand Down Expand Up @@ -381,6 +406,7 @@ def except_hook(exc_type, exc_value, exc_tb):
file.write("Python Implementation: " + platform.python_implementation() + '\n')
file.write("Release: " + platform.release() + '\n')
file.write("Version: " + platform.version() + '\n')
file.write("MorphoMetrix Version: " + VERSION + '\n')
file.write("Machine: " + platform.machine() + '\n')
file.write("Processor: " + platform.processor() + '\n' + '\n')
file.write(tb)
Expand Down
Binary file added morphometrix/dot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 26 additions & 10 deletions morphometrix/graphicsview.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ def __init__(self, parent=None):

self.picked_color = QtGui.QColor("red") # Default width ellipse color
self.slider_pos = 10 # Used by Ellipse Class
self.opacity_pos = 10 # Used by Ellipse Class
self.numwidths = None # User defined for width measurements
self.measurement_stack = [] # Initialize Empty Stack (FIFO)
self.measuring_state = None # Current measuring state
self.pixmap = None # Background image
self.crosshair_shape = "Crosshair"

self.setMouseTracking(True)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
Expand Down Expand Up @@ -105,7 +107,7 @@ def draw_scene(self):
case consts.LINEITEM:
self.scene.addItem(QGraphicsLineItem(item["parms"]))
case consts.ELLIPSEITEM:
item["parms"].update_scale(self.slider_pos)
item["parms"].update_crosshair(self.slider_pos, self.opacity_pos)
self.scene.addItem(item["parms"])
case consts.PATHITEM:
self.scene.addPath(item["parms"])
Expand Down Expand Up @@ -157,8 +159,9 @@ def update_application(self):

# Changes size of ellipses drawn on screen
# Called from MainWindow
def slider_moved(self, value):
self.slider_pos = value
def slider_moved(self, width_value, opactity_value):
self.slider_pos = width_value
self.opacity_pos = opactity_value
self.draw_scene()

# Activated every key press
Expand Down Expand Up @@ -456,7 +459,7 @@ def measure_widths(self):
"type": consts.FONTITEM
})
width_measurement.append_object({ # Append Ellipse
"parms": MovingEllipse(self, start, end, self.slider_pos, l%2),
"parms": MovingEllipse(self, start, end, self.slider_pos, l%2, self.parent().subWin.width_tabs.currentText()),
"type": consts.ELLIPSEITEM
})
width_measurement.append_object({ # Append Line
Expand Down Expand Up @@ -524,13 +527,20 @@ def resource_path(relative_path):
# Ellipse is bound to parent line
# Input: Point P1 (QPointF), Point P2 (QPointF)
class MovingEllipse(QGraphicsPixmapItem):
def __init__(self, parent,lp1, lp2, scale, side):
def __init__(self, parent,lp1, lp2, scale, side, shape_type):
# LP2 is always border point (PyQt6.QtCore.QPointF(1030.9353133069922, 0.0))
super(MovingEllipse,self).__init__()

scaledSize = int(parent.scene.height()/80) + (scale*10)
Image = QPixmap(resource_path("crosshair.png")).scaled(scaledSize,scaledSize)
scaledSize = 10 + (scale*10)
self.shape_key = shape_type
match self.shape_key:
case "Crosshair": # Save user selected shape type
Image = QPixmap(resource_path("crosshair.png")).scaled(scaledSize,scaledSize)
case "Dot":
Image = QPixmap(resource_path("dot.png")).scaled(scaledSize,scaledSize)

self.color = parent.picked_color
self.setOpacity(parent.opacity_pos)
self.Pixmap = QPixmap(Image.size())
self.Pixmap.fill(self.color)
self.Pixmap.setMask(Image.createMaskFromColor(Qt.GlobalColor.transparent))
Expand Down Expand Up @@ -559,15 +569,21 @@ def __init__(self, parent,lp1, lp2, scale, side):
self.setAcceptHoverEvents(True)
self.drag = False

def update_scale(self, scale):
scaledSize = int(self.parent.scene.height()/60) + (scale*10)
Image = QPixmap(resource_path("crosshair.png")).scaled(scaledSize,scaledSize)
def update_crosshair(self, scale, opacity):
# scaledSize = int(self.parent.scene.height()/60) + (scale*10) # OLD WAY, just set to 50 pixel minimum for those hardcore low res users
scaledSize = 10 + (scale*10)
match self.shape_key:
case "Crosshair": # Save user selected shape type
Image = QPixmap(resource_path("crosshair.png")).scaled(scaledSize,scaledSize)
case "Dot":
Image = QPixmap(resource_path("dot.png")).scaled(scaledSize,scaledSize)
self.Pixmap = QPixmap(Image.size())
self.Pixmap.fill(self.color)
self.Pixmap.setMask(Image.createMaskFromColor(Qt.GlobalColor.transparent))

self.setPixmap(self.Pixmap)
self.setOffset(QtCore.QPointF(-scaledSize/2,-scaledSize/2)) # Set offset to center of image
self.setOpacity(opacity/10)

def assignPoints(self, slope, lp1, lp2):
# Set Points depending on their path slope
Expand Down
2 changes: 1 addition & 1 deletion morphometrix/universal_mac.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ a = Analysis(
['__main__.py'],
pathex=[],
binaries=[],
datas=[('crosshair.png', '.'),('icon.png', '.')],
datas=[('crosshair.png', '.'),('icon.png', '.'),('dot.png', '.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
Expand Down
2 changes: 1 addition & 1 deletion morphometrix/windows.spec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ a = Analysis(
['__main__.py'],
pathex=[],
binaries=[],
datas=[('crosshair.png', '.'),('icon.png', '.')],
datas=[('crosshair.png', '.'),('icon.png', '.'),('dot.png', '.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
Expand Down

0 comments on commit 4308b5d

Please sign in to comment.