Форум сайта python.su
0
Пытаюсь разобраться с 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)
Офлайн
72
HolzerНет, виджет не перемещается потому, что вы не передаёте ему новую позицию.
Я так понял, что виджет не перемещается , если он определен в другом классе, а не в том, где вызывается метод перемещения.
HolzerКогда вы тащите объект, происходит событие которое “знает” какой объект перемещается. В функции dropEvent вместо не правильного self.but.move(position) написать event.source().move(event.pos() - QPoint(x, y)) (QPoint(x, y) — это поправка на положение курсора, которое нужно определить)
Можно ли как-то вызывать перемещение обьекта(but) в классе, где его нет(class Example), из другого класса, в котором он и создается(class MainW)? Ну и главное как сделать так, чтобы можно было переместить обьект из одного виджета в другой?
Отредактировано rami (Дек. 26, 2019 22:28:10)
Офлайн
0
Действительно, заменив self.but на event.source(), разрешило проблему с вылетом, а вот как поменять родителя не нашел. event.source.setParent(example2) опять же вызывает вылет. Видимо из-за example2, на что это надо заменить, чтобы он понимал? Или я неправильно понимаю?
Офлайн
72
Вы должны понимать в каждый момент выполнения кода где вы находитесь, чтобы узнать какие объекты и методы вам доступны в данный момент. Когда вы захватываете объект (кнопку) вы находитесь в классе Example(), один из экземпляров которого (example1) является родителем объекта. Когда вы тянете кнопку по левому фрейму (example1) переменная self ссылается на него, но когда вы заходите на территорию правого фрейма, переменная self ссылается на example2. Поэтому нужно назначать родителем перетягиваемого объекта self (в классе Example(), в функции dropEvent()). Должно быть event.source().setParent(self) (в начале функции).
Офлайн
0
Неожиданно…. просто, а то я что туда только не подставлял, искал в библиотеках pyqt5 и qt. Считал, что там должно быть чтото вроде таргета или чтото в этом роде. Спасибо за разьяснение self, а то я несколько иначе его представлял. Но вот почему обьект Button пропадает из первого виджета после перемещения, но не появляется во втором?
Офлайн
72
Появляется, только он после смены родителя становится не видимым, нужно включить видимость: e.source().setVisible(True)
Офлайн
0
Сразу попробовал применить show к source, но соответственно ничего не появилось. А оказалось отдельная команда для этого существует. Искал в документации питона и ничего такого там не нашел. Можете подсказать какую-то базу с перечнем всего имеющегося?
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?
Отредактировано Holzer (Дек. 27, 2019 14:39:13)
Офлайн
72
HolzerВ любом нормальном редакторе для Python есть подсказки. Всегда можно пользоваться функциями help() или dir().
Можете подсказать какую-то базу с перечнем всего имеющегося?
HolzerДо сих пор речь шла о том, как переместить виджет, а не зачем это нужно. Чтобы узнать что лучше вы должны попробовать разные варианты.
И еще читал что лучше не перемещать виджет. а использовать QStackedWidget это действительно лучше для подобного рода задач?
Офлайн
44
rami… и __dict__
dir()
и вставьте ссылку на его url Офлайн