You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Current »

On this page:

Child pages:

Copied from Controls Software Operations Group's page by Tasha Summers

Useful links

Common Practices For PyDM Displays

When creating a display through designer (.ui file) or python (.py file), there are a few things that we as controls software ops support group would like to keep consistent across all displays.

  1. Buttons that launch other applications should have a related display indicator! This is so the user of the display can easily distinguish between a clickable button writing to some PV through channel access protocols and a related display. The same logic should also be applied to shell commands that launch external displays.
  2. Main screens (files with naming convention {subsystem}_{area}_main.ui and appear as the first layer on LCLSHOME) should include a title as shown in the screenshot below.

Default Python Based PyDM

This block of code can be used to create a basic PyDM screen.  This is useful for testing new ideas, creating demonstrations, or as a launch point for new Python script based PyDM user interfaces.  You may need to import additional Qt and PyDM widgets, as well as other useful Python packages.  The Python packages epics, functools, and pandas are among some frequently used packages.


Default Python Based PyDM
from qtpy.QtWidgets import (QApplication, QHBoxLayout, QVBoxLayout, 
                            QGridLayout, QLabel, QPushButton,
                            QFrame, QTableWidget, QLineEdit,
                            QSpacerItem, QSizePolicy)
from pydm import Display
from pydm.widgets import PyDMLabel, PyDMLineEdit
from pydm.widgets.base import PyDMWidget
from pydm.widgets.related_display_button import PyDMRelatedDisplayButton

class MainWindow(Display):
    def __init__(self, *args, **kwargs):        
        super(MainWindow, self).__init__(*args, **kwargs)

        self.main_layout = QVBoxLayout()
        self.setLayout(self.main_layout)


QTableWidget

Tables are a powerful PyQT tool.  Tables are intuitive and organized by nature, in contrast to some of the PyQT Layouts.  The geometry of tables lend themselves to programmatic creation using lists and for loops.  Widgets can be placed into table cells and easily called on again.  It is simple to hide/show entire rows or columns.


QTableWidget Example
## Default PyDM imports
from qtpy.QtWidgets import (QVBoxLayout, QLabel,
                            QTableWidget)
from pydm import Display
from pydm.widgets import PyDMLabel, PyDMLineEdit
from pydm.widgets.related_display_button import PyDMRelatedDisplayButton

class MainWindow(Display):
    def __init__(self, *args, **kwargs):        
        super(MainWindow, self).__init__(*args, **kwargs)

        self.main_layout = QVBoxLayout()
        self.setLayout(self.main_layout)

        ## Make a 4x4 table
        table = QTableWidget()
        table.setRowCount(4)
        table.setColumnCount(4)

        ## Arbitrary list of n pvs
        list_of_pvs = ['pv1', 'pv2', 'pv3', 'pv4']

        ## Create the widgets that will get inserted in the table
        for i in range(table.rowCount()):
            pv = list_of_pvs[i]

            label = QLabel(pv)

            readback = PyDMLabel()
            readback.channel = pv

            line_edit = PyDMLineEdit()
            line_edit.channel = pv

            related_display = PyDMRelatedDisplayButton()
            related_display.filenames = ['my_file']

            ## Arbitrary list of n widgets
            widgets = [label, readback, line_edit, related_display]

            ## Add the widgets to the table at position i, j
            for j in range(table.columnCount()):
                table.setCellWidget(i, j, widgets[j])

        ## Add the whole table to the main layout
        self.main_layout.addWidget(table)

        ## Grab any widget in the table and do something, for ex.
        pv1_label = table.cellWidget(0, 0)
        pv1_label.setText('Hello, World!')

		## Hide any row
		table.hideRow(2)

		## Show any row
		table.showRow(2)

PyDMRelatedDisplayButton

This widget can be used to open both EDM and PyDM files.  To open a designated file, a list of filenames is given. If more than one filename is in the list, a dropdown menu is generated to let the user select which file to open.

Local Channels

Using a local channel to set rules based on macros

As a tool for dynamic displays, macros can be used as PV values to trigger rule events.  Create a local variable of the form loc://<my_variable_name>?type=str&init=${my_macro} by setting the channel field of a PyDM Widget.  The varaiable can then be called from the rules editor to dynamically change display properties.

QSplitters

QSplitters are a useful type of frame that allows the user to control the size of child widgets by dragging the boundary between them. These splitters can contain any number of widgets, and even allow the user to collapse widgets. More information on QSplitters can be found here: QSplitter - Qt for Python

In designer, widgets can be added to a splitter using the buttons circled in the picture below. The buttons are only selectable when multiple widgets (that aren't already in a layout) are selected.

The default splitter handle's are difficult to see, so the code below can be added to a stylesheet in order to make them more visible:

QSplitter Handle Style
QSplitter::handle {
     background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5,
 									   radius:0.5, fx:0.5, fy:0.5,
 									   stop:0 rgba(121, 121, 121, 255),
 									   stop:0.3 rgba(121, 121, 121, 255),
 									   stop:0.301 rgba(255, 255, 255, 255),
 									   stop:1 rgba(255, 255, 255, 100));
}
  • No labels