Qt/PyQt5 강좌

두 개의 바를 사용하여 최대값, 최소값 조정하는 슬라이더 PyQt5 예제

webnautes 2024. 8. 9. 22:50
반응형

두 개의 바를 사용하여 최대값, 최소값 조정하는 슬라이더 PyQt5  예제입니다.

 

2024. 8. 9 최초작성







from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt, pyqtSignal, QRectF
from PyQt5.QtGui import QPainter, QColor, QPen

class RangeSlider(QWidget):
    valueChanged = pyqtSignal(int, int)

    def __init__(self, values, parent=None):
        super().__init__(parent)
        self.values = values
        self.first_position = 0
        self.second_position = len(values) - 1
        self.moving = None
        self.handle_radius = 10
        self.padding = self.handle_radius + 2  # 패딩 추가
        self.setMinimumHeight(2 * (self.handle_radius + self.padding))

    def mousePressEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            x = event.pos().x()
            distance_first = abs(self.positionToX(self.first_position) - x)
            distance_second = abs(self.positionToX(self.second_position) - x)
            if distance_first < distance_second:
                self.moving = "first"
            else:
                self.moving = "second"

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            x = event.pos().x()
            position = self.xToPosition(x)
            if self.moving == "first" and position < self.second_position:
                self.first_position = position
            elif self.moving == "second" and position > self.first_position:
                self.second_position = position
            self.update()
            self.valueChanged.emit(self.values[self.first_position], self.values[self.second_position])

    def mouseReleaseEvent(self, event):
        self.moving = None

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # 그리기 영역 조정
        draw_area = self.width() - 2 * self.padding
        start_x = self.padding
        end_x = self.width() - self.padding

        # Draw the line
        pen = QPen(QColor(200, 200, 200))
        pen.setWidth(4)
        painter.setPen(pen)
        painter.drawLine(start_x, self.height() // 2, end_x, self.height() // 2)

        # Draw the handles
        painter.setBrush(QColor(255, 255, 255))
        painter.drawEllipse(QRectF(self.positionToX(self.first_position) - self.handle_radius,
                            self.height() // 2 - self.handle_radius,
                            self.handle_radius * 2, self.handle_radius * 2))
        painter.drawEllipse(QRectF(self.positionToX(self.second_position) - self.handle_radius,
                            self.height() // 2 - self.handle_radius,
                            self.handle_radius * 2, self.handle_radius * 2))

    def positionToX(self, position):
        draw_area = self.width() - 2 * self.padding
        return int(position * draw_area / (len(self.values) - 1)) + self.padding

    def xToPosition(self, x):
        draw_area = self.width() - 2 * self.padding
        adjusted_x = max(self.padding, min(x, self.width() - self.padding)) - self.padding
        return min(max(round(adjusted_x * (len(self.values) - 1) / draw_area), 0), len(self.values) - 1)

class PriceRangeWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.values = [20, 35, 50, 75, 100, 150, 200, 250# 사전 정의된 값 리스트
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(10)

        self.range_slider = RangeSlider(self.values)
        self.range_slider.valueChanged.connect(self.updateLabels)

        self.min_label = QLabel(f'최소: {self.values[0]}만원')
        self.max_label = QLabel(f'최대: {self.values[-1]}만원')

        font = self.min_label.font()
        font.setPointSize(12)
        self.min_label.setFont(font)
        self.max_label.setFont(font)

        layout.addWidget(self.min_label)
        layout.addWidget(self.range_slider)
        layout.addWidget(self.max_label)

        self.setLayout(layout)
        self.setWindowTitle('가격 범위 설정')
        self.setMinimumSize(400, 150)

    def updateLabels(self, min_val, max_val):
        self.min_label.setText(f'최소: {min_val}만원')
        self.max_label.setText(f'최대: {max_val}만원')

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    ex = PriceRangeWidget()
    ex.show()
    sys.exit(app.exec_())


반응형