A realtime meter
PtWidget --> PtBasic --> RtMeter
For more information, see the diagram of the widget hierarchy.
<photon/realtime/RtMeter.h>
The RtMeter widget is drawn as a half circle with divisional ticks at 1/4, 1/2, and 3/4 of the arc.
An RtMeter widget.
The needle can be moved with the mouse, the keyboard or programmatically:
Up to 3 severity arcs can be drawn in colors to indicate different levels of the meter:
The widget bases its size on the text size and the specified dimensions. If the given dimensions are too small, it sizes itself appropriately based on the resize policy. The height of the widget depends on the radius of the meter, which in turn depends on the X dimension and text sizes.
To create a 3-arc meter with the default arc colors and positions (as shown above):
... PhArea_t area = { { 10, 10 }, { 200, 200 } }; ... PtSetArg(&args[0], Pt_ARG_AREA, &area, 0); PtCreateWidget(RtMeter, parent, 1, args) ...
To create a 1-arc meter that can be moved by clicking the mouse buttons, has a minimum value of 0, has a maximum of 1000, and notifies you when the user moves the needle:
A one-arc RtMeter widget.
... PhArea_t area = { { 10, 10 }, { 200, 200 } }; PtCallback_t cb[1] = { {moved_cb, NULL} }; PtSetArg(&args[0], Pt_ARG_AREA, &area, 0); PtSetArg(&args[1], Rt_ARG_METER_MAX_NEEDLE_POSITION, 1000, 0); PtSetArg(&args[2], Rt_CB_METER_MOVED, &cb[1], 0); PtCreateWidget(RtMeter, parent, 3, args) ... int moved_cb(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { RtMeterCallback_t *mydata; mydata = info->cbdata; printf("Got the callback. Position was: %d severity: %d\n ", mydata->position, mydata->severity); } ...
To create a 3-arc meter whose needle can be moved
with an increment of 10 for each keystroke (for example, the meter will move 0, 10, 20, ... when you press the up-arrow key):
... PhArea_t area = { { 10, 10 }, { 200, 200 } }; PtCallback_t cb[1] = { {moved_cb, NULL} }; PtSetArg(&args[0], Pt_ARG_AREA, &area, 0); PtSetArg(&args[1], Rt_ARG_METER_KEY_LEFT, Pk_Down, 0); PtSetArg(&args[2], Rt_ARG_METER_KEY_RIGHT, Pk_Up, 0); PtSetArg(&args[3], Rt_ARG_METER_INCREMENT, 10, 0); PtSetArg(&args[4], Rt_CB_METER_MOVED, &cb[1], 0); PtCreateWidget( RtMeter, parent, 5, args ); ... int moved_cb( PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { RtMeterCallback_t *mydata; mydata = info->cbdata; printf("Got the callback. Position was: %d severity: %d\n", mydata->position, mydata->severity); }
You'll notice that as you move the needle on the widget, there's very little flickering. This is because when the needle moves it's merely erased and then drawn at the new position. However, if you create a meter with Pg_TRANSPARENT as a fill color, you'll notice more flickering because the needle can't merely be erased - the background must be drawn as well. In this case, flickering is reduced by calculating a bounding rectangle for the needle and redrawing only that rectangle. The most flickering (redraw) occurs when the needle is at 45° or 135°.
For flicker-free performance when using Pg_TRANSPARENT as a fill color, put the RtMeter inside a PtDBContainer widget. |
#include <stdio.h> #include <Pt.h> #include <photon/realtime/RtMeter.h> PtWidget_t *window, *meter, *quit, *sev_lbl, *pos_lbl; // callback for meter moved int meter_cb( PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { RtMeterCallback_t *mydata; char pos[10], sev[5]; PtArg_t args[2]; mydata = info->cbdata; itoa(mydata->position, pos, 10); itoa(mydata->severity, sev, 10); // set the position label to the current position PtSetArg(&args[0], Pt_ARG_TEXT_STRING, pos, 0); PtSetResources(pos_lbl, 1, args); // set the severity label to the current severity PtSetArg(&args[0], Pt_ARG_TEXT_STRING, sev, 0); PtSetResources(sev_lbl, 1, args); return (Pt_CONTINUE); } // callback for the quit button void quit_cb( PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { exit (EXIT_SUCCESS); } void main(int argc, char *argv[]) { PtArg_t args[10]; PhDim_t win_dim = { 300, 300 }; PhArea_t meter_area = { { 10, 20 }, { 280, 280 } }; PhArea_t sev_area = { { 125, 200 }, { 50, 20 } }; PhArea_t pos_area = { { 125, 230 }, { 50, 20} }; PhArea_t quit_area = { { 230, 270 }, { 60, 20 } }; PtCallback_t callbacks[2] = { {meter_cb, NULL}, {quit_cb, NULL} }; int n = 0; PtSetArg( &args[n++], Pt_ARG_WINDOW_TITLE, "RtMeter Demo", 0 ); PtSetArg( &args[n++], Pt_ARG_DIM, &win_dim, 0 ); window = PtAppInit( NULL, &argc, argv, n, args ); // draw the meter with 3 arcs and a callback for meter moved n = 0; PtSetArg( &args[n++], Pt_ARG_AREA, &meter_area, 0 ); PtSetArg( &args[n++], Rt_ARG_METER_MAX_NEEDLE_POSITION, 1000, 0 ); PtSetArg( &args[n++], Rt_ARG_METER_TEXT_FONT, "helv12", 0 ); PtSetArg( &args[n++], Rt_CB_METER_MOVED, &callbacks[0], 0 ); // If you don't want your meter to be selectable, add // the following: // // PtSetArg( &args[n++], Rt_ARG_METER_FLAGS, // RtM_NON_SELECTABLE, RtM_NON_SELECTABLE ); meter = PtCreateWidget( RtMeter, window, n, args ); // Draw a label to show the severity changes. // The first label is the label to be changed, // and the second is the name of the parameter. n = 0; PtSetArg( &args[n++], Pt_ARG_AREA, &sev_area, 0 ); PtSetArg( &args[n++], Pt_ARG_FLAGS, Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT, \ Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT); PtSetArg( &args[n++], Pt_ARG_BORDER_WIDTH, 1, 0); PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "1", 0); sev_lbl = PtCreateWidget( PtLabel, window, n, args ); n = 0; sev_area.pos.x -= 60; PtSetArg( &args[n++], Pt_ARG_AREA, &sev_area, 0 ); PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Severity:", 0); PtCreateWidget( PtLabel, window, n, args ); // Draw a label to show the position changes. // The first label is the label to be changed, // and the second is the name of the parameter. n = 0; PtSetArg( &args[n++], Pt_ARG_AREA, &pos_area, 0 ); PtSetArg( &args[n++], Pt_ARG_FLAGS, Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT, \ Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT); PtSetArg( &args[n++], Pt_ARG_BORDER_WIDTH, 1, 0); PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "0", 0); pos_lbl = PtCreateWidget( PtLabel, window, n, args ); n = 0; pos_area.pos.x -= 60; PtSetArg( &args[n++], Pt_ARG_AREA, &pos_area, 0 ); PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Position:", 0); PtCreateWidget( PtLabel, window, n, args ); // draw a quit button n = 0; PtSetArg( &args[n++], Pt_ARG_AREA, &quit_area, 0 ); PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Quit", 0); PtSetArg( &args[n++], Pt_CB_ACTIVATE, &callbacks[1], 0); quit = PtCreateWidget( PtButton, window, n, args ); PtRealizeWidget( window ); PtMainLoop(); }
Resource | C type | Pt type | Default |
---|---|---|---|
Rt_ARG_METER_COLOR | PgColor_t | Scalar | Pg_BLACK |
Rt_ARG_METER_FLAGS | unsigned short | Flag | RtM_SELECTABLE |
Rt_ARG_METER_FONT_COLOR | PgColor_t | Scalar | Pg_BLACK |
Rt_ARG_METER_INCREMENT | int | Scalar | 5 |
Rt_ARG_METER_KEY_LEFT | int | Scalar | Pk_Left |
Rt_ARG_METER_KEY_RIGHT | int | Scalar | Pk_Right |
Rt_ARG_METER_LEVEL1_COLOR | PgColor_t | Scalar | Pg_GREEN |
Rt_ARG_METER_LEVEL1_POS | short | Scalar | 50 |
Rt_ARG_METER_LEVEL2_COLOR | PgColor_t | Scalar | Pg_YELLOW |
Rt_ARG_METER_LEVEL2_POS | short | Scalar | 75 |
Rt_ARG_METER_LEVEL3_COLOR | PgColor_t | Scalar | Pg_RED |
Rt_ARG_METER_MAX_NEEDLE_POSITION | short | Scalar | 100 |
Rt_ARG_METER_MIN_NEEDLE_POSITION | short | Scalar | 0 |
Rt_ARG_METER_NEEDLE_COLOR | PgColor_t | Scalar | Pg_WHITE |
Rt_ARG_METER_NEEDLE_POSITION | short | Scalar | 0 |
Rt_ARG_METER_NUM_SEVERITY_LEVELS | short | Scalar | 3 |
Rt_ARG_METER_TEXT_FONT | char * | String | "helv10" |
Rt_CB_METER_MOVED | PtCallback_t * | Link | NULL |
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_BLACK |
The color for the center circle, outline of the meter, and divisional ticks.
C type | Pt type | Default |
---|---|---|
unsigned short | Flag | RtM_SELECTABLE |
The valid bits are:
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_BLACK |
The font color for the minimum and maximum strings.
C type | Pt type | Default |
---|---|---|
int | Scalar | 5 |
The increment used when the keyboard is used to move the meter's needle. Every press of the assigned keys will move the meter this distance.
C type | Pt type | Default |
---|---|---|
int | Scalar | Pk_Left |
The key, as defined in <photon/PkKeyDef.h>, that's to be used to move the meter's needle to the left. The default value is the left arrow, Pk_Left.
Pt_ARG_FLAGS must have Pt_GETS_FOCUS set. |
C type | Pt type | Default |
---|---|---|
int | Scalar | Pk_Right |
The key, as defined in <photon/PkKeyDef.h>, that's to be used to move the meter's needle to the right. The default value is the right arrow, Pk_Right.
Pt_ARG_FLAGS must have Pt_GETS_FOCUS set. |
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_GREEN |
The color of the first severity arc.
C type | Pt type | Default |
---|---|---|
short | Scalar | 50 |
The position of the end of the first severity arc, expressed as a percentage of the whole. If the minimum and/or maximum value(s) change, the location of the arc is updated to remain at this percentage.
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_YELLOW |
The color of the second severity arc.
C type | Pt type | Default |
---|---|---|
short | Scalar | 75 |
The position of the end of the second severity arc, expressed as a percentage of the whole. If the minimum and/or maximum value(s) change, the location of the arc is updated to remain at this percentage.
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_RED |
The color of the third severity arc.
C type | Pt type | Default |
---|---|---|
short | Scalar | 100 |
The maximum needle position; also the value drawn as the maximum.
C type | Pt type | Default |
---|---|---|
short | Scalar | 0 |
The minimum needle position; also the value drawn as the minimum.
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pg_WHITE |
The color of the meter's needle.
C type | Pt type | Default |
---|---|---|
short | Scalar | 0 |
The current needle position, somewhere between the minimum and maximum needle position. If the position is above the maximum, the maximum is used; if the position is below the minimum, the minimum is used.
C type | Pt type | Default |
---|---|---|
short | Scalar | 3 |
The number of severity arcs (levels) that the meter displays. This must be 1, 2, or 3. If this resource is set higher than 3, only 3 arcs are displayed.
C type | Pt type | Default |
---|---|---|
char * | String | "helv10" |
The font for the minimum and maximum strings.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of callbacks invoked when the needle is moved. Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
For more information, see PhEvent_t in the Photon Library Reference.
These callbacks should return Pt_CONTINUE.
If the widget modifies an inherited resource, the "Default override" column indicates the new value. This modification affects any subclasses of the widget.