有没有办法防止矩形 pyqtgraph ROI 不左右移动?
Is there a way to prevent a rectangular pyqtgraph ROI to not move left-right?
我从我正在使用 pyqtgraph ROI 处理的部分代码中获得了这个片段。我还设置了投资回报率不能跨越所有方面的界限。当我移动任一垂直刻度手柄时,如果在其内部单击,它会为 ROI 提供左右移动的机会。有没有办法防止这种情况发生?我只希望它上下移动。这有点像根据当前的 X 开始位置和 X 停止位置在原始边界内设置另一个边界到 ROI。
我尝试使用信号修改 ROI class 中的 self.maxBound 变量,但它变得混乱,并且 ROI 一直忽略右边界。
任何帮助将不胜感激
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QGridLayout,
QWidget)
import pyqtgraph as pg
import sys
import numpy as np
from PyQt5.QtCore import QRectF, QRect
class TestROI(QMainWindow):
imageWidth = 1000
imageHardLimitTop = 1048
imageHardLimitBottom = 2047
shallowestPixel = 1400
deepestPixel = 1699
ROITopBottomMargin = 20
shaderDarkness = 185
shaderColor = (0, 0, 50, shaderDarkness)
imageHardLimitDepth = imageHardLimitBottom - imageHardLimitTop + 1
def __init__(self):
super(TestROI, self).__init__()
self.mainWidget = QWidget()
self.imagePlotCanvas = pg.GraphicsLayoutWidget()
self.graphGridLayout = QGridLayout(self.mainWidget)
self.graphGridLayout.addWidget(self.imagePlotCanvas)
self.setCentralWidget(self.mainWidget)
self.showMaximized()
# Place for 2D images:
self.plotArea = self.imagePlotCanvas.addPlot()
self.plotArea.setRange(
QRect(0, self.imageHardLimitTop, self.imageWidth, self.imageHardLimitDepth))
self.plotArea.setLimits(xMin=-1000, xMax=2000)
self.plotArea.setAspectLocked(True)
self.plotArea.invertY(b=True)
self.plotArea.showGrid(x=True, y=True, alpha=1.0)
self.plotArea.showButtons()
self.twoDImageROI = pg.ROI(pos=[0, self.shallowestPixel],
size=[
self.imageWidth, self.deepestPixel - self.shallowestPixel + 1],
removable=False,
maxBounds=QRectF(-1, self.imageHardLimitTop-1,
self.imageWidth + 2, self.imageHardLimitDepth+1),
scaleSnap=False, translateSnap=False)
self.twoDImageROI.setZValue(20)
self.shadedTopRegion = pg.LinearRegionItem(
[self.imageHardLimitTop, self.shallowestPixel], orientation=pg.LinearRegionItem.Horizontal, movable=False)
self.shadedTopRegion.setBrush(color=self.shaderColor)
self.shadedTopRegion.setZValue(10)
self.plotArea.addItem(self.shadedTopRegion)
self.shadedBottomRegion = pg.LinearRegionItem(
[self.deepestPixel + 1, self.imageHardLimitBottom+1], orientation=pg.LinearRegionItem.Horizontal, movable=False)
self.shadedBottomRegion.setBrush(color=self.shaderColor)
self.shadedBottomRegion.setZValue(10)
self.plotArea.addItem(self.shadedBottomRegion)
# self.twoDImageROI.setAcceptedMouseButtons(Qt.LeftButton)
self.twoDImageROI.sigRegionChanged.connect(self.imageROIChanged)
# Shaded Region on the left and right to cover up the above two vertical lines when out of image bound.
self.shadedLeftRegion = pg.LinearRegionItem(
[-1000, 0], orientation=pg.LinearRegionItem.Vertical, movable=False)
self.shadedLeftRegion.setBrush(color=(0, 0, 0))
self.shadedLeftRegion.setZValue(20)
self.plotArea.addItem(self.shadedLeftRegion)
self.shadedRightRegion = pg.LinearRegionItem(
[1000, 2000], orientation=pg.LinearRegionItem.Vertical, movable=False)
self.shadedRightRegion.setBrush(color=(0, 0, 0))
self.shadedRightRegion.setZValue(20)
self.plotArea.addItem(self.shadedRightRegion)
self.twoDImageROI.addScaleHandle([0.5, 0.0], [0.5, 1.0], index=0)
self.twoDImageROI.addScaleHandle([0.5, 1.0], [0.5, 0.0], index=1)
self.twoDImageROI.addScaleHandle([1.0, 0.5], [0.5, 0.5])
self.twoDImageROI.addScaleHandle([0.0, 0.5], [0.5, 0.5])
self.twoDOCMImage = pg.ImageItem(border='c')
self.twoDOCMImage.setParentItem(self.plotArea)
self.plotArea.addItem(self.twoDOCMImage)
self.plotArea.addItem(self.twoDImageROI)
zeroImage = np.zeros(self.imageWidth * self.imageHardLimitDepth)\
.reshape((self.imageWidth, self.imageHardLimitDepth))
self.twoDOCMImage.setImage(zeroImage)
startingRect = QRect(0, self.imageHardLimitTop,
self.imageWidth, self.imageHardLimitDepth)
self.twoDOCMImage.setRect(startingRect)
def imageROIChanged(self):
x, top = self.twoDImageROI.pos()
top = int(round(top, 0))
w, h = self.twoDImageROI.size()
h = int(round(h, 0))
bot = top + h - 1
self.shallowestPixel = top
self.deepestPixel = bot
self.updateLinearRegion()
def updateLinearRegion(self):
x, top = self.twoDImageROI.pos()
top = int(round(top, 0))
w, h = self.twoDImageROI.size()
h = int(round(h, 0))
bot = top + h - 1
self.shadedTopRegion.setRegion([self.imageHardLimitTop, top])
self.shadedBottomRegion.setRegion([bot, self.imageHardLimitBottom+1])
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = TestROI()
main_window.show()
sys.exit(app.exec_())
我相信您所说的问题是在上下移动 ROI 时从左到右的 1px 摆动。这种效果是由于将实际 ROI 位置转换为绘制 X、Y 值。总会有四舍五入,因此投资回报率总是会左右摆动。
为防止这种情况,您可以手动设置您的投资回报率的常量 x 位置。为此,您必须覆盖 ROI class.
的 setPos
这是投资回报率示例 class,您可以使用:
class ConstantXROI(ROI):
constant_x = 0
def setPos(self, pos, y=None, update=True, finish=True):
pos.setX(self.constant_x)
super().setPos(pos, y=y, update=update, finish=finish)
然后在您的代码中,只需使用:
self.twoDImageROI = ConstantXROI(...)
我从我正在使用 pyqtgraph ROI 处理的部分代码中获得了这个片段。我还设置了投资回报率不能跨越所有方面的界限。当我移动任一垂直刻度手柄时,如果在其内部单击,它会为 ROI 提供左右移动的机会。有没有办法防止这种情况发生?我只希望它上下移动。这有点像根据当前的 X 开始位置和 X 停止位置在原始边界内设置另一个边界到 ROI。
我尝试使用信号修改 ROI class 中的 self.maxBound 变量,但它变得混乱,并且 ROI 一直忽略右边界。
任何帮助将不胜感激
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QGridLayout,
QWidget)
import pyqtgraph as pg
import sys
import numpy as np
from PyQt5.QtCore import QRectF, QRect
class TestROI(QMainWindow):
imageWidth = 1000
imageHardLimitTop = 1048
imageHardLimitBottom = 2047
shallowestPixel = 1400
deepestPixel = 1699
ROITopBottomMargin = 20
shaderDarkness = 185
shaderColor = (0, 0, 50, shaderDarkness)
imageHardLimitDepth = imageHardLimitBottom - imageHardLimitTop + 1
def __init__(self):
super(TestROI, self).__init__()
self.mainWidget = QWidget()
self.imagePlotCanvas = pg.GraphicsLayoutWidget()
self.graphGridLayout = QGridLayout(self.mainWidget)
self.graphGridLayout.addWidget(self.imagePlotCanvas)
self.setCentralWidget(self.mainWidget)
self.showMaximized()
# Place for 2D images:
self.plotArea = self.imagePlotCanvas.addPlot()
self.plotArea.setRange(
QRect(0, self.imageHardLimitTop, self.imageWidth, self.imageHardLimitDepth))
self.plotArea.setLimits(xMin=-1000, xMax=2000)
self.plotArea.setAspectLocked(True)
self.plotArea.invertY(b=True)
self.plotArea.showGrid(x=True, y=True, alpha=1.0)
self.plotArea.showButtons()
self.twoDImageROI = pg.ROI(pos=[0, self.shallowestPixel],
size=[
self.imageWidth, self.deepestPixel - self.shallowestPixel + 1],
removable=False,
maxBounds=QRectF(-1, self.imageHardLimitTop-1,
self.imageWidth + 2, self.imageHardLimitDepth+1),
scaleSnap=False, translateSnap=False)
self.twoDImageROI.setZValue(20)
self.shadedTopRegion = pg.LinearRegionItem(
[self.imageHardLimitTop, self.shallowestPixel], orientation=pg.LinearRegionItem.Horizontal, movable=False)
self.shadedTopRegion.setBrush(color=self.shaderColor)
self.shadedTopRegion.setZValue(10)
self.plotArea.addItem(self.shadedTopRegion)
self.shadedBottomRegion = pg.LinearRegionItem(
[self.deepestPixel + 1, self.imageHardLimitBottom+1], orientation=pg.LinearRegionItem.Horizontal, movable=False)
self.shadedBottomRegion.setBrush(color=self.shaderColor)
self.shadedBottomRegion.setZValue(10)
self.plotArea.addItem(self.shadedBottomRegion)
# self.twoDImageROI.setAcceptedMouseButtons(Qt.LeftButton)
self.twoDImageROI.sigRegionChanged.connect(self.imageROIChanged)
# Shaded Region on the left and right to cover up the above two vertical lines when out of image bound.
self.shadedLeftRegion = pg.LinearRegionItem(
[-1000, 0], orientation=pg.LinearRegionItem.Vertical, movable=False)
self.shadedLeftRegion.setBrush(color=(0, 0, 0))
self.shadedLeftRegion.setZValue(20)
self.plotArea.addItem(self.shadedLeftRegion)
self.shadedRightRegion = pg.LinearRegionItem(
[1000, 2000], orientation=pg.LinearRegionItem.Vertical, movable=False)
self.shadedRightRegion.setBrush(color=(0, 0, 0))
self.shadedRightRegion.setZValue(20)
self.plotArea.addItem(self.shadedRightRegion)
self.twoDImageROI.addScaleHandle([0.5, 0.0], [0.5, 1.0], index=0)
self.twoDImageROI.addScaleHandle([0.5, 1.0], [0.5, 0.0], index=1)
self.twoDImageROI.addScaleHandle([1.0, 0.5], [0.5, 0.5])
self.twoDImageROI.addScaleHandle([0.0, 0.5], [0.5, 0.5])
self.twoDOCMImage = pg.ImageItem(border='c')
self.twoDOCMImage.setParentItem(self.plotArea)
self.plotArea.addItem(self.twoDOCMImage)
self.plotArea.addItem(self.twoDImageROI)
zeroImage = np.zeros(self.imageWidth * self.imageHardLimitDepth)\
.reshape((self.imageWidth, self.imageHardLimitDepth))
self.twoDOCMImage.setImage(zeroImage)
startingRect = QRect(0, self.imageHardLimitTop,
self.imageWidth, self.imageHardLimitDepth)
self.twoDOCMImage.setRect(startingRect)
def imageROIChanged(self):
x, top = self.twoDImageROI.pos()
top = int(round(top, 0))
w, h = self.twoDImageROI.size()
h = int(round(h, 0))
bot = top + h - 1
self.shallowestPixel = top
self.deepestPixel = bot
self.updateLinearRegion()
def updateLinearRegion(self):
x, top = self.twoDImageROI.pos()
top = int(round(top, 0))
w, h = self.twoDImageROI.size()
h = int(round(h, 0))
bot = top + h - 1
self.shadedTopRegion.setRegion([self.imageHardLimitTop, top])
self.shadedBottomRegion.setRegion([bot, self.imageHardLimitBottom+1])
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = TestROI()
main_window.show()
sys.exit(app.exec_())
我相信您所说的问题是在上下移动 ROI 时从左到右的 1px 摆动。这种效果是由于将实际 ROI 位置转换为绘制 X、Y 值。总会有四舍五入,因此投资回报率总是会左右摆动。
为防止这种情况,您可以手动设置您的投资回报率的常量 x 位置。为此,您必须覆盖 ROI class.
的 setPos这是投资回报率示例 class,您可以使用:
class ConstantXROI(ROI):
constant_x = 0
def setPos(self, pos, y=None, update=True, finish=True):
pos.setX(self.constant_x)
super().setPos(pos, y=y, update=update, finish=finish)
然后在您的代码中,只需使用:
self.twoDImageROI = ConstantXROI(...)