Не могу использовать технологию перетаскивания в PyQt5 Scene - PullRequest
0 голосов

У меня есть карты на моей сцене. Например, в этом коде я пытался переместить мой объект ManikenCard в другую позицию, но не могу этого сделать, потому что мои методы перемещения не реагируют на мои щелчки (я добавляю «print» к этим методам). Я заметил, что я Я могу щелкнуть мою Карту, и она вызовет MausePressEvent, и там будет сказано, что не работает только моя система перетаскивания. Как я могу переместить мои карты на поле. Я прочитал эту статью Drag n Drop внутри QgraphicsView не работает (PyQt) с подобной проблемой, но не могу сделать это в моей собственной программе.

from PyQt5 import QtCore, QtGui, QtWidgets

import os,random


class PyramideCard(QtWidgets.QLabel):

    card_suits = ['♠', '♥', '♦', '♣']
    card_ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'B', 'D', 'K']
    card_values = {rank: value for value, rank in enumerate(card_ranks, 1)}

    def __init__(self,rank,suit):
        #----------------Backend_data---------------------
        self.__suit = suit
        self.__rank = rank
        self.__value = PyramideCard.card_values[rank]
        # ----------------State-------------------------
        self.active = False  # back_ground_phone
        self.visible = False
        #----------------Visual_parameters----------------
        self.__img_back = os.path.join(r"C:\Users\user\Desktop\ооп\Programs\Pyramide\Cards_100_150\purple_back")
        QtWidgets.QLabel.__init__(self)
        self.setGeometry(QtCore.QRect(0, 0, 100, 150))
        self.setObjectName(self.__rank + self.__suit)
        self.__img = os.path.join(r"C:\Users\user\Desktop\ооп\Programs\Pyramide\Cards_100_150", self.__rank +
                                  self.__suit)
        self.setPixmap_()
        self.ScaledContents=True
        #----------------drag_drop----------------
        self.setAcceptDrops(True)

    def setPixmap_(self):
        if self.visible :
            self.setPixmap(QtGui.QPixmap(self.__img))
        else :
            self.setPixmap(QtGui.QPixmap(self.__img_back))

    def change_visible(self):
        if self.visible :
            self.visible = False
            self.setPixmap_()
        else :
            self.visible = True
            self.setPixmap_()

    def change_active_state(self):
        if self.active :
            self.active = False
        else :
            self.active = True

    def __add__(self, other):
        return self.value + other.value

class MinikenCard(QtWidgets.QLabel):
    #signalChangeDeckCard = QtCore.pyqtSignal()
    def __init__(self):

        # ----------------Visual_parameters----------------
        QtWidgets.QLabel.__init__(self)
        self.setGeometry(QtCore.QRect(0, 0, 100, 150))
        self.setObjectName("DeckCard")
        self.__img = os.path.join(r"C:\Users\user\Desktop\ооп\Programs\Pyramide\Cards_100_150\purple_back")
        self.setPixmap(QtGui.QPixmap(self.__img))
        self.ScaledContents = True

        self.setAcceptDrops(True)

    def mouseMoveEvent(self, e):
        """PROBLEM IS HERE """
        print("Moving")

        if e.buttons() != QtCore.Qt.RightButton:
            return

        mimeData = QMimeData()

        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())

        dropAction = drag.exec_(Qt.MoveAction)

    def mousePressEvent(self, e):

        QtWidgets.QLabel.mousePressEvent(self, e)

        if e.button() == QtCore.Qt.LeftButton:
            print('press')

