2013-03-25 458 views
1

我需要能够在背景图像顶部的屏幕上显示控件。我已经完成了该任务,并且已经创建并显示了一个控件(一个显示图像的QLabel)。现在我需要能够通过将标签拖动到我想要移动它的位置来移动标签,我已经遵循了几个关于在pyqt中进行拖放的教程,但是我未能完成此任务在QFrame中移动(拖动)QLabel

这是我的代码。请注意,控件可以移动,但是当您移动它时,背景也会移动,当您放下它时,它会保持原位。我要的是只移动(在QLabel显示图像)的控制和移动它只是拖动标签内:

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

class CentralWidget(QFrame): 
    def __init__(self, *args): 
    super(CentralWidget, self).__init__(*args) 
    self.setStyleSheet("background-image: url(logo.png);") 
    self.setAcceptDrops(True) 

    def dragEnterEvent(self, e): 
     e.accept() 

    def dropEvent(self, e): 
     # get the relative position from the mime data 
     mime = e.mimeData().text() 
     x, y = map(int, mime.split(',')) 
     # move 
     # so move the dragged button (i.e. event.source()) 
     e.source().move(e.pos()-QPoint(x, y)) 
     # set the drop action as Move 
     e.setDropAction(Qt.MoveAction) 
     # tell the QDrag we accepted it 
     e.accept() 

class Selector(QLabel): 
    def mouseMoveEvent(self, e): 
     if e.buttons() != Qt.LeftButton: 
      return 

     # write the relative cursor position to mime data 
     mimeData = QMimeData() 
     # simple string with 'x,y' 
     mimeData.setText('%d,%d' % (e.x(), e.y())) 

     # let's make it fancy. we'll show a "ghost" of the button as we drag 
     # grab the button to a pixmap 
     pixmap = QPixmap.grabWidget(self) 

     # below makes the pixmap half transparent 
     painter = QPainter(pixmap) 
     painter.setCompositionMode(painter.CompositionMode_DestinationIn) 
     painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127)) 
     painter.end() 

     # make a QDrag 
     drag = QDrag(self) 
     # put our MimeData 
     drag.setMimeData(mimeData) 
     # set its Pixmap 
     drag.setPixmap(pixmap) 
     # shift the Pixmap so that it coincides with the cursor position 
     drag.setHotSpot(e.pos()) 

     # start the drag operation 
     # exec_ will return the accepted action from dropEvent 
     if drag.exec_(Qt.MoveAction) == Qt.MoveAction: 
      print 'moved' 
     # else: 
      # print 'copied' 

    def mousePressEvent(self, e): 
     QLabel.mousePressEvent(self,e) 
     if e.button() == Qt.LeftButton: 
      print 'press' 


class fPrincipal(QMainWindow): 
    def __init__(self, parent=None): 
    # Call base class constructor 
    QMainWindow.__init__(self, parent) 

    self.setGeometry(QRect(0, 0, 599+10, 399+10)) 
    self.move(QDesktopWidget().availableGeometry().center() - self.frameGeometry().center()) 

    # Creamos el contenedor central, que sera organizado por pestañas 
    centralWidget = QTabWidget() 
    self.setCentralWidget(centralWidget); 

    # Creamos la 1ra pestaña 
    tab = CentralWidget() 

    tabLayout = QHBoxLayout() 
    tab.setLayout(tabLayout) 

    # Añadimos la pestaña al contenedor central 
    centralWidget.addTab(tab,"Escena 1") 

    logDockWidget = QDockWidget("Tools", self) 
    logDockWidget.setObjectName("LogDockWidget") 
    logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) 
    self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) 

    def crearMenu(): 
     mimenu = self.menuBar().addMenu("&Archivo") 

    crearMenu() 
    selectorLb = Selector() 
    picture = QPixmap('D:\Adrian\Tesis\Codigo\selector.png') 
    selectorLb.setPixmap(picture) 
    tabLayout.addWidget(selectorLb)  

if __name__ == "__main__": 
    app = QApplication(sys.argv) 

    w = fPrincipal() 
    w.show() 

    sys.exit(app.exec_()) 

回答

1

结帐的PyQt fridgemagnets example,这里是一个简化版本:

#!/usr/bin/env python 
#-*- coding:utf-8 -*- 

import sip 
sip.setapi('QString', 2) 

from PyQt4 import QtCore, QtGui 

myMimeType = 'application/MyWindow' 

class MyLabel(QtGui.QLabel): 
    def __init__(self, parent): 
     super(MyLabel, self).__init__(parent) 

     self.setStyleSheet(""" 
      background-color: black; 
      color: white; 
      font: bold; 
      padding: 6px; 
      border-width: 2px; 
      border-style: solid; 
      border-radius: 16px; 
      border-color: white; 
     """) 

    def mousePressEvent(self, event): 
     itemData = QtCore.QByteArray() 
     dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly) 
     dataStream.writeString(self.text()) 
     dataStream << QtCore.QPoint(event.pos() - self.rect().topLeft()) 

     mimeData = QtCore.QMimeData() 
     mimeData.setData(myMimeType, itemData) 
     mimeData.setText(self.text()) 

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

     self.hide() 

     if drag.exec_(QtCore.Qt.MoveAction | QtCore.Qt.CopyAction, QtCore.Qt.CopyAction) == QtCore.Qt.MoveAction: 
      self.close() 

     else: 
      self.show() 


class MyFrame(QtGui.QFrame): 
    def __init__(self, parent=None): 
     super(MyFrame, self).__init__(parent) 

     self.setStyleSheet(""" 
      background-color: lightgray; 
      border-width: 2px; 
      border-style: solid; 
      border-color: black; 
      margin: 2px; 
     """) 

     y = 6 
     for labelNumber in range(6): 
      label = MyLabel(self) 
      label.setText("Label #{0}".format(labelNumber)) 
      label.move(6, y) 
      label.show() 

      y += label.height() + 2 

     self.setAcceptDrops(True) 

    def dragEnterEvent(self, event): 
     if event.mimeData().hasFormat(myMimeType): 
      if event.source() in self.children(): 
       event.setDropAction(QtCore.Qt.MoveAction) 
       event.accept() 

      else: 
       event.acceptProposedAction() 

     else: 
      event.ignore() 

    def dropEvent(self, event): 
     if event.mimeData().hasFormat(myMimeType): 
      mime  = event.mimeData() 
      itemData = mime.data(myMimeType) 
      dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly) 

      text = QtCore.QByteArray() 
      offset = QtCore.QPoint() 
      dataStream >> text >> offset 

      newLabel = MyLabel(self) 
      newLabel.setText(event.mimeData().text()) 
      newLabel.move(event.pos() - offset) 
      newLabel.show() 

      if event.source() in self.children(): 
       event.setDropAction(QtCore.Qt.MoveAction) 
       event.accept() 

      else: 
       event.acceptProposedAction() 

     else: 
      event.ignore() 

class MyWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MyWindow, self).__init__(parent) 

     self.myFrame = MyFrame(self) 

     self.setCentralWidget(self.myFrame) 

if __name__ == "__main__": 
    import sys 

    app = QtGui.QApplication(sys.argv) 
    app.setApplicationName('MyWindow') 

    main = MyWindow() 
    main.resize(333, 333) 
    main.move(app.desktop().screen().rect().center() - main.rect().center()) 
    main.show() 

    sys.exit(app.exec_()) 

image

+1

谢谢@ X.Jacobs你的回答非常好:D – 2013-03-25 20:40:42

+1

@Adrián如果它很好,也许接受它并且赞成它。 – neuronet 2014-07-05 14:25:43