0

I have cards in my scene. For example in this code i tried to move my ManikenCard object to another position, but can't do this, because my moving methods don't respond to my clicks (i add "print" to this methods ).I noticed, that i can click on my Card and it raise MausePressEvent , and it say that only my drag-and-drop system doesn't work . How can i move my cards on the field. I read this article Drag n Drop inside QgraphicsView doesn't work (PyQt) with the similar problem, but can't do this in my own program .

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 Answers1

1

If you call the base class mousePressEvent() on a widget that normally doesn't deal with mouse interactions (such as a QLabel), the event will be intercepted by the widget parent(s) until it's dealt with.
In this case there is no parent, but there's the graphics scene, which will "eat" all mouse events from that moment on.

def mousePressEvent(self, e):

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

    if e.button() == QtCore.Qt.LeftButton:
        print('press')
musicamante
  • 41,230
  • 6
  • 33
  • 58