Thursday, February 16, 2023

Display a Ruler on top of a QTextEdit Widget

I am trying to mimic a typical Wordprocessor document as part of my ongoing Chat Application project with an Integrated Development Environment(IDE) and which slowly evolving to have a Content management System(CMS) module. Having the said module should have at least a ruler be displayed on top of the Code Editor pane(QTextEdit Widget) . SO far, I have come up with the following sample program . But first here is the screenshot:


And here is the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QTextEdit
from PyQt5.QtGui import QFont, QFontMetrics, QPainter
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPen

class Ruler(QWidget):
    def __init__(self):
        super().__init__()

        # Set up the widget
        self.setFixedHeight(20)
        self.font = QFont('Arial', 5)
        self.font_metrics = QFontMetrics(self.font)
        self.text_edit = None

    def set_text_edit(self, text_edit):
        self.text_edit = text_edit
        self.text_edit.cursorPositionChanged.connect(self.update)

    def paintEvent(self, event):
        if not self.text_edit:
            return

        painter = QPainter(self)

        # Set up the white background
        painter.fillRect(self.rect(), Qt.white)

        # Get the metrics for the font
        painter.setFont(self.font)
        font_metrics = self.font_metrics

        # Draw the tick marks and text labels
        x_pos = self.text_edit.horizontalScrollBar().value()
        width = self.width()
        step = font_metrics.width(' ') * 5

        for x in range(x_pos % step, width, step):
            if x % 100 == 0:
                painter.drawLine(x, 0, x, 5)

                # Center the text labels to the lines
                label_width = font_metrics.width(str(x))
                label_x_pos = x - label_width / 2
                label_y_pos = 15
                painter.drawText(int(label_x_pos), int(label_y_pos), str(x))
            elif x % 50 == 0:
                painter.drawLine(x, 0, x, 3)
            elif x % 10 == 0:
                painter.drawLine(x, 0, x, 1)
         # Draw the red line at the current mouse position
        #painter.setPen(QPen(Qt.red, 1))
        #painter.drawLine(self.mouse_pos.x(), 0, self.mouse_pos.x(), self.height())
    #def mouseMoveEvent(self, event):
    #    pos = event.pos()
    #    self.mouse_x = pos.x()
    #    self.update()  
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Set up main window
        self.setWindowTitle("Ruler Example")
        self.setGeometry(100, 100, 800, 600)

        # Set up text editor
        self.text_edit = QTextEdit()
        self.setCentralWidget(self.text_edit)

        # Set up ruler
        self.ruler = Ruler()
        self.ruler.set_text_edit(self.text_edit)

        # Set up layout
        layout = QVBoxLayout()
        layout.addWidget(self.ruler)
        layout.addWidget(self.text_edit)

        # Set the layout for the main window
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

I will include this in the next upgrade of my Chat Application project.



No comments:

Post a Comment