Issue
I need to add a crosshair, like here on the page.crosshair The crosshair should move behind the mouse. There are few examples on the Internet on this topic. There's "pyqtgraph" everywhere". I don't understand them. I want to use the button to add and remove the crosshair. Can I do with just one pyqt?
Сan use this code as a basis to add a crosshair.
from PyQt5 import QtCore, QtGui, QtWidgets, QtChart
from PyQt5.QtCore import *
from PyQt5.QtChart import *
import math
import numpy as np
mas =[1.33, 1.15, 1.55, 1.65, 1.64, 1.91, 1.33, 2.3, 1.5, 1.35, 2.52, 1.77, 1.7, 1.87, 2.0, 1.55, 1.73, 2.1,
1.33, 1.15, 1.55, 1.92, 1.64, 1.91, 1.33, 1.71, 1.5, 1.35, 1.22, 1.77, 1.7, 1.87, 2.7, 1.55, 1.73, 2.1,
1.33, 1.15, 1.55, 1.92, 1.64, 1.91, 1.33, 1.71, 1.5, 1.35, 1.22, 1.77, 1.7, 1.87, 2.0, 1.55, 1.73, 2.1]
x = len(mas)
x_ = x - 1
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, start = 1, parent=None):
self.start = start
super().__init__(parent)
self.step = 30
self._chart_view = QtChart.QChartView()
self.scrollbar = QtWidgets.QScrollBar(
QtCore.Qt.Horizontal,
sliderMoved=self.onAxisSliderMoved,
pageStep=self.step,
)
self.scrollbar.setRange(0, x_)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
for w in (self._chart_view, self.scrollbar):
lay.addWidget(w)
self._chart = QtChart.QChart()
self._line_serie = QtChart.QLineSeries()
for i in range(0, len(mas)):
self._line_serie.append(QtCore.QPointF(i, mas[i]))
min_x, max_x = 0, x_
self._chart.addSeries(self._line_serie)
axisX = QValueAxis()
axisX.setTickCount(5)
axisX.setLabelFormat("%d")
self._chart.addAxis(axisX, Qt.AlignBottom)
self._line_serie.attachAxis(axisX)
axisY = QValueAxis()
self._chart.addAxis(axisY, Qt.AlignLeft)
self._line_serie.attachAxis(axisY)
self._chart.legend().hide()
self._chart_view.setChart(self._chart)
self.lims = np.array([min_x, max_x])
self.onAxisSliderMoved(self.scrollbar.value())
self.adjust_axes(self.start, 31)
def adjust_axes(self, value_min, value_max):
if value_min >= 0 and value_max >= 0 and value_max <= x_ and value_max > value_min:
self._chart.axisX(self._line_serie).setRange(value_min, value_max)
@QtCore.pyqtSlot(int)
def onAxisSliderMoved(self, value):
value2 = value + self.step
value1 = value
if value2 >= x_:
value2 = x_
value1 = value2 - self.step
self.adjust_axes(math.floor(value1), math.ceil(value2))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow(start = 0)
w.show()
sys.exit(app.exec_())
Solution
A possible solution is to override the drawForeground method of QChartView where the lines should be drawn based on the mouse position:
class ChartView(QtChart.QChartView):
def __init__(self, parent=None):
super().__init__(parent)
self._value_pos = QtCore.QPoint()
self.setMouseTracking(True)
def drawForeground(self, painter, rect):
super().drawForeground(painter, rect)
if self.chart() is None or self._value_pos.isNull():
return
pen = QtGui.QPen(QtGui.QColor("salmon"))
pen.setWidth(8)
painter.setPen(pen)
area = self.chart().plotArea()
sp = self.chart().mapToPosition(self._value_pos)
x1 = QtCore.QPointF(area.left() + pen.width() / 2, sp.y())
x2 = QtCore.QPointF(area.right() - pen.width() / 2, sp.y())
y1 = QtCore.QPointF(sp.x(), area.top() + pen.width() / 2)
y2 = QtCore.QPointF(sp.x(), area.bottom() - pen.width() / 2)
if area.left() <= sp.x() <= area.right():
painter.drawLine(y1, y2)
if area.top() < sp.y() < area.bottom():
painter.drawLine(x1, x2)
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
if self.chart() is None:
return
sp = self.mapToScene(event.pos())
if self.chart().plotArea().contains(sp):
self._value_pos = self.chart().mapToValue(sp)
self.setCursor(QtCore.Qt.PointingHandCursor)
else:
self.unsetCursor()
self.update()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, start=1, parent=None):
super().__init__(parent)
self.start = start
self._chart_view = ChartView()
# ...
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.