我想将PyQtGraph鼠标轮缩放功能连接到QSlider小部件上。因此,当我放大/缩小图形时,我会得到视图框的范围,滑块窗口应该在滑动范围内跟随。最接近我想要的例子可以在这个PyQtGraph示例中找到:http://www.pyqtgraph.org/downloads/0.10.0/pyqtgraph-0.10.0-deb/pyqtgraph-0.10.0/examples/crosshair.py
因此,我想以某种方式连接以下定义。
def update_plot(self):
self.axX = self.p6.getAxis('bottom')
self.xmin = self.axX.range[0]
self.xmax = self.axX.range[0]
print(self.axX.range)
return xmin, xmax
def update_slider(self, xmin, xmax):
self.size = self.w1.slider.value()
self.p6.setXRange(self.xmin+self.size,self.xmax+self.size)
print(self.size)
然而,我似乎无法让它发挥作用。我已附上我的例子的完整代码如下。你能帮我什么忙吗?
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel, QSizePolicy, QSlider, QSpacerItem, \
QVBoxLayout, QWidget
import pyqtgraph as pg
import numpy as np
class Slider(QWidget):
def __init__(self, minimum, maximum, parent=None):
super(Slider, self).__init__(parent=parent)
self.verticalLayout = QVBoxLayout(self)
self.label = QLabel(self)
self.verticalLayout.addWidget(self.label)
self.horizontalLayout = QHBoxLayout()
spacerItem = QSpacerItem(0, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.slider = QSlider(self)
self.slider.setOrientation(Qt.Vertical)
self.horizontalLayout.addWidget(self.slider)
spacerItem1 = QSpacerItem(0, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.verticalLayout.addLayout(self.horizontalLayout)
self.resize(self.sizeHint())
self.minimum = minimum
self.maximum = maximum
self.slider.valueChanged.connect(self.setLabelValue)
self.x = None
self.setLabelValue(self.slider.value())
def setLabelValue(self, value):
self.x = self.minimum + (float(value) / (self.slider.maximum() - self.slider.minimum())) * (
self.maximum - self.minimum)
self.label.setText("{0:.4g}".format(self.x))
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent=parent)
self.horizontalLayout = QHBoxLayout(self)
# plot (p6)
self.win = pg.GraphicsWindow(title="Basic plotting examples")
self.horizontalLayout.addWidget(self.win)
self.p6 = self.win.addPlot(title="My Plot")
x = np.arange(1e5)
self.y1 = np.random.randn(x.size)
self.p6.plot(self.y1, pen="r")
self.p6.setMouseEnabled(x=True, y=False)
self.p6.setXRange(0,300)
self.p6.setLimits(xMin=0, xMax=len(self.y1))
self.p6.sigRangeChanged.connect(self.update_plot)
# slider (w1)
self.w1 = Slider(0, len(self.y1))
self.horizontalLayout.addWidget(self.w1)
self.w1.slider.setMinimum(0)
self.w1.slider.setMaximum(len(self.y1))
self.w1.slider.valueChanged.connect(self.update_slider)
def update_plot(self):
self.axX = self.p6.getAxis('bottom')
self.xmin = self.axX.range[0]
self.xmax = self.axX.range[0]
print(self.axX.range)
return self.xmin, self.xmax
def update_slider(self, xmin, xmax):
self.size = self.w1.slider.value()
self.p6.setXRange(self.xmin+self.size,self.xmax+self.size)
print(self.size)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
发布于 2019-11-24 04:12:13
首先,你先问的问题实际上对StackOverflow的“行为”更有用。在编辑之后,您刚刚从pyqtgraph示例中留下了一个无用的普通复制/粘贴。
,,不要那么做。
人们很少经过编辑,看到你的问题的现状,他们会认为你根本没有努力去解决你的问题(导致他们忽视你的问题)。我建议您撤消编辑,或者至少还原原始的问题示例代码。
你问题的主要问题是缩放不是线性的。从普通用户的角度来看,缩放滑块的每一步都应该增加或减少一个缩放因子(pyqtgraph实际上就是这样做的)。
滑块通常是一个线性界面,这意味着它的每一步都应该与其先前或接下来的步骤成正比。
简单地说,如果滑块的“中间步骤”等于图像的原始大小,而“下一步”等于双倍大小,则用户期望接下来的步骤将导致大小再次翻倍。很明显,同样的方法也是向后的。
把它想象成一个菠萝盒,甚至几个+/-
按钮。
size = 2
print(size)
Out[1]: 2
def doZoom(size, step):
zoomFactor = 2
if step > 0:
size *= zoomFactor
else:
size /= zoomFactor
return size
size = doZoom(size, +1)
print(size)
Out[2]: 4
size = doZoom(size, +1)
print(size)
Out[3]: 8
size = doZoom(size, -1)
print(size)
Out[4]: 4
一个可能的解决方案是实现一个考虑到所有这一切的滑块。
import sys
from math import log
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QLabel, QSlider, QWidget,
QHBoxLayout, QVBoxLayout)
import pyqtgraph as pg
import numpy as np
class LabelSlider(QWidget):
def __init__(self, *args, **kwargs):
super(LabelSlider, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
# IMPORTANT! QStyles sometimes create *huge* margins (6-10 pixels) around
# layout contents; we don't really need those in here
layout.setContentsMargins(0, 0, 0, 0)
self.label = QLabel()
layout.addWidget(self.label, alignment=Qt.AlignHCenter)
# use an arbitrary text for the minimum width to minimize size flickering
# on value changes
self.label.setMinimumWidth(self.fontMetrics().width("8.8888e+88"))
self.label.setAlignment(Qt.AlignCenter)
layout.addSpacing(10)
self.slider = QSlider()
# when adding a QSlider to a QLayout and specifying an alignment, the
# opposite of the orientation *has* to be omitted to ensure that it's
# centered in the other direction
layout.addWidget(self.slider, alignment=Qt.AlignHCenter)
# set the slider "transparent" for mouse events, so that the user will
# still see it as enabled but won't be able to interact with it
self.slider.setAttribute(Qt.WA_TransparentForMouseEvents)
#set a range high enough to limit rounding errors
self.slider.setMaximum(100000)
# expose the basic slider signal/methods for transparency, so that
# this LabelSlider will have a similar interface to that of a QSlider
self.value = self.slider.value
self.valueChanged = self.slider.valueChanged
def setValue(self, value, xLimit):
sliderValue = self.slider.maximum() - value * self.slider.maximum()
self.slider.setValue(sliderValue)
xLimitMin, xLimitMax = xLimit
limitRange = xLimitMax - xLimitMin
floatValue = xLimitMin + (value * limitRange / (limitRange)) * (
limitRange)
self.label.setText("{0:.4g}".format(floatValue))
# ensure that the widget is resized to fit the label contents too;
# sizeHint will be called afterwards
self.updateGeometry()
def sizeHint(self):
hint = super(LabelSlider, self).sizeHint()
# adjust the minimum hint width to accomodate the label contents
if hint.width() < self.label.width():
hint.setWidth(self.label.width())
return hint
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent=parent)
self.horizontalLayout = QHBoxLayout(self)
self.win = pg.GraphicsWindow(title="Basic plotting examples")
self.horizontalLayout.addWidget(self.win)
self.p6 = self.win.addPlot(title="My Plot")
x = np.arange(1e5)
self.y1 = np.random.randn(x.size)
self.p6.plot(self.y1, pen="r")
self.p6.setMouseEnabled(x=True, y=False)
self.p6.setXRange(0,300)
# set a minimum x range for the plot
# this value *HAS* to be > 0
self.p6.setLimits(xMin=0, xMax=len(self.y1), minXRange=1)
self.p6.sigRangeChanged.connect(self.update_plot)
self.slider = LabelSlider()
self.horizontalLayout.addWidget(self.slider)
def update_plot(self):
state = self.p6.getViewBox().state
# get the limits of the plot's ViewBox
limits = state["limits"]
minZoom, maxZoom = xLimit = limits["xLimits"]
xRangeMin, xRangeMax = limits["xRange"]
# if the minimum x range is set, use that instead
if xRangeMin is not None:
minZoom = xRangeMin
# ensure that the minimum x range is > 0
minZoom = max(1, minZoom)
if xRangeMax is not None:
maxZoom = xRangeMax
xMin, xMax = self.p6.getAxis("bottom").range
diff = xMax - xMin
# get the possible minimum and maximum values based on the wheel factor
factor = abs(state["wheelScaleFactor"])
minimum = log(maxZoom / 100000., factor)
maximum = log(minZoom / 100000., factor)
value = log(diff / 100000., factor)
# adjust the factor to a 0.0-1.0 range according to the possible zoom
realValue = (value - minimum) / (maximum - minimum)
# set the slider value according to the above value
self.slider.setValue(realValue, xLimit)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
https://stackoverflow.com/questions/59010270
复制相似问题