【问题标题】:Create a drag and drop modeling tool in Python在 Python 中创建拖放建模工具
【发布时间】:2017-05-04 07:42:24
【问题描述】:

我不知道怎么问这个,但这里是......

我想创建一个定义大约 10 个不同对象的用户界面。

这些对象都可以相互连接。

是否有基于 Python 的工具可以轻松定义简单的用户界面和带有一些可拖动对象的画布。

例如。假设我有一个 python 框架来解决 powerflow。我以编程方式创建网络。

现在我只想定义一些对象,每个对象都有一张小图片,将它们拖到画布上,右键单击它们以设置它们的设置。

我可以调查所有正常的 python 东西,但只是检查是否有可能不是一个可以帮助自动化的工具。

我添加了一张商业工具的图片。 托比

【问题讨论】:

  • PyQT 或 PySide 可以帮助您。使用 PIP install PySide 安装 PySide。转到 PySide 安装文件夹 "C:\Python27\Lib\site-packages\PySide\examples" 浏览所有示例。示例可能会帮助您完成任务。
  • 您好,感谢您的回答,但我认为这正是我不问的。我了解这些框架并且以前使用过它们。我的问题与“是否有一个框架可以使构建简单的建模工具,具有简单的拖放界面。
  • 抱歉,我无法正确理解您的问题。你能给我任何你可能正在寻找的类似工具的例子吗?我正在使用具有拖放界面的 Qt Designer 来构建表单,我想你知道 Qt Designer。
  • 嗨,应用程序本身将是一个拖放界面。我们需要为网络建模而构建的应用程序将在选择窗格中包含一些设备,您应该能够将它们拖放到画布上。将它们相互连接并设置它们的属性。这是一个 js 选项的示例 - freegroup.github.io/draw2d_js.app.brainbox.
  • 你好@Tooblippe。您是否找到了解决问题的方法。我需要一个你想要的界面。

标签: python modeling


【解决方案1】:

它必须是原生 UI 吗?如果没有,我建议使用 D3.js 之类的东西进行可视化,使用 python 作为后端,使用 AJAX 进行通信。它比使用 PyQt 或 PyTk 实现类似的功能要高效得多。

至于一些现成的包装,我不知道有没有。

【讨论】:

  • 这是一个很好的观点。我认为如果它支持网络,那就更好了。
  • 您能举例说明如何做到这一点吗?
【解决方案2】:

要完成您的任务,您需要将 qtnodes(https://github.com/cb109/qtnodes) 模块与 Pyqt 拖放代码结合起来。下面的代码可能会对您有所帮助,但您需要阅读 qtnodes 的内部代码。如果您可以妥协拖放选项,那么您可以轻松地仅使用 qtnodes 构建应用程序。

您可以构建与 Tobie 相同的工具,但您需要使用 pyside 或 pyqt 或 tkinter 从头开始​​编写所有代码。

拖放列表到图形场景

from PyQt4 import QtCore, QtGui
import sys

class GraphicsScene(QtGui.QGraphicsScene):

    def __init__(self, parent = None):
        super(GraphicsScene, self).__init__(parent)

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

    def dragMoveEvent(self, event):
        event.accept()

    def dragLeaveEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        text = QtGui.QGraphicsTextItem(event.mimeData().text())
        text.setPos(event.scenePos())
        self.addItem(text)
        event.accept()

class ListView(QtGui.QListView):

    def __init__(self, parent = None):
        super(ListView, self).__init__(parent)
        self.setDragEnabled(True)

    def dragEnterEvent(self, event):
        event.setDropAction(QtCore.Qt.MoveAction)
        event.accept()

    def startDrag(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return

        selected = self.model().data(index, QtCore.Qt.DisplayRole)

        mimeData = QtCore.QMimeData()
        mimeData.setText(selected.toString())

        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        result = drag.start(QtCore.Qt.MoveAction)
        if result: # == QtCore.Qt.MoveAction:
            pass

    def mouseMoveEvent(self, event):
        self.startDrag(event)

class MainWindow(QtGui.QMainWindow):

    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)

        self.setGeometry(100, 100, 400, 400)

        self.widget = QtGui.QWidget()
        self.setCentralWidget(self.widget)
        layout = QtGui.QGridLayout(self.widget)

        self.ListView = ListView()

        data = QtCore.QStringList()
        data << "one" << "two" << "three"
        self.model = QtGui.QStringListModel(data)
        

        self.ListView.setModel(self.model)

        self.GraphicsView = QtGui.QGraphicsView()
        self.scene = GraphicsScene()
        self.GraphicsView.setScene(self.scene)
        #self.GraphicsView.setSceneRect(0, 0, self.GraphicsView.width(), self.GraphicsView.height())
        
        layout.addWidget(self.ListView, 0, 0, 5, 5)
        layout.addWidget(self.GraphicsView, 0, 1, 5, 5)

        self.show()
        self.GraphicsView.setSceneRect(0, 0, self.GraphicsView.width(), self.GraphicsView.height())

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

以下代码用于按钮的拖放

from PyQt4 import QtGui, QtCore

class DragButton(QtGui.QPushButton):

    def __init__(self, parent):
         super(DragButton,  self).__init__(parent)
         self.allowDrag = True
    
    def setAllowDrag(self, allowDrag):
        if type(allowDrag) == bool:
           self.allowDrag = allowDrag
        else:
            raise TypeError("You have to set a boolean type")
    
    def mouseMoveEvent(self, e):
        if e.buttons() != QtCore.Qt.RightButton:
            return
    
        if self.allowDrag == True:
            # write the relative cursor position to mime data
            mimeData = QtCore.QMimeData()
            # simple string with 'x,y'
            mimeData.setText('%d,%d' % (e.x(), e.y()))
            print mimeData.text()
    
            # let's make it fancy. we'll show a "ghost" of the button as we drag
            # grab the button to a pixmap
            pixmap = QtGui.QPixmap.grabWidget(self)
    
            # below makes the pixmap half transparent
            painter = QtGui.QPainter(pixmap)
            painter.setCompositionMode(painter.CompositionMode_DestinationIn)
            painter.fillRect(pixmap.rect(), QtGui.QColor(0, 0, 0, 127))
            painter.end()
    
            # make a QDrag
            drag = QtGui.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_(QtCore.Qt.LinkAction | QtCore.Qt.MoveAction) == QtCore.Qt.LinkAction:
                print 'linked'
            else:
                print 'moved'
    
    def mousePressEvent(self, e):
        QtGui.QPushButton.mousePressEvent(self, e)
        if e.button() == QtCore.Qt.LeftButton:
            print 'press'
            #AQUI DEBO IMPLEMENTAR EL MENU CONTEXTUAL
    
    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())
        print e.pos()
            #e.source().move(e.pos()-QtCore.QPoint(x, y))
            # set the drop action as LinkAction
        e.setDropAction(QtCore.Qt.LinkAction)
        # tell the QDrag we accepted it
        e.accept()

我从堆栈溢出中复制的所有代码。通过下面的链接了解更多详情。

Drag n Drop inside QgraphicsView doesn't work (PyQt)

Drag n Drop Button and Drop-down menu PyQt/Qt designer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多