The source code for this example is gui_example.py

GUI Programming with PySide

In this example, we develop a simple GUI dialog which creates a PFC model. The pyside Python extension module provides bindings to the Qt GUI programming library used by PFC.

First we import the itasca module and some submodules from the pyside2 package.

from PySide2 import QtCore, QtGui, QtWidgets, shiboken2
import itasca as it
it.command("python-reset-state false")

To incorporate the dialog we are creating into the PFC GUI we need to get access to the Itasca GUI doc widget.

dockWidget = it.dockWidget("Demo GUI","",True)
dockWidget = shiboken2.wrapInstance(int(dockWidget),QtWidgets.QDockWidget)
widget = dockWidget.widget()

Next we define our dialog as a derived class of the QtGui.QWidget class.

class Window(QtWidgets.QWidget):
    def __init__(self, parent = None):
        QtWidgets.QWidget.__init__(self, parent)

        mainLayout = QtWidgets.QVBoxLayout()
        self.setLayout(mainLayout)

        self.setWindowTitle(self.tr("Demo GUI"))

        verticalGroupBox = QtWidgets.QGroupBox("Settings")
        layout1 = QtWidgets.QVBoxLayout()
        ballLimit = 10000
        msg = "Number of balls (between {} and {}):"
        labelBalls = QtWidgets.QLabel(msg.format(0, ballLimit));
        layout1.addWidget(labelBalls)
        spinBox = QtWidgets.QSpinBox(self)
        spinBox.setRange(0, ballLimit)
        spinBox.setValue(1000)
        layout1.addWidget(spinBox)
        verticalGroupBox.setLayout(layout1)
        mainLayout.addWidget(verticalGroupBox)

        horizontalGroupBox = QtWidgets.QGroupBox("Actions")
        layout = QtWidgets.QHBoxLayout()
        buttons = []
        for i in range(4):
            button = QtWidgets.QPushButton("Button %d" % (i + 1))
            layout.addWidget(button)
            buttons.append(button)
        horizontalGroupBox.setLayout(layout)
        mainLayout.addWidget(horizontalGroupBox)

        #change the name of the first button to new and connect to a command
        buttons[0].setText("New")
        def onButton0():
            it.command("model new")
        buttons[0].clicked.connect(onButton0)

        #change the names of the later buttons
        buttons[1].setText("Domain")
        def onButton1():
            it.command("model domain extent -10 10")
        buttons[1].clicked.connect(onButton1)

        buttons[2].setText("Generate Balls")
        def onButton2():
            nballs = spinBox.value()
            try:
                it.command("ball generate number {}".format(nballs))
            except RuntimeError as error:
                warning_box = QtWidgets.QMessageBox(main)
                msg = "A PFC error has occurred: {}"
                warning_box.setText(msg.format(error))
                warning_box.show()
        buttons[2].clicked.connect(onButton2)

        buttons[3].setText("Show Balls")
        def onButton3():
            it.command('''
                plot create
                plot clear
                plot active on
                plot background 'white'
                plot item create ball
                plot show''')
        buttons[3].clicked.connect(onButton3)

Finally, we connect our dialog to the PFC GUI as a dockable window and bring it to the top level.

widget.layout().addWidget(Window())
dockWidget.show()
dockWidget.raise_()

Clicking the New, Domain, Generate Balls and Show Balls buttons in sequence results in the image below.

../../../../../../../_images/gui_ex.png