Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 26, 2019 01:40:28

Holzer
Зарегистрирован: 2019-12-26
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Пытаюсь разобраться с 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_())

Отредактировано Holzer (Дек. 26, 2019 01:41:52)

Офлайн

#2 Дек. 26, 2019 20:38:34

rami
Зарегистрирован: 2018-01-08
Сообщения: 281
Репутация: +  72  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Holzer
Я так понял, что виджет не перемещается , если он определен в другом классе, а не в том, где вызывается метод перемещения.
Нет, виджет не перемещается потому, что вы не передаёте ему новую позицию.

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

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

В соответствии с выше сказанным исправить и дополнить код необходимыми данными. Если не получится, могу выложить свой код.

Отредактировано rami (Дек. 26, 2019 22:28:10)

Офлайн

#3 Дек. 26, 2019 23:48:05

Holzer
Зарегистрирован: 2019-12-26
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Действительно, заменив self.but на event.source(), разрешило проблему с вылетом, а вот как поменять родителя не нашел. event.source.setParent(example2) опять же вызывает вылет. Видимо из-за example2, на что это надо заменить, чтобы он понимал? Или я неправильно понимаю?

Офлайн

#4 Дек. 27, 2019 12:25:28

rami
Зарегистрирован: 2018-01-08
Сообщения: 281
Репутация: +  72  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Вы должны понимать в каждый момент выполнения кода где вы находитесь, чтобы узнать какие объекты и методы вам доступны в данный момент. Когда вы захватываете объект (кнопку) вы находитесь в классе Example(), один из экземпляров которого (example1) является родителем объекта. Когда вы тянете кнопку по левому фрейму (example1) переменная self ссылается на него, но когда вы заходите на территорию правого фрейма, переменная self ссылается на example2. Поэтому нужно назначать родителем перетягиваемого объекта self (в классе Example(), в функции dropEvent()). Должно быть event.source().setParent(self) (в начале функции).

Офлайн

#5 Дек. 27, 2019 13:01:27

Holzer
Зарегистрирован: 2019-12-26
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Неожиданно…. просто, а то я что туда только не подставлял, искал в библиотеках pyqt5 и qt. Считал, что там должно быть чтото вроде таргета или чтото в этом роде. Спасибо за разьяснение self, а то я несколько иначе его представлял. Но вот почему обьект Button пропадает из первого виджета после перемещения, но не появляется во втором?

Офлайн

#6 Дек. 27, 2019 13:46:52

rami
Зарегистрирован: 2018-01-08
Сообщения: 281
Репутация: +  72  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Появляется, только он после смены родителя становится не видимым, нужно включить видимость: e.source().setVisible(True)

Офлайн

#7 Дек. 27, 2019 14:36:11

Holzer
Зарегистрирован: 2019-12-26
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Сразу попробовал применить show к source, но соответственно ничего не появилось. А оказалось отдельная команда для этого существует. Искал в документации питона и ничего такого там не нашел. Можете подсказать какую-то базу с перечнем всего имеющегося?
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?

Отредактировано Holzer (Дек. 27, 2019 14:39:13)

Офлайн

#8 Дек. 27, 2019 14:59:48

rami
Зарегистрирован: 2018-01-08
Сообщения: 281
Репутация: +  72  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

Holzer
Можете подсказать какую-то базу с перечнем всего имеющегося?
В любом нормальном редакторе для Python есть подсказки. Всегда можно пользоваться функциями help() или dir().

Holzer
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?
До сих пор речь шла о том, как переместить виджет, а не зачем это нужно. Чтобы узнать что лучше вы должны попробовать разные варианты.

Офлайн

#9 Дек. 27, 2019 18:28:07

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Помогите разобраться с DragDrop

rami
dir()
… и __dict__



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

есчщо

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version