class PyramideCardsCreator() :
    '''create cards fpr Pyramide game'''
    def create_cards_for_game(self) -> list :
        '''
        :return: list of all the game cards
        '''
        suits = PyramideCard.card_suits
        ranks = PyramideCard.card_ranks

        return [ PyramideCard(rank,suit)
                    for suit in suits
                        for rank in ranks ]

    def optional_components(self):
        '''
        :return: tuple(deck_cards,playing_layers-cards in the field)
        '''
        cards = self.create_cards_for_game()
        random.shuffle(cards)

        playing_cards = cards[:28]
        deck_cards = cards[28:]

        return deck_cards,self.createPiramideCardsLayers(playing_cards)

    def createPiramideCardsLayers(self,cards):
        '''
        emit from optional_components
        :param cards: all cards in the game
        :return: list of card in the field : [[0],[0,1]..[0,1,2,4,5]]
        '''
        f = 0
        playing_layers = []
        for layer in range(6, -1, -1):
            playing_layers.append(cards[f:f + layer + 1])
            f += layer + 1
        return playing_layers

class PyramideScene(QtWidgets.QGraphicsScene):

    def __init__(self):
        QtWidgets.QGraphicsScene.__init__(self)
        #------------------------scene_parameters----------------------
        self.setBackgroundBrush(QtGui.QColor(92,117,97,alpha = 255))
        self.setSceneRect(0, 150, 995, 650)
        self.addRect(self.sceneRect())
        #------------------------adding_cards_to_the_field-------------
        self.deck_cards, self.pyramide_layers = PyramideCardsCreator().optional_components()
        self.cards_to_the_deck()

        maniken_obj=MinikenCard()
        self.maniken_card=self.addWidget(maniken_obj)
        self.maniken_card.setPos(30,200)
        #maniken_obj.signalChangeDeckCard.connect(self.ChangeDeckCard)
        # ----------------------------------------------------

    @QtCore.pyqtSlot()
    def ChangeDeckCard(self):
        print("ChangeCardDeck")

    def dragEnterEvent(self, e):
        "PROBLEM IS HERE "
        print('dragEnterEvent')
        e.accept()

    def dropEvent(self, e):
        "PROBLEM IS HERE "
        print('dropEvent')
        position = e.pos()
        self.maniken_card.move(position)

        e.setDropAction(Qt.MoveAction)
        e.accept()


    def cards_to_the_deck(self):

        layers =self.pyramide_layers
        # make the firs layer visible
        for card in layers[0]:
            card.change_visible()
        # starter point to put card in the field
        starter_x=635
        for layer in range(len(layers),-1,-1) :
            layer_length=7-layer
            for card in range(layer_length) :

                card_in_the_field=self.addWidget(layers[layer][card])
                card_in_the_field.setPos(starter_x-(layer_length-card)*100,(layer_length+1)*80)
            starter_x+=50

class Game(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.setObjectName('MainWidget')
        self.setStyleSheet('''#MainWidget {
                        background-color: #267;
                    }''')

        # parameters QWIndowWIdget
        self.setFixedSize(1050,800 )
        self.Initialization()

    def Initialization(self):
        layout = QtWidgets.QGridLayout()
        self.setLayout(layout)
        self.PyramideView = QtWidgets.QGraphicsView()
        self.PyramideView.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
        layout.addWidget(self.PyramideView)
        self.PyramideScene = PyramideScene()
        self.PyramideView.setScene(self.PyramideScene)
        #parameters PyramideView
        self.PyramideView.setFixedSize(1000, 655)
        self.PyramideView.setRenderHints(QtGui.QPainter.Antialiasing)

        self.setAcceptDrops(True)




def main():
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Pyramide = Game()
    Pyramide.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

1 Ответ

1 голос
/ 25 марта 2020

Если вы вызываете базовый класс mousePressEvent() для виджета, который обычно не связан с взаимодействиями с мышью (например, QLabel), событие будет перехватываться родительским (и) виджетом до тех пор, пока оно не будет обработано.
В этом случае нет родителя, , но есть графическая сцена, которая "съест" все события мыши с этого момента.

def mousePressEvent(self, e):

    # remove this line:
    QtWidgets.QLabel.mousePressEvent(self, e)

    if e.button() == QtCore.Qt.LeftButton:
        print('press')
...