1. 程式人生 > 實用技巧 >QGraphicsView實現虛擬搖桿

QGraphicsView實現虛擬搖桿

效果如下:

# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.Qt import Qt
from PyQt5.QtCore import pyqtSignal, pyqtSlot


class CustomButtonView(QtWidgets.QGraphicsView):
    MousePress = pyqtSignal()
    MouseMove = pyqtSignal(QtCore.QPoint)
    MouseRelease = pyqtSignal()

    # ==========================利用訊號傳遞事件==========================
    def mousePressEvent(self, QMouseEvent):
        if QMouseEvent.button() == Qt.LeftButton:
            self.MousePress.emit()
        super(CustomButtonView, self).mousePressEvent(QMouseEvent)

    def mouseReleaseEvent(self, QMouseEvent):
        self.MouseRelease.emit()
        super(CustomButtonView, self).mouseReleaseEvent(QMouseEvent)

    def mouseMoveEvent(self, QMouseEvent):
        self.MouseMove.emit(QMouseEvent.pos())
        super(CustomButtonView, self).mouseMoveEvent(QMouseEvent)


class ControlButton(QtWidgets.QWidget):
    Go_Direction = pyqtSignal(str)
    End_Action = pyqtSignal()

    def __init__(self, parent=None):
        super(ControlButton, self).__init__(parent, flags=Qt.Widget)

        self.is_move = False
        self.NoPen = QtGui.QPen(Qt.NoPen)
        self.W_H = 300
        self.brush_1 = QtGui.QBrush(Qt.white)
        self.brush_2 = QtGui.QBrush(QtGui.QColor(52, 160, 220))

        self.__initView()
        self.__initButton()
        self.__initSignal()

    # ==========================初始化==========================
    def __initView(self):
        # 初始化檢視
        self.view = CustomButtonView(self)
        self.view.resize(self.W_H, self.W_H)
        # self.setCentralWidget(self.view)
        self.view.setAlignment(Qt.AlignCenter)
        self.view.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
        self.view.setMouseTracking(True)
        self.scene = QtWidgets.QGraphicsScene(QtCore.QRectF(-self.W_H / 2, -self.W_H / 2, self.W_H, self.W_H))
        self.view.setScene(self.scene)

    def __initButton(self):
        # 最外圍的圓
        ___ = QtWidgets.QGraphicsEllipseItem(-self.W_H / 2, -self.W_H / 2, self.W_H, self.W_H)
        ___.setPen(self.NoPen)
        brush = QtGui.QLinearGradient(0, -self.W_H / 2, 0, self.W_H / 2)
        brush.setColorAt(0, QtGui.QColor(74, 68, 68))
        brush.setColorAt(1, QtGui.QColor(158, 156, 156))
        ___.setBrush(brush)
        self.scene.addItem(___)
        # 第二個大圓
        ___ = QtWidgets.QGraphicsEllipseItem(-self.W_H / 2 + 5, -self.W_H / 2 + 5, self.W_H - 10, self.W_H - 10)
        ___.setPen(self.NoPen)
        brush = QtGui.QRadialGradient(0, 0, self.W_H / 2 - 5, 0, 0)
        brush.setColorAt(0, QtGui.QColor(110, 110, 110))
        brush.setColorAt(0.8, QtGui.QColor(35, 35, 35))
        brush.setColorAt(1, QtGui.QColor(14, 14, 14))
        ___.setBrush(brush)
        self.scene.addItem(___)
        # 最裡面的圓
        ___ = QtWidgets.QGraphicsEllipseItem(-(self.W_H / 6 + 5), -(self.W_H / 6 + 5), self.W_H / 3 + 10,
                                             self.W_H / 3 + 10)
        ___.setPen(self.NoPen)
        brush = QtGui.QRadialGradient(0, 0, self.W_H / 6 + 5, 0, 0)
        brush.setColorAt(0, QtGui.QColor(95, 95, 95))
        brush.setColorAt(1, QtGui.QColor(45, 45, 45))
        ___.setBrush(brush)
        self.scene.addItem(___)
        # 四條線
        pen_1 = QtGui.QPen()
        pen_1.setWidth(5)
        pen_1.setCapStyle(Qt.RoundCap)
        pen_1.setColor(QtGui.QColor(52, 160, 220))

        pen_2 = QtGui.QPen()
        pen_2.setWidth(5)
        pen_2.setColor(QtGui.QColor(10, 10, 10))
        angle = 45
        for i in range(4):
            ___ = QtWidgets.QGraphicsLineItem(self.W_H / 6 + 5, 0, self.W_H / 2 - 10, 0)
            ___.setPen(pen_1)
            ___.setRotation(angle)
            self.scene.addItem(___)
            ___ = QtWidgets.QGraphicsLineItem(self.W_H / 2 - 10, 0, self.W_H / 2 - 5, 0)
            ___.setPen(pen_2)
            ___.setRotation(angle)
            self.scene.addItem(___)
            angle += 90

        # 上下左右
        x = self.W_H / 3
        x_ = x + self.W_H / 15
        y = self.W_H / 30
        self.right = QtWidgets.QGraphicsPolygonItem()
        self.right.setPolygon(QtGui.QPolygonF([QtCore.QPoint(x, -y), QtCore.QPoint(x, y), QtCore.QPoint(x_, 0)]))
        self.right.setPen(self.NoPen)
        self.right.setBrush(self.brush_1)
        self.scene.addItem(self.right)

        self.down = QtWidgets.QGraphicsPolygonItem()
        self.down.setPolygon(QtGui.QPolygonF([QtCore.QPoint(x, -y), QtCore.QPoint(x, y), QtCore.QPoint(x_, 0)]))
        self.down.setPen(self.NoPen)
        self.down.setBrush(self.brush_1)
        self.down.setRotation(90)
        self.scene.addItem(self.down)

        self.left = QtWidgets.QGraphicsPolygonItem()
        self.left.setPolygon(QtGui.QPolygonF([QtCore.QPoint(x, -y), QtCore.QPoint(x, y), QtCore.QPoint(x_, 0)]))
        self.left.setPen(self.NoPen)
        self.left.setBrush(self.brush_1)
        self.left.setRotation(180)
        self.scene.addItem(self.left)

        self.up = QtWidgets.QGraphicsPolygonItem()
        self.up.setPolygon(QtGui.QPolygonF([QtCore.QPoint(x, -y), QtCore.QPoint(x, y), QtCore.QPoint(x_, 0)]))
        self.up.setPen(self.NoPen)
        self.up.setBrush(self.brush_1)
        self.up.setRotation(-90)
        self.scene.addItem(self.up)

        # 中心的可拖拽按鈕
        self.button = QtWidgets.QGraphicsEllipseItem(-self.W_H / 6, -self.W_H / 6, self.W_H / 3, self.W_H / 3)
        self.button.setPen(self.NoPen)
        brush = QtGui.QRadialGradient(0, 0, self.W_H / 6, 0, 0)
        brush.setColorAt(0, QtGui.QColor(80, 80, 80))
        brush.setColorAt(0.5, QtGui.QColor(40, 40, 40))
        brush.setColorAt(1, QtGui.QColor(15, 15, 15))
        self.button.setBrush(brush)
        self.scene.addItem(self.button)

    def __initSignal(self):
        # 初始化訊號槽
        self.view.MouseRelease.connect(self.do_mouseReleaseEvent)
        self.view.MousePress.connect(self.do_mousePressEvent)
        self.view.MouseMove.connect(self.do_mouseMoveEvent)

    # ==========================事件處理==========================
    def do_mouseReleaseEvent(self):
        self.End_Action.emit()
        self.is_move = False
        self.button.setPos(0, 0)
        brush_1 = QtGui.QBrush(Qt.white)
        self.right.setBrush(brush_1)
        self.left.setBrush(brush_1)
        self.up.setBrush(brush_1)
        self.down.setBrush(brush_1)

    def do_mousePressEvent(self):
        self.is_move = True

    @pyqtSlot(QtCore.QPoint, name="do_mouseMoveEvent")
    def do_mouseMoveEvent(self, point):
        if self.is_move:
            pt = self.view.mapToScene(point)
            x = pt.x()
            y = pt.y()

            max_ = self.W_H / 3 + self.W_H / 6 / 2
            min_ = self.W_H / 10
            if abs(x) > abs(y):
                y = 0
            else:
                x = 0
            if abs(x) >= max_:
                x = max_ * x / abs(x)
            if abs(y) >= max_:
                y = max_ * y / abs(y)
            if x > min_:
                self.right.setBrush(self.brush_2)
                self.left.setBrush(self.brush_1)
                self.up.setBrush(self.brush_1)
                self.down.setBrush(self.brush_1)
                self.Go_Direction.emit("right")
            elif x < -min_:
                self.right.setBrush(self.brush_1)
                self.left.setBrush(self.brush_2)
                self.up.setBrush(self.brush_1)
                self.down.setBrush(self.brush_1)
                self.Go_Direction.emit("left")
            elif y > min_:
                self.right.setBrush(self.brush_1)
                self.left.setBrush(self.brush_1)
                self.up.setBrush(self.brush_1)
                self.down.setBrush(self.brush_2)
                self.Go_Direction.emit("down")
            elif y < -min_:
                self.right.setBrush(self.brush_1)
                self.left.setBrush(self.brush_1)
                self.up.setBrush(self.brush_2)
                self.down.setBrush(self.brush_1)
                self.Go_Direction.emit("up")
            else:
                self.right.setBrush(self.brush_1)
                self.left.setBrush(self.brush_1)
                self.up.setBrush(self.brush_1)
                self.down.setBrush(self.brush_1)

            self.button.setPos(x, y)

    def resizeEvent(self, event):
        # 自適配介面
        if self.width() > self.height():
            self.W_H = self.height() - 50
        else:
            self.W_H = self.width() - 50
        self.view.resize(self.width(), self.height())
        self.scene.setSceneRect(QtCore.QRectF(-self.W_H / 2, -self.W_H / 2, self.W_H, self.W_H))
        self.scene.clear()
        self.__initButton()


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    button = ControlButton()
    button.show()
    sys.exit(app.exec_())