Найти - Пользователи
Полная версия: Помогите разобраться с DragDrop
Начало » Python для новичков » Помогите разобраться с DragDrop
1
Holzer
Пытаюсь разобраться с DragDrop на основе простейшего примера. Хочу сделать перемещение виджета из одного в другой, но все обрывается в момент перемещениям даже в 1 виджете. Я так понял, что виджет не перемещается , если он определен в другом классе, а не в том, где вызывается метод перемещения. Можно ли как-то вызывать перемещение обьекта(but) в классе, где его нет(class Example), из другого класса, в котором он и создается(class MainW)? Ну и главное как сделать так, чтобы можно было переместить обьект из одного виджета в другой?

 import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QApplication, QMainWindow, QFrame, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt, QMimeData, QPoint
from PyQt5.QtGui import QDrag, QColor, QPixmap
class MainW (QMainWindow):
    def __init__(self, parent=None):
        super(MainW, self).__init__(parent)
        self.setupWidgets()
        self.setToolTip('self')
        self.setWindowTitle('Click or Move')
        self.setGeometry(300, 300, 800, 600)
        
    def setupWidgets(self):
        
        self.frame = QFrame()
        frameLayout = QHBoxLayout(self.frame)
        
        self.setCentralWidget(self.frame)
        
        self.example1 = Example()
        self.example2 = Example()
        
        frameLayout.addWidget(self.example1)
        frameLayout.addWidget(self.example2)
        frameL = QVBoxLayout(self.frame)
        frameL.addLayout (frameLayout)
        #Создаю перемещаемую рамку в одной из принимающих рамок 
        self.but = Button(self.example1)
        
        self.frame.setStyleSheet("QFrame{border-style: outset;border-width: 2px;border-color: black;Background-color: rgb(255,247,191);color: black;}")
        #self.setAcceptDrops(True)
# Класс предназначенный для приема перемещаемой рамки
class Example(QFrame):
    def __init__(self):
        super(Example, self).__init__()
        self.setAcceptDrops(True)
        self.setMinimumSize(200, 200)
        self.setMaximumSize(200, 200)
        self.setStyleSheet("QWidget{border-style: outset;border-width: 2px;border-color: black;Background-color: rgb(255,247,191);color: black;}")
        
        
  
    def dragEnterEvent(self, e):
        e.accept()
    def dropEvent(self, event):
      
        position = event.pos()
        print ('dropEvent', position)
        mimeData = event.mimeData()
        
        print ('dropEvent', event)
        # Перемещение закрывает окно
        self.but.move(position)
        event.setDropAction(Qt.MoveAction)
        
        print ('dropEvent', mimeData)
        event.accept()            
    
# Класс перемещаемой рамки
class Button(QFrame):
    def __init__(self, parent=None):
        super(Button, self).__init__(parent)
        self.setMinimumSize(50, 40)
        self.setMaximumSize(50, 40)
        self.setStyleSheet("QWidget{border-style: outset;border-width: 2px;border-color: black;Background-color: rgb(255,247,191);color: black;}")
        
    def mouseMoveEvent(self, e):
        if e.buttons() != Qt.RightButton:
            return
        
        mimeData = QMimeData()
        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())
        
        dropAction = drag.exec_(Qt.MoveAction)
        print('rrr', dropAction)
    def mousePressEvent(self, e):
        QFrame.mousePressEvent(self, e)
        if e.button() == Qt.LeftButton:
            print('press')
            
    
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainW()
    window.show()
    sys.exit(app.exec_())
rami
Holzer
Я так понял, что виджет не перемещается , если он определен в другом классе, а не в том, где вызывается метод перемещения.
Нет, виджет не перемещается потому, что вы не передаёте ему новую позицию.

Holzer
Можно ли как-то вызывать перемещение обьекта(but) в классе, где его нет(class Example), из другого класса, в котором он и создается(class MainW)? Ну и главное как сделать так, чтобы можно было переместить обьект из одного виджета в другой?
Когда вы тащите объект, происходит событие которое “знает” какой объект перемещается. В функции dropEvent вместо не правильного self.but.move(position) написать event.source().move(event.pos() - QPoint(x, y)) (QPoint(x, y) — это поправка на положение курсора, которое нужно определить)

У перемещаемого объекта есть родитель (левый фрейм), чтобы объект переместился в правый фрейм, нужно переназначить родителем объекта правый фрейм.

В соответствии с выше сказанным исправить и дополнить код необходимыми данными. Если не получится, могу выложить свой код.
Holzer
Действительно, заменив self.but на event.source(), разрешило проблему с вылетом, а вот как поменять родителя не нашел. event.source.setParent(example2) опять же вызывает вылет. Видимо из-за example2, на что это надо заменить, чтобы он понимал? Или я неправильно понимаю?
rami
Вы должны понимать в каждый момент выполнения кода где вы находитесь, чтобы узнать какие объекты и методы вам доступны в данный момент. Когда вы захватываете объект (кнопку) вы находитесь в классе Example(), один из экземпляров которого (example1) является родителем объекта. Когда вы тянете кнопку по левому фрейму (example1) переменная self ссылается на него, но когда вы заходите на территорию правого фрейма, переменная self ссылается на example2. Поэтому нужно назначать родителем перетягиваемого объекта self (в классе Example(), в функции dropEvent()). Должно быть event.source().setParent(self) (в начале функции).
Holzer
Неожиданно…. просто, а то я что туда только не подставлял, искал в библиотеках pyqt5 и qt. Считал, что там должно быть чтото вроде таргета или чтото в этом роде. Спасибо за разьяснение self, а то я несколько иначе его представлял. Но вот почему обьект Button пропадает из первого виджета после перемещения, но не появляется во втором?
rami
Появляется, только он после смены родителя становится не видимым, нужно включить видимость: e.source().setVisible(True)
Holzer
Сразу попробовал применить show к source, но соответственно ничего не появилось. А оказалось отдельная команда для этого существует. Искал в документации питона и ничего такого там не нашел. Можете подсказать какую-то базу с перечнем всего имеющегося?
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?
rami
Holzer
Можете подсказать какую-то базу с перечнем всего имеющегося?
В любом нормальном редакторе для Python есть подсказки. Всегда можно пользоваться функциями help() или dir().

Holzer
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?
До сих пор речь шла о том, как переместить виджет, а не зачем это нужно. Чтобы узнать что лучше вы должны попробовать разные варианты.
AD0DE412
rami
dir()
… и __dict__
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB