<legend id='aFTEX'><style id='aFTEX'><dir id='aFTEX'><q id='aFTEX'></q></dir></style></legend>

    <small id='aFTEX'></small><noframes id='aFTEX'>

        <bdo id='aFTEX'></bdo><ul id='aFTEX'></ul>
      1. <tfoot id='aFTEX'></tfoot>

      2. <i id='aFTEX'><tr id='aFTEX'><dt id='aFTEX'><q id='aFTEX'><span id='aFTEX'><b id='aFTEX'><form id='aFTEX'><ins id='aFTEX'></ins><ul id='aFTEX'></ul><sub id='aFTEX'></sub></form><legend id='aFTEX'></legend><bdo id='aFTEX'><pre id='aFTEX'><center id='aFTEX'></center></pre></bdo></b><th id='aFTEX'></th></span></q></dt></tr></i><div id='aFTEX'><tfoot id='aFTEX'></tfoot><dl id='aFTEX'><fieldset id='aFTEX'></fieldset></dl></div>

        将范围滑块小部件移植到 PyQt5

        时间:2023-10-19

        • <bdo id='Tchir'></bdo><ul id='Tchir'></ul>
          <tfoot id='Tchir'></tfoot>
            1. <small id='Tchir'></small><noframes id='Tchir'>

                <i id='Tchir'><tr id='Tchir'><dt id='Tchir'><q id='Tchir'><span id='Tchir'><b id='Tchir'><form id='Tchir'><ins id='Tchir'></ins><ul id='Tchir'></ul><sub id='Tchir'></sub></form><legend id='Tchir'></legend><bdo id='Tchir'><pre id='Tchir'><center id='Tchir'></center></pre></bdo></b><th id='Tchir'></th></span></q></dt></tr></i><div id='Tchir'><tfoot id='Tchir'></tfoot><dl id='Tchir'><fieldset id='Tchir'></fieldset></dl></div>

                    <tbody id='Tchir'></tbody>
                  <legend id='Tchir'><style id='Tchir'><dir id='Tchir'><q id='Tchir'></q></dir></style></legend>
                  本文介绍了将范围滑块小部件移植到 PyQt5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我目前需要一个范围滑块(一个可以设置最小值和最大值的滑块).我发现了两个相关的问题 Qt 中的范围滑块(两个句柄在一个QSlider) 和 为什么 RangeSlider 在 QtQuick 中可用而不是作为标准 Widget 但它们都不是用 python3 编写的,而且我对 C++ 不是很熟悉.

                  I am currently in need for a range slider (a slider where I can set up a min and a max value). I found two related questions Range slider in Qt (two handles in a QSlider) and Why RangeSlider is available in QtQuick and not as standard Widget but neither of them is written in python3 and I am not very familiar with C++.

                  我找到了这个完美的 github 工具 https://github.com/rsgalloway/qrangeslider 但它不幸的是,它是为 PyQt4 编写的,我正在使用 PyQt5.

                  I found this perfect github tool https://github.com/rsgalloway/qrangeslider but it is unfortunately written for PyQt4 and I am using PyQt5.

                  我打算用 PyQt5 绑定重新格式化这个 github 源,但在这样做之前我想知道是否有人以前做过这样我可以节省时间?或者,如果有人有不同的解决方案,我愿意接受建议.

                  I am planning to reformat this github source with PyQt5 bindings but before doing so I want to know if anyone has done it before so I could save time? Or if anyone has a different solution, I am open to suggestions.

                  推荐答案

                  下面是 QRangeSlider 小部件的 PyQt5 端口.为简洁起见,我删除了所有注释、文档字符串、断言语句等.它似乎在 Python 2 和 Python 3 上都可以正常工作,但我并没有真正对其进行过多测试.

                  Below is a PyQt5 port of the QRangeSlider widget. For the sake of brevity, I have removed all comments, doc-strings, assert statements, etc. It seems to work okay with both Python 2 and Python 3, but I haven't really tested it much.

                  qrangeslider.py:

                  import sys, os
                  from PyQt5 import QtCore, QtGui, QtWidgets
                  
                  __all__ = ['QRangeSlider']
                  
                  DEFAULT_CSS = """
                  QRangeSlider * {
                      border: 0px;
                      padding: 0px;
                  }
                  QRangeSlider #Head {
                      background: #222;
                  }
                  QRangeSlider #Span {
                      background: #393;
                  }
                  QRangeSlider #Span:active {
                      background: #282;
                  }
                  QRangeSlider #Tail {
                      background: #222;
                  }
                  QRangeSlider > QSplitter::handle {
                      background: #393;
                  }
                  QRangeSlider > QSplitter::handle:vertical {
                      height: 4px;
                  }
                  QRangeSlider > QSplitter::handle:pressed {
                      background: #ca5;
                  }
                  """
                  
                  def scale(val, src, dst):
                      return int(((val - src[0]) / float(src[1]-src[0])) * (dst[1]-dst[0]) + dst[0])
                  
                  
                  class Ui_Form(object):
                      def setupUi(self, Form):
                          Form.setObjectName("QRangeSlider")
                          Form.resize(300, 30)
                          Form.setStyleSheet(DEFAULT_CSS)
                          self.gridLayout = QtWidgets.QGridLayout(Form)
                          self.gridLayout.setContentsMargins(0, 0, 0, 0)
                          self.gridLayout.setSpacing(0)
                          self.gridLayout.setObjectName("gridLayout")
                          self._splitter = QtWidgets.QSplitter(Form)
                          self._splitter.setMinimumSize(QtCore.QSize(0, 0))
                          self._splitter.setMaximumSize(QtCore.QSize(16777215, 16777215))
                          self._splitter.setOrientation(QtCore.Qt.Horizontal)
                          self._splitter.setObjectName("splitter")
                          self._head = QtWidgets.QGroupBox(self._splitter)
                          self._head.setTitle("")
                          self._head.setObjectName("Head")
                          self._handle = QtWidgets.QGroupBox(self._splitter)
                          self._handle.setTitle("")
                          self._handle.setObjectName("Span")
                          self._tail = QtWidgets.QGroupBox(self._splitter)
                          self._tail.setTitle("")
                          self._tail.setObjectName("Tail")
                          self.gridLayout.addWidget(self._splitter, 0, 0, 1, 1)
                          self.retranslateUi(Form)
                          QtCore.QMetaObject.connectSlotsByName(Form)
                  
                      def retranslateUi(self, Form):
                          _translate = QtCore.QCoreApplication.translate
                          Form.setWindowTitle(_translate("QRangeSlider", "QRangeSlider"))
                  
                  
                  class Element(QtWidgets.QGroupBox):
                      def __init__(self, parent, main):
                          super(Element, self).__init__(parent)
                          self.main = main
                  
                      def setStyleSheet(self, style):
                          self.parent().setStyleSheet(style)
                  
                      def textColor(self):
                          return getattr(self, '__textColor', QtGui.QColor(125, 125, 125))
                  
                      def setTextColor(self, color):
                          if type(color) == tuple and len(color) == 3:
                              color = QtGui.QColor(color[0], color[1], color[2])
                          elif type(color) == int:
                              color = QtGui.QColor(color, color, color)
                          setattr(self, '__textColor', color)
                  
                      def paintEvent(self, event):
                          qp = QtGui.QPainter()
                          qp.begin(self)
                          if self.main.drawValues():
                              self.drawText(event, qp)
                          qp.end()
                  
                  
                  class Head(Element):
                      def __init__(self, parent, main):
                          super(Head, self).__init__(parent, main)
                  
                      def drawText(self, event, qp):
                          qp.setPen(self.textColor())
                          qp.setFont(QtGui.QFont('Arial', 10))
                          qp.drawText(event.rect(), QtCore.Qt.AlignLeft, str(self.main.min()))
                  
                  
                  class Tail(Element):
                      def __init__(self, parent, main):
                          super(Tail, self).__init__(parent, main)
                  
                      def drawText(self, event, qp):
                          qp.setPen(self.textColor())
                          qp.setFont(QtGui.QFont('Arial', 10))
                          qp.drawText(event.rect(), QtCore.Qt.AlignRight, str(self.main.max()))
                  
                  
                  class Handle(Element):
                      def __init__(self, parent, main):
                          super(Handle, self).__init__(parent, main)
                  
                      def drawText(self, event, qp):
                          qp.setPen(self.textColor())
                          qp.setFont(QtGui.QFont('Arial', 10))
                          qp.drawText(event.rect(), QtCore.Qt.AlignLeft, str(self.main.start()))
                          qp.drawText(event.rect(), QtCore.Qt.AlignRight, str(self.main.end()))
                  
                      def mouseMoveEvent(self, event):
                          event.accept()
                          mx = event.globalX()
                          _mx = getattr(self, '__mx', None)
                          if not _mx:
                              setattr(self, '__mx', mx)
                              dx = 0
                          else:
                              dx = mx - _mx
                          setattr(self, '__mx', mx)
                          if dx == 0:
                              event.ignore()
                              return
                          elif dx > 0:
                              dx = 1
                          elif dx < 0:
                              dx = -1
                          s = self.main.start() + dx
                          e = self.main.end() + dx
                          if s >= self.main.min() and e <= self.main.max():
                              self.main.setRange(s, e)
                  
                  
                  class QRangeSlider(QtWidgets.QWidget, Ui_Form):
                      endValueChanged = QtCore.pyqtSignal(int)
                      maxValueChanged = QtCore.pyqtSignal(int)
                      minValueChanged = QtCore.pyqtSignal(int)
                      startValueChanged = QtCore.pyqtSignal(int)
                      minValueChanged = QtCore.pyqtSignal(int)
                      maxValueChanged = QtCore.pyqtSignal(int)
                      startValueChanged = QtCore.pyqtSignal(int)
                      endValueChanged = QtCore.pyqtSignal(int)
                  
                      _SPLIT_START = 1
                      _SPLIT_END = 2
                  
                      def __init__(self, parent=None):
                          super(QRangeSlider, self).__init__(parent)
                          self.setupUi(self)
                          self.setMouseTracking(False)
                          self._splitter.splitterMoved.connect(self._handleMoveSplitter)
                          self._head_layout = QtWidgets.QHBoxLayout()
                          self._head_layout.setSpacing(0)
                          self._head_layout.setContentsMargins(0, 0, 0, 0)
                          self._head.setLayout(self._head_layout)
                          self.head = Head(self._head, main=self)
                          self._head_layout.addWidget(self.head)
                          self._handle_layout = QtWidgets.QHBoxLayout()
                          self._handle_layout.setSpacing(0)
                          self._handle_layout.setContentsMargins(0, 0, 0, 0)
                          self._handle.setLayout(self._handle_layout)
                          self.handle = Handle(self._handle, main=self)
                          self.handle.setTextColor((150, 255, 150))
                          self._handle_layout.addWidget(self.handle)
                          self._tail_layout = QtWidgets.QHBoxLayout()
                          self._tail_layout.setSpacing(0)
                          self._tail_layout.setContentsMargins(0, 0, 0, 0)
                          self._tail.setLayout(self._tail_layout)
                          self.tail = Tail(self._tail, main=self)
                          self._tail_layout.addWidget(self.tail)
                          self.setMin(0)
                          self.setMax(99)
                          self.setStart(0)
                          self.setEnd(99)
                          self.setDrawValues(True)
                  
                      def min(self):
                          return getattr(self, '__min', None)
                  
                      def max(self):
                          return getattr(self, '__max', None)
                  
                      def setMin(self, value):
                          setattr(self, '__min', value)
                          self.minValueChanged.emit(value)
                  
                      def setMax(self, value):
                          setattr(self, '__max', value)
                          self.maxValueChanged.emit(value)
                  
                      def start(self):
                          return getattr(self, '__start', None)
                  
                      def end(self):
                          return getattr(self, '__end', None)
                  
                      def _setStart(self, value):
                          setattr(self, '__start', value)
                          self.startValueChanged.emit(value)
                  
                      def setStart(self, value):
                          v = self._valueToPos(value)
                          self._splitter.splitterMoved.disconnect()
                          self._splitter.moveSplitter(v, self._SPLIT_START)
                          self._splitter.splitterMoved.connect(self._handleMoveSplitter)
                          self._setStart(value)
                  
                      def _setEnd(self, value):
                          setattr(self, '__end', value)
                          self.endValueChanged.emit(value)
                  
                      def setEnd(self, value):
                          v = self._valueToPos(value)
                          self._splitter.splitterMoved.disconnect()
                          self._splitter.moveSplitter(v, self._SPLIT_END)
                          self._splitter.splitterMoved.connect(self._handleMoveSplitter)
                          self._setEnd(value)
                  
                      def drawValues(self):
                          return getattr(self, '__drawValues', None)
                  
                      def setDrawValues(self, draw):
                          setattr(self, '__drawValues', draw)
                  
                      def getRange(self):
                          return (self.start(), self.end())
                  
                      def setRange(self, start, end):
                          self.setStart(start)
                          self.setEnd(end)
                  
                      def keyPressEvent(self, event):
                          key = event.key()
                          if key == QtCore.Qt.Key_Left:
                              s = self.start()-1
                              e = self.end()-1
                          elif key == QtCore.Qt.Key_Right:
                              s = self.start()+1
                              e = self.end()+1
                          else:
                              event.ignore()
                              return
                          event.accept()
                          if s >= self.min() and e <= self.max():
                              self.setRange(s, e)
                  
                      def setBackgroundStyle(self, style):
                          self._tail.setStyleSheet(style)
                          self._head.setStyleSheet(style)
                  
                      def setSpanStyle(self, style):
                          self._handle.setStyleSheet(style)
                  
                      def _valueToPos(self, value):
                          return scale(value, (self.min(), self.max()), (0, self.width()))
                  
                      def _posToValue(self, xpos):
                          return scale(xpos, (0, self.width()), (self.min(), self.max()))
                  
                      def _handleMoveSplitter(self, xpos, index):
                          hw = self._splitter.handleWidth()
                          def _lockWidth(widget):
                              width = widget.size().width()
                              widget.setMinimumWidth(width)
                              widget.setMaximumWidth(width)
                          def _unlockWidth(widget):
                              widget.setMinimumWidth(0)
                              widget.setMaximumWidth(16777215)
                          v = self._posToValue(xpos)
                          if index == self._SPLIT_START:
                              _lockWidth(self._tail)
                              if v >= self.end():
                                  return
                              offset = -20
                              w = xpos + offset
                              self._setStart(v)
                          elif index == self._SPLIT_END:
                              _lockWidth(self._head)
                              if v <= self.start():
                                  return
                              offset = -40
                              w = self.width() - xpos + offset
                              self._setEnd(v)
                          _unlockWidth(self._tail)
                          _unlockWidth(self._head)
                          _unlockWidth(self._handle)
                  
                  if __name__ == '__main__':
                  
                      app = QtWidgets.QApplication(sys.argv)
                      rs = QRangeSlider()
                      rs.show()
                      rs.setRange(15, 35)
                      rs.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);')
                      rs.handle.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);')
                      app.exec_()
                  

                  如果你想运行 examples,你只需要更改以下代码块(在文件顶部):

                  If you want to run the examples, you just need to change the following code block (at the top of the file):

                  examples.py:

                  import sys, os
                  from PyQt5 import QtCore
                  from PyQt5 import QtGui
                  from PyQt5 import QtWidgets
                  
                  from qrangeslider import QRangeSlider
                  
                  app = QtWidgets.QApplication(sys.argv)
                  
                  ...
                  

                  这篇关于将范围滑块小部件移植到 PyQt5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:如何在 matplotlib 中制作两个滑块 下一篇:如何更新可滚动、matplotlib 和 multiplot 中的艺术家

                  相关文章

                  <i id='Q6dGY'><tr id='Q6dGY'><dt id='Q6dGY'><q id='Q6dGY'><span id='Q6dGY'><b id='Q6dGY'><form id='Q6dGY'><ins id='Q6dGY'></ins><ul id='Q6dGY'></ul><sub id='Q6dGY'></sub></form><legend id='Q6dGY'></legend><bdo id='Q6dGY'><pre id='Q6dGY'><center id='Q6dGY'></center></pre></bdo></b><th id='Q6dGY'></th></span></q></dt></tr></i><div id='Q6dGY'><tfoot id='Q6dGY'></tfoot><dl id='Q6dGY'><fieldset id='Q6dGY'></fieldset></dl></div>

                1. <tfoot id='Q6dGY'></tfoot>
                    • <bdo id='Q6dGY'></bdo><ul id='Q6dGY'></ul>

                    <small id='Q6dGY'></small><noframes id='Q6dGY'>

                      <legend id='Q6dGY'><style id='Q6dGY'><dir id='Q6dGY'><q id='Q6dGY'></q></dir></style></legend>