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"""
 2We all love "hello world" examples =)
 3"""
 4
 5import sys
 6
 7from PyQt5 import QtWidgets
 8from PyQt5.QtCore import QSize
 9from PyQt5.QtWidgets import QMainWindow
10
11from qmxgraph.widget import QmxGraph
12
13
14class HelloWorldWindow(QMainWindow):
15    def __init__(self):
16        QMainWindow.__init__(self)
17
18        self.setMinimumSize(QSize(640, 480))
19        self.setWindowTitle("Qmx Hello World")
20
21        self.graph_widget = QmxGraph(parent=self)
22        # Only operate with the qmx's api after the widget has been loaded.
23        self.graph_widget.loadFinished.connect(self.graph_load_handler)
24        self.setCentralWidget(self.graph_widget)
25
26    def graph_load_handler(self, is_loaded):
27        assert is_loaded
28        qmx = self.graph_widget.api
29        v0_id = qmx.insert_vertex(x=100, y=100, width=50, height=100, label="Qmx")
30        v1_id = qmx.insert_vertex(x=400, y=300, width=100, height=50, label="World")
31        qmx.insert_edge(source_id=v0_id, target_id=v1_id, label="Hello")
32
33
34if __name__ == "__main__":
35    app = QtWidgets.QApplication(sys.argv)
36    mainWin = HelloWorldWindow()
37    mainWin.show()
38    sys.exit(app.exec_())

Basic on styles

 1"""
 2Display the use of styles. This is similar to the hello world sample.
 3"""
 4
 5import sys
 6
 7from PyQt5 import QtWidgets
 8from PyQt5.QtCore import QSize
 9from PyQt5.QtWidgets import QMainWindow
10
11from qmxgraph.configuration import GraphStyles
12from qmxgraph.widget import QmxGraph
13
14
15class StyleWindow(QMainWindow):
16    def __init__(self):
17        QMainWindow.__init__(self)
18
19        self.setMinimumSize(QSize(640, 480))
20        self.setWindowTitle("Qmx Styles")
21
22        styles_cfg = {
23            "round_node": {
24                "shape": "ellipse",
25                "fill_color": "#D88",
26                "vertical_label_position": "bottom",
27                "vertical_align": "top",
28            },
29            "bold_edge": {
30                "end_arrow": "classic",
31                "shape": "connector",
32                "stroke_width": 5.0,
33            },
34        }
35
36        self.graph_widget = QmxGraph(styles=GraphStyles(styles_cfg), parent=self)
37        # Only operate with the qmx's api after the widget has been loaded.
38        self.graph_widget.loadFinished.connect(self.graph_load_handler)
39        self.setCentralWidget(self.graph_widget)
40
41    def graph_load_handler(self, is_loaded):
42        assert is_loaded
43        qmx = self.graph_widget.api
44        v0_id = qmx.insert_vertex(x=100, y=100, width=50, height=50, label="AAA")
45        # Style by configured style name.
46        v1_id = qmx.insert_vertex(
47            x=400,
48            y=100,
49            width=100,
50            height=50,
51            label="BBB",
52            style="round_node",
53        )
54        # Style by explicit values.
55        v2_id = qmx.insert_vertex(
56            x=200,
57            y=300,
58            width=50,
59            height=100,
60            label="CCC",
61            style="fillColor=#8D8",
62        )
63
64        qmx.insert_edge(source_id=v0_id, target_id=v1_id, label="normal")
65        qmx.insert_edge(source_id=v1_id, target_id=v2_id, label="bold", style="bold_edge")
66
67
68if __name__ == "__main__":
69    app = QtWidgets.QApplication(sys.argv)
70    mainWin = StyleWindow()
71    mainWin.show()
72    sys.exit(app.exec_())

Drag&drop and events bridge

  1"""
  2Display drag from the app into the graph widget and the event bridge.
  3This is similar to the hello world sample.
  4"""
  5
  6import sys
  7
  8from PyQt5 import QtWidgets
  9from PyQt5.QtCore import QSize
 10from PyQt5.QtGui import QDrag
 11from PyQt5.QtWidgets import QGridLayout
 12from PyQt5.QtWidgets import QMainWindow
 13from PyQt5.QtWidgets import QPushButton
 14from PyQt5.QtWidgets import QVBoxLayout
 15from PyQt5.QtWidgets import QWidget
 16
 17import qmxgraph.mime
 18from qmxgraph.widget import QmxGraph
 19
 20
 21def create_drag_button(text, qmx_style, parent=None):
 22    button = DragButton(parent)
 23    button.setText(text)
 24    # # You can set an icon to the button with:
 25    # button.setIcon(...)
 26    button.setProperty("qmx_style", qmx_style)
 27    button.setToolTip("Drag me into the graph widget")
 28    return button
 29
 30
 31class DragButton(QPushButton):
 32    """
 33    Start a drag even with custom data.
 34    """
 35
 36    def mousePressEvent(self, event):
 37        mime_data = qmxgraph.mime.create_qt_mime_data(
 38            {
 39                "vertices": [
 40                    {
 41                        "dx": 0,
 42                        "dy": 0,
 43                        "width": 120,
 44                        "height": 40,
 45                        "label": self.text(),
 46                        "style": self.property("qmx_style"),
 47                    }
 48                ]
 49            }
 50        )
 51
 52        drag = QDrag(self)
 53        drag.setMimeData(mime_data)
 54        # # You can set icons like the following:
 55        # w, h = self.property('component_size')
 56        # # Image displayed while dragging.
 57        # drag.setPixmap(self.icon().pixmap(w, h))
 58        # # Position of the image where the mouse is centered.
 59        # drag.setHotSpot(QPoint(w // 2, h // 2)
 60        drag.exec_()
 61
 62
 63class DragAndDropWindow(QMainWindow):
 64    def __init__(self):
 65        QMainWindow.__init__(self)
 66
 67        self.setProperty("name", "adas")
 68        self.setMinimumSize(QSize(640, 480))
 69        self.setWindowTitle("Drag&Drop Styles")
 70
 71        central_widget = QWidget(self)
 72        self.setCentralWidget(central_widget)
 73
 74        self.button_pane = QWidget(self)
 75        self.button_pane.setEnabled(False)
 76        red_button = create_drag_button("RED", "fillColor=#D88", self.button_pane)
 77        green_button = create_drag_button("GREEN", "fillColor=#8D8", self.button_pane)
 78        blue_button = create_drag_button("BLUE", "fillColor=#88D", self.button_pane)
 79
 80        self.graph_widget = QmxGraph(parent=central_widget)
 81        self.events_bridge = self.create_events_bridge()
 82        self.graph_widget.loadFinished.connect(self.graph_load_handler)
 83
 84        main_layout = QGridLayout(self)
 85        central_widget.setLayout(main_layout)
 86        main_layout.addWidget(self.graph_widget, 0, 0)
 87        main_layout.addWidget(self.button_pane, 0, 1)
 88
 89        buttons_layout = QVBoxLayout(self.button_pane)
 90        self.button_pane.setLayout(buttons_layout)
 91        buttons_layout.addWidget(red_button)
 92        buttons_layout.addWidget(green_button)
 93        buttons_layout.addWidget(blue_button)
 94
 95    def create_events_bridge(self):
 96        ##################################
 97        # Based in `EventsBridge` docstring.
 98
 99        def on_cells_added_handler(cell_ids):
100            print(f"added {cell_ids}")
101            qmx = widget.api
102            for cid in cell_ids:
103                label = qmx.get_label(cid)
104                qmx.set_label(cid, f"{label} ({cid})")
105
106        def on_terminal_changed_handler(cell_id, terminal_type, new_terminal_id, old_terminal_id):
107            print(
108                f"{terminal_type} of {cell_id} changed from"
109                f" {old_terminal_id} to {new_terminal_id}"
110            )
111
112        def on_cells_removed_handler(cell_ids):
113            print(f"removed {cell_ids}")
114
115        def on_cells_bounds_changed_handler(changed_cell_bounds):
116            print(f"cells bounds changed {changed_cell_bounds}")
117
118        widget = self.graph_widget
119        events_bridge = widget.events_bridge
120
121        events_bridge.on_cells_added.connect(on_cells_added_handler)
122        events_bridge.on_cells_removed.connect(on_cells_removed_handler)
123        events_bridge.on_terminal_changed.connect(on_terminal_changed_handler)
124        events_bridge.on_cells_bounds_changed.connect(on_cells_bounds_changed_handler)
125
126        #
127        ##################################
128        return events_bridge
129
130    def graph_load_handler(self, is_loaded):
131        self.button_pane.setEnabled(is_loaded)
132
133
134if __name__ == "__main__":
135    app = QtWidgets.QApplication(sys.argv)
136    mainWin = DragAndDropWindow()
137    mainWin.show()
138    sys.exit(app.exec_())