Reputation: 1
I need to develop a program to enter time reports. What I do is very similar to time graphics. I was only able to implement scaling, shuffling and pseudo-infinity fields. The main task is to somehow add intermediate lines between years as we scale. And add dates under each line up to minutes.
I tried to implement this by drawing a line only to the edges of the screen. That is, I took the width of the screen and divided it integerly by the distance between the lines and got the number of lines to the edges of the screen. And the distance between the lines depended on the scale. But I couldn't add sublines and make the scaling infinite like in time graphics
Code:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt, QPoint
class DrawingApp(QMainWindow):
def __init__(self):
super().__init__()
#settings
self.drawing_widget = self.DrawingWidget(self)
self.setCentralWidget(self.drawing_widget)
self.status_label = QLabel("", self)
self.status_label.setGeometry(10, 10, 200, 20)
self.setGeometry(100, 100, 800, 600)
self.drawing_widget.installEventFilter(self)
self.drawing_widget.setMouseTracking(True)
self.dragging = False
self.drag_start_position = QPoint()
self.was_dragged = False
def eventFilter(self, obj, event):
'''all mouse events'''
if obj is self.drawing_widget:
if event.type() == event.MouseButtonPress and event.button() == Qt.LeftButton:
self.dragging = True
self.drag_start_position = event.pos()
self.was_dragged = False
return True
if event.type() == event.MouseMove and self.dragging:
delta = event.pos() - self.drag_start_position
if delta.manhattanLength() > 0:
self.drawing_widget.update_offset(delta)
self.drag_start_position = event.pos()
self.was_dragged = True
return True
if event.type() == event.MouseButtonRelease and event.button() == Qt.LeftButton:
self.dragging = False
if not self.was_dragged:
self.status_label.setText(f"Click at: ({event.pos().x()}, {event.pos().y()})")
return True
if event.type() == event.Wheel:
zoom_scale = 1.1
if event.angleDelta().y() > 0:
self.drawing_widget.change_scale(zoom_scale, event.pos())
else:
self.drawing_widget.change_scale(1 / zoom_scale, event.pos())
return True
return super().eventFilter(obj, event)
class DrawingWidget(QWidget):
'''all drawing events'''
def __init__(self, parent=None):
super().__init__(parent)
self.setMinimumSize(800, 600)
self.offset = QPoint(0, 0)
self.scale = 1.0
def update_offset(self, delta):
self.offset += delta
self.update()
def change_scale(self, scale_factor, mouse_pos):
'''change scale with align to cursors coordinate'''
new_scale = self.scale * scale_factor
if new_scale < 0.1:
new_scale = 0.1
if new_scale > 100:
new_scale = 100
cursor_offset = mouse_pos - self.rect().center()
self.offset = QPoint(
int(self.offset.x() * scale_factor - cursor_offset.x() * (scale_factor - 1)),
#int(self.offset.y() * scale_factor - cursor_offset.y() * (scale_factor - 1))
)
self.scale = new_scale
self.update()
def paintEvent(self, event):
painter = QPainter(self)
offset_x, offset_y = self.offset.x(), self.offset.y()
widget_width = self.width()
widget_height = self.height()
center = self.rect().center()
scaled_size = 100 * self.scale
sector_count = round(widget_width / scaled_size)
offset_x %= scaled_size
for i in range(sector_count + 2):
# x_start = round(center.x() + offset_x) - scaled_size * i
# x_end = round(center.x() + offset_x) + scaled_size * i
painter.setPen(QPen(Qt.green, 2, Qt.SolidLine))
x = round(round(center.x() + offset_x) + scaled_size * i)
painter.drawLine(x, 20, x, widget_height - 20)
x = round(round(center.x() + offset_x) - scaled_size * i)
painter.drawLine(x, 20, x, widget_height - 20)
#sublines
# if scaled_size > 200:
# subgrid_interval = scaled_size / 4
# for j in range(1, 4):
# sub_x1 = round(x_start + j * subgrid_interval)
# sub_x2 = round(x_end - j * subgrid_interval)
# painter.setPen(QPen(Qt.gray, 1, Qt.DashLine))
# painter.drawLine(sub_x1, 20, sub_x1, widget_height - 20)
# painter.drawLine(sub_x2, 20, sub_x2, widget_height - 20)
#dates
# painter.setPen(Qt.black)
# painter.drawText(x_start - 10, widget_height // 2 + 5, "date")
# painter.drawText(x_end - 10, widget_height // 2 + 5, "date")
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = DrawingApp()
main_window.show()
sys.exit(app.exec_())
Pls help me with this or suggest articles or ready-made solutions that can be adapted to my needs. Maybe someone has already encountered this problem.
Upvotes: -1
Views: 95
Reputation: 19375
add dates under each line
A date can be added to each line depending on the widget's offset, e. g. for years:
toyear = 2024+(offset_x-self.offset.x())/scaled_size
painter.drawText(x_start - 10, widget_height // 2 + 5, "%d"%(toyear-i))
painter.drawText(x_end - 10, widget_height // 2 + 5, "%d"%(toyear+i))
This can of course be expanded for sublines as desired.
Note that you must not limit scale
to 100
if you want to zoom in beyond days.
Upvotes: 0