Examples

The examples here can be found in the examples folder in the project’s repository root.

How to run the examples

To run test you will need Conda and conda-devenv to setup the environment.

git clone https://github.com/ESSS/qmxgraph.git
cd qmxgraph
git clone --depth=1 --branch v3.7.5 https://github.com/jgraph/mxgraph.git
conda devenv
conda activate qmxgraph
inv qrc
# Hello world example.
python examples/hello_world/main.py
# Drag and drop example.
python examples/drag_and_drop/main.py

Hello world

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
We all love "hello world" examples =)
"""

import sys

from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QMainWindow

from qmxgraph.widget import QmxGraph


class HelloWorldWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(640, 480))
        self.setWindowTitle("Qmx Hello World")

        self.graph_widget = QmxGraph(parent=self)
        # Only operate with the qmx's api after the widget has been loaded.
        self.graph_widget.loadFinished.connect(self.graph_load_handler)
        self.setCentralWidget(self.graph_widget)

    def graph_load_handler(self, is_loaded):
        assert is_loaded
        qmx = self.graph_widget.api
        v0_id = qmx.insert_vertex(
            x=100, y=100, width=50, height=100, label="Qmx"
        )
        v1_id = qmx.insert_vertex(
            x=400, y=300, width=100, height=50, label="World"
        )
        qmx.insert_edge(source_id=v0_id, target_id=v1_id, label="Hello")


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = HelloWorldWindow()
    mainWin.show()
    sys.exit(app.exec_())

Basic on styles

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
Display the use of styles. This is similar to the hello world sample.
"""

import sys

from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QMainWindow

from qmxgraph.configuration import GraphStyles
from qmxgraph.widget import QmxGraph


class StyleWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(640, 480))
        self.setWindowTitle("Qmx Styles")

        styles_cfg = {
            'round_node': {
                'shape': 'ellipse',
                'fill_color': '#D88',
                'vertical_label_position': 'bottom',
                'vertical_align': 'top',
            },
            'bold_edge': {
                'end_arrow': 'classic',
                'shape': 'connector',
                'stroke_width': 5.0,
            },
        }

        self.graph_widget = QmxGraph(
            styles=GraphStyles(styles_cfg), parent=self
        )
        # Only operate with the qmx's api after the widget has been loaded.
        self.graph_widget.loadFinished.connect(self.graph_load_handler)
        self.setCentralWidget(self.graph_widget)

    def graph_load_handler(self, is_loaded):
        assert is_loaded
        qmx = self.graph_widget.api
        v0_id = qmx.insert_vertex(
            x=100, y=100, width=50, height=50, label="AAA"
        )
        # Style by configured style name.
        v1_id = qmx.insert_vertex(
            x=400,
            y=100,
            width=100,
            height=50,
            label="BBB",
            style='round_node',
        )
        # Style by explicit values.
        v2_id = qmx.insert_vertex(
            x=200,
            y=300,
            width=50,
            height=100,
            label="CCC",
            style='fillColor=#8D8',
        )

        qmx.insert_edge(source_id=v0_id, target_id=v1_id, label='normal')
        qmx.insert_edge(
            source_id=v1_id, target_id=v2_id, label='bold', style='bold_edge'
        )


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = StyleWindow()
    mainWin.show()
    sys.exit(app.exec_())

Drag&drop and events bridge

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
"""
Display drag from the app into the graph widget and the event bridge.
This is similar to the hello world sample.
"""

import sys

from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QDrag
from PyQt5.QtWidgets import (
    QGridLayout,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)

import qmxgraph.mime
from qmxgraph.widget import EventsBridge, QmxGraph


def create_drag_button(text, qmx_style, parent=None):
    button = DragButton(parent)
    button.setText(text)
    # # You can set an icon to the button with:
    # button.setIcon(...)
    button.setProperty('qmx_style', qmx_style)
    button.setToolTip("Drag me into the graph widget")
    return button


class DragButton(QPushButton):
    """
    Start a drag even with custom data.
    """

    def mousePressEvent(self, event):
        mime_data = qmxgraph.mime.create_qt_mime_data(
            {
                'vertices': [
                    {
                        'dx': 0,
                        'dy': 0,
                        'width': 120,
                        'height': 40,
                        'label': self.text(),
                        'style': self.property('qmx_style'),
                    }
                ]
            }
        )

        drag = QDrag(self)
        drag.setMimeData(mime_data)
        # # You can set icons like the following:
        # w, h = self.property('component_size')
        # # Image displayed while dragging.
        # drag.setPixmap(self.icon().pixmap(w, h))
        # # Position of the image where the mouse is centered.
        # drag.setHotSpot(QPoint(w // 2, h // 2)
        drag.exec_()


class DragAndDropWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setProperty('name', 'adas')
        self.setMinimumSize(QSize(640, 480))
        self.setWindowTitle("Drag&Drop Styles")

        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)

        self.button_pane = QWidget(self)
        self.button_pane.setEnabled(False)
        red_button = create_drag_button(
            'RED', 'fillColor=#D88', self.button_pane
        )
        green_button = create_drag_button(
            'GREEN', 'fillColor=#8D8', self.button_pane
        )
        blue_button = create_drag_button(
            'BLUE', 'fillColor=#88D', self.button_pane
        )

        self.graph_widget = QmxGraph(parent=central_widget)
        self.graph_widget.loadFinished.connect(self.graph_load_handler)

        main_layout = QGridLayout(self)
        central_widget.setLayout(main_layout)
        main_layout.addWidget(self.graph_widget, 0, 0)
        main_layout.addWidget(self.button_pane, 0, 1)

        buttons_layout = QVBoxLayout(self.button_pane)
        self.button_pane.setLayout(buttons_layout)
        buttons_layout.addWidget(red_button)
        buttons_layout.addWidget(green_button)
        buttons_layout.addWidget(blue_button)

    def graph_load_handler(self, is_loaded):
        ##################################
        # Based in `EventsBridge` docstring.

        def on_cells_added_handler(cell_ids):
            print(f'added {cell_ids}')
            qmx = widget.api
            for cid in cell_ids:
                label = qmx.get_label(cid)
                qmx.set_label(cid, f'{label} ({cid})')

        def on_terminal_changed_handler(
            cell_id, terminal_type, new_terminal_id, old_terminal_id
        ):
            print(
                f'{terminal_type} of {cell_id} changed from'
                f' {old_terminal_id} to {new_terminal_id}'
            )

        def on_cells_removed_handler(cell_ids):
            print(f'removed {cell_ids}')

        events_bridge = EventsBridge()
        widget = self.graph_widget
        widget.set_events_bridge(events_bridge)

        events_bridge.on_cells_added.connect(on_cells_added_handler)
        events_bridge.on_cells_removed.connect(on_cells_removed_handler)
        events_bridge.on_terminal_changed.connect(on_terminal_changed_handler)

        #
        ##################################

        self.button_pane.setEnabled(is_loaded)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = DragAndDropWindow()
    mainWin.show()
    sys.exit(app.exec_())