Конвертировать горизонтальный / вертикальный слайдер в одну кнопку - PullRequest
0 голосов
/ 26 июня 2019

Я искал способ конвертировать горизонтальный слайдер + вертикальный слайдер в одну кнопку в области окна. Вы знаете или думаете, что Qt способен сделать это?

это изображение показывает, что я хочу

enter image description here

Ответы [ 2 ]

2 голосов
/ 26 июня 2019

Этот вид виджета довольно легко создать, если вы используете события мыши:

  • mousePressEvent: если мышь находится над курсором, курсор может перемещаться
  • mouseReleaseEvent:отключить курсор
  • mouseMoveEvent: переместить курсор, если ходы разрешены

Затем с помощью paintEvent отобразить курсор в его положении.

ДляДля определения значения курсора необходимо преобразовать позицию в пикселях в значение, основанное на границах оси.

Быстрый пример джойстика со значением H в диапазоне от -10 до 20 и значением Vот -10 до 10:

from PyQt4.QtGui import QWidget, QApplication, QPainter
from PyQt4 import QtCore
import sys

class Joystick(QWidget):
    def __init__(self, parent=None):
        super(Joystick, self).__init__(parent)
        self.setFixedSize(100, 100)

        self._minimumX = -10
        self._maximumX = 20
        self._minimumY = -10
        self._maximumY = 10

        self.cursorPosition = QtCore.QPointF(10, 90)
        self.grabCursor = False

    def valueX(self):
        return (self.cursorPosition.x() - 10) * (self._maximumX - self._minimumX) / (self.width() - 20) + self._minimumX

    def valueY(self):
        return (self.cursorPosition.y() - 10) * (self._maximumY - self._minimumY) / (self.width() - 20) + self._minimumY

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(QtCore.Qt.lightGray)
        painter.setPen(QtCore.Qt.NoPen)
        painter.drawRect(0, 0, self.width(), self.height())
        painter.setBrush(QtCore.Qt.blue)
        painter.drawEllipse(self.cursorRect())

    def boundedCursor(self, position):
        def bound(low, high, value):
            return max(low, min(high, value))
        x = bound(10, self.width() - 10, position.x())
        y = bound(10, self.height() - 10, position.y())
        return QtCore.QPointF(x, y)

    def cursorRect(self):
        return QtCore.QRectF(-5, -5, 10, 10).translated(self.cursorPosition)

    def mousePressEvent(self, ev):
        self.grabCursor = self.cursorRect().contains(ev.pos())
        return super().mousePressEvent(ev)

    def mouseReleaseEvent(self, event):
        self.grabCursor = False
        self.update()

    def mouseMoveEvent(self, event):
        if self.grabCursor:
            print("Moving")
            self.cursorPosition = self.boundedCursor(event.pos())
            self.update()
        print(self.valueX(), self.valueY())

if __name__ == '__main__':
    # Create main application window
    app = QApplication([])
    joystick = Joystick()
    joystick.show()
    sys.exit(app.exec_())
0 голосов
/ 06 июля 2019

Основываясь на ответе , который дал Ромха Корев, я сделал вариант.

Этот пример позволяет устанавливать различные параметры и может отслеживать положение мыши, любые данные и ограничения, которые у вас есть.,Он не учитывает фиксированный размер / диапазон виджетов (по крайней мере, в моих тестах), но все равно адаптируется в соответствии с размером виджета.

class Bubble(QtWidgets.QWidget):
    xChanged = QtCore.pyqtSignal(int)
    yChanged = QtCore.pyqtSignal(int)
    valuesChanged = QtCore.pyqtSignal(int, int)
    moving = False

    def __init__(self, minX=0, maxX=100, minY=0, maxY=100, cursorSize=10):
        QtWidgets.QWidget.__init__(self)
        self.margin = 10
        self.setContentsMargins(0, 0, 0, 0)
        self.minX = minX
        self.minY = minY
        self.maxX = maxX
        self.maxY = maxY
        self.extentX = abs(maxX - minX)
        self.extentY = abs(maxY - minY)
        self.setMinimumSize(self.extentX + self.margin * 2, self.extentY + self.margin * 2)
        self.cursorSize = cursorSize
        self.halfCursorSize = cursorSize * .5
        self.cursorColor = QtGui.QColor(0, 174, 239)
        self.movingCursorColor = QtGui.QColor(120, 124, 205)
        self.cursorRect = QtCore.QRectF(-self.halfCursorSize, -self.halfCursorSize, cursorSize, cursorSize)
        self.cursorX = self.minX + self.extentX * .5
        self.cursorY = self.minY + self.extentY * .5
        self.trackAnywhere = True

    def visualPos(self):
        # convert values to visual coordinates
        return QtCore.QPointF(self.margin + self.halfCursorSize + ((self.cursorX - self.minX) / self.extentX) * (self.width() - self.margin * 2 - self.cursorSize), 
            self.margin + self.halfCursorSize + ((self.cursorY - self.minY) / self.extentY) * (self.height() - self.margin * 2 - self.cursorSize))

    def realX(self, visualX):
        visualExtent = self.width() - self.margin * 2 - self.cursorSize
        realX = max(0, min(float(visualX - self.margin - self.halfCursorSize) / visualExtent, 1.)) * self.extentX
        return self.minX + realX

    def realY(self, visualY):
        visualExtent = self.height() - self.margin * 2 - self.cursorSize
        realY = max(0., min(float(visualY - self.margin - self.halfCursorSize) / visualExtent, 1.)) * self.extentY
        return self.minY + realY

    def realValues(self, pos):
        return self.realX(pos.x()), self.realY(pos.y())

    def mousePressEvent(self, event):
        pos = event.pos()
        visualPos = self.visualPos()
        if self.trackAnywhere:
            self.moving = True
            if pos in self.cursorRect.translated(visualPos):
                self.mouseDelta = visualPos - event.pos()
            else:
                self.mouseDelta = QtCore.QPoint()
        elif pos in self.cursorRect.translated(visualPos):
            self.moving = True
            self.mouseDelta = visualPos - event.pos()
        else:
            self.moving = False
        self.update()

    def mouseMoveEvent(self, event):
        if self.moving:
            self.cursorX = self.realX(event.x() + self.mouseDelta.x())
            self.cursorY = self.realY(event.y() + self.mouseDelta.y())
            self.xChanged.emit(self.cursorX)
            self.yChanged.emit(self.cursorY)
            self.valuesChanged.emit(self.cursorX, self.cursorY)
            self.update()

    def mouseReleaseEvent(self, event):
        self.moving = False
        self.update()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setRenderHints(qp.Antialiasing)
        # *** unnecessary, but it could be useful to show the visible range
        qp.save()
        qp.translate(.5, .5)
        qp.drawRoundedRect(self.rect().adjusted(self.margin - 1, self.margin - 1, -self.margin, -self.margin), 2, 2)
        qp.restore()
        # comment the lines from the *** to this point, if not interested in the visual range
        qp.setPen(QtCore.Qt.NoPen)
        if self.moving:
            qp.setBrush(self.movingCursorColor)
        else:
            qp.setBrush(self.cursorColor)
        qp.drawEllipse(self.cursorRect.translated(self.visualPos()))

Одним из многих преимуществ этого решения является то, что он можетСледите за тем, где нажимается «ползунок», при этом сохраняя согласованность.
Обратите внимание, что realX, realY и realValues являются числами с плавающей точкой, и они автоматически преобразуются в int в сигнале, поскольку их объявления используют этотип объекта.

...