看你的代码,主要的问题在于计算 QSlider 的数值位置和进行drawText操作的地方。这里给你一个修正和优化的版本,希望能帮助你解决问题。
import sys
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QSlider, QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QFontMetrics
class NumberLineSlider(QSlider):
def __init__(self, min_value, max_value, *args, **kwargs):
super().__init__(Qt.Horizontal, *args, **kwargs)
self.min_value = min_value
self.max_value = max_value
self.setMinimum(min_value)
self.setMaximum(max_value)
self.setTickPosition(QSlider.TicksBelow)
self.setTickInterval(1) # 设置每个刻度的间隔为1
def paintEvent(self, event):
super().paintEvent(event)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
slider_width = self.width()
slider_height = self.height()
for value in range(self.min_value, self.max_value + 1):
x = self.position_for_value(value, slider_width)
painter.drawLine(x, slider_height - 20, x, slider_height - 10)
text = str(value)
font_metrics = painter.fontMetrics()
text_width = font_metrics.horizontalAdvance(text) # 更新点:使用 horizontalAdvance 而不是 width
painter.drawText(x - text_width // 2, slider_height - 30, text)
def position_for_value(self, value, slider_width):
"""计算给定数值在滑块上的 x 坐标"""
slider_min = self.minimum()
slider_max = self.maximum()
if slider_max == slider_min:
return 0
return int(slider_width * (value - slider_min) / (slider_max - slider_min))
# 主窗口
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Number Line Slider Example')
self.setGeometry(100, 100, 600, 100)
layout = QVBoxLayout()
self.slider = NumberLineSlider(0, 10)
layout.addWidget(self.slider)
self.value_label = QLabel("0")
layout.addWidget(self.value_label)
self.slider.valueChanged.connect(self.update_label)
self.setLayout(layout)
def update_label(self, value):
self.value_label.setText(str(value))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
主要修改点:
1. 使用 `font_metrics.horizontalAdvance(text)` 而不是 `font_metrics.width(text)`。`horizontalAdvance` 是计算字符串显示长度的更现代化方法。
2. 增加了超出显示范围的处理。比如当 `self.minimum()` 和 `self.maximum()` 值相等时防止除以零错误。
3. 为方便测试,增加一个主窗口类 `MainWindow`, 承载 `NumberLineSlider` 并且显示当前的 Slider 值。
希望对你有帮助!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |