`

绘制Item

阅读更多

原文链接:http://www.eclipse.org/articles/article.php?file=Article-CustomDrawingTableAndTreeItems/index.html

Custom Drawing Table and Tree Items

Summary

Populating a table or tree widget involves creating items and setting their attributes (eg.- texts, images, etc.), after which the table or tree takes responsibility for displaying the items. This approach makes item creation straightforward and visually consistent. As of Eclipse 3.2, clients of Table and Tree can now custom draw their items, enabling a wide range of potential visual appearances. This article explores the custom draw mechanism for Table and Tree.

By Grant Gayed, IBM Ottawa Lab
September 15th, 2006 (updated to include SWT.HOT style on June 8, 2007)

Background

Tables and trees are powerful tools for presenting data in a structured manner. Data is displayed as a collection of items which have attributes like text(s), image(s), and sometimes interactive controls such as checkboxes. Typically, clients create the items and set their attributes, after which the table or tree takes responsibility for displaying them. This approach makes item creation straightforward and visually consistent, but is inflexible. For example, an item in a table or tree can only contain one image, and it must appear before its text. Given the range of visual appearances that a client may want an item to have, the best way to ensure that clients can create items with custom appearances is to allow items to be drawn.

The ability to partially or fully custom draw TableItems and TreeItems has been added as of Eclipse 3.2, and will be described in this article. It should be noted that all references made throughout the article to tables can be equally applied to trees, and vice versa.

Custom Draw Events

Custom drawing is done on a per-cell basis, where a cell is the portion of an item that resides within some row and column of the parent table, or the full item if the table has no columns. For example, if a table has two columns and three items then it has six cells.

The following Table events have been defined to provide hooks into the drawing process:

  • SWT.MeasureItem: allows a client to specify the dimensions of a cell's content
  • SWT.EraseItem: allows a client to custom draw a cell's background and/or selection, and to influence whether the cell's foreground should be drawn
  • SWT.PaintItem: allows a client to custom draw or augment a cell's foreground and/or focus rectangle

To minimize the amount of work required to draw cells, these events are configured to reflect how the cell would be drawn by default. This makes it easy to augment a cell's default appearance without having to draw the whole cell. If a client does not hook one of these listeners then the default cell drawing process will occur. The following sections will examine each of these events in detail along with some example code snippets.

SWT.MeasureItem

SWT.MeasureItem is the first custom draw event that is sent. This event gives a client the opportunity to specify the width and/or height of a cell's content. It is important to note that content size is not necessarily equivalent to cell size, since the latter may include additional decorations such as checkboxes or tree indentation. Contexts where this event is typically sent include drawing a cell and packing a table column. This event comes pre-configured with the following fields:

  • item: the item
  • index: the column index of item to be measured
  • width: the default content width that the table would use if it were to draw the cell itself, based on its text, image, and checkbox
  • height: the default content height that the table would use, based on the height of all of its items
  • gc: a GC that is configured with the cell's font, which can be useful for performing string measurements

An application that wishes to specify a different content width and/or height for the cell can do so by changing the event's width andheight fields. A listener may choose to not change one or both of these values.

Example 1: Specifying cell widths and heights

Listing 1 (snippet) demonstrates the use of SWT.MeasureItem to specify custom content dimensions in a table with no columns.

1 Display display = new Display();
2 Shell shell = new Shell(display);
3 shell.setBounds(10,10,200,250);
4 final Table table = new Table(shell, SWT.NONE);
5 table.setBounds(10,10,150,200);
6 table.setLinesVisible(true);
7 for (int i = 0; i < 5; i++) {
8    new TableItem(table, SWT.NONE).setText("item " + i);
9 }
10 table.addListener(SWT.MeasureItem, new Listener() {
11    public void handleEvent(Event event) {
12       int clientWidth = table.getClientArea().width;
13       event.height = event.gc.getFontMetrics().getHeight() * 2;
14       event.width = clientWidth * 2;
15    }
16 });
17 shell.open();
18 while (!shell.isDisposed()) {
19    if (!display.readAndDispatch()) display.sleep();
20 }
21 display.dispose();

Listing 1. Specifying custom widths and heights for items in a table with no columns

Lines 1-3:
Creates a display and shell, and sets the shell's bounds.

Lines 4-6:
Creates the table with no columns, sets its bounds, and sets its lines to be visible.

Lines 7-9:
Creates the table's items.

Lines 10-11
Adds an SWT.MeasureItem listener to the table, which will be invoked whenever the size of a cell's content is needed.

Line 12:
Gets the table's client width, which will be used when specifying the cell's content width.

Line 13:
Sets the event's height field to double the height of the font. This effectively doubles the height of the item in the event's itemfield relative to its default height.

Line 14:
Sets the event's width field to double the width of the table. This specifies that the width of the cell should be this value regardless of its content. Note that since this table has no columns, the width of the cell is equivalent to that of the full item.

Lines 17 to 21:
Opens the shell, runs the event loop until the shell has been disposed, and disposes the display just before exiting.

Figure 1 shows a screenshot of the snippet in Listing 1 running. Note the increased item heights (caused by line 13), and increased item widths (caused by line 14) which can be inferred from the table's horizontal scrollbar. Figure 2 shows a screenshot of the same snippet running with lines 10 through 16 commented out, allowing the table to draw in its default manner.


Figure 1. Screenshot of Listing 1 running, which specifies custom widths and heights for the items in a table


Figure 2. Screenshot of Listing 1 running without the SWT.MeasureItem listener

Note that attempts to change a cell's width or height in SWT.MeasureItem events are subject to the following constraints:

  1. As of Eclipse 3.2 cell heights are not allowed to shrink, only to grow.
  2. All items in a table have the same height, so increasing the height of a cell will result in the height of all items in the table growing accordingly.
  3. If the cell is within a table column then its width is determined by the column's width. However, the SWT.MeasureItem event's width field should still always be set to the cell's desired content width because this value will be used if the table has no columns or if its column is being packed.

Example 2: Packing columns

Listing 2 (snippet) demonstrates the use of SWT.MeasureItem to specify cell widths when a table column is packed.

1 Display display = new Display();
2 Shell shell = new Shell(display);
3 shell.setBounds(10,10,400,200);
4 Table table = new Table(shell, SWT.NONE);
5 table.setBounds(10,10,350,150);
6 table.setHeaderVisible(true);
7 table.setLinesVisible(true);
8 final TableColumn column0 = new TableColumn(table, SWT.NONE);
9 column0.setWidth(100);
10 final TableColumn column1 = new TableColumn(table, SWT.NONE);
11 column1.setWidth(100);
12 column0.addListener(SWT.Selection, new Listener() {
13    public void handleEvent(Event event) {
14       column0.pack();
15    }
16 });
17 column1.addListener(SWT.Selection, new Listener() {
18    public void handleEvent(Event event) {
19       column1.pack();
20    }
21 });
22 for (int i = 0; i < 5; i++) {
23    TableItem item = new TableItem(table, SWT.NONE);
24    item.setText(0, "item " + i + " col 0");
25    item.setText(1, "item " + i + " col 1");
26 }
27 table.addListener(SWT.MeasureItem, new Listener() {
28    public void handleEvent(Event event) {
29       event.width *= 2;
30    }
31 });
32 shell.open();
33 while (!shell.isDisposed()) {
34    if (!display.readAndDispatch()) display.sleep();
35 }
36 display.dispose();

Listing 2. Specifying custom cell content widths that are used by TableColumn.pack() to size a column

Lines 1-3:
Creates a display and shell, and sets the shell's bounds.

Lines 4-7:
Creates the table, sets its bounds, and sets its header and lines to be visible.

Lines 8-11:
Creates two table columns and sets the initial width of each to 100 pixels.

Lines 12-21:
Adds an SWT.Selection listener to each of the table's columns. These listeners will invoke pack() on the column whenever its header is clicked by the user.

Lines 22-26:
Creates the table's items.

Lines 27-28:
Adds an SWT.MeasureItem listener to the table, which will be invoked whenever the size of a cell's content is needed.

Line 29:
Sets the event's width field to double the default width of the cell. This specifies that the width of the cell should be this value regardless of its content.

Lines 32-36:
Opens the shell, runs the event loop until the shell has been disposed, and disposes the display just before exiting.

Figure 3 shows a screenshot of the snippet in Listing 2 running after each of the table's columns have been packed by clicking on their headers. Note that the columns have been packed to a width that is double of what is needed as a result of the SWT.MeasureItem listener in line 29. Figure 4 shows a screenshot of the same snippet running with lines 27 through 31 commented out, which leaves the table's columns to pack to their default widths.


Figure 3. Screenshot of Listing 2 running after the table's columns have been packed using the cell content sizes specified in theSWT.MeasureItem listener


Figure 4. Screenshot of Listing 2 running after the table's columns have been packed using the default cell sizes

SWT.EraseItem

SWT.EraseItem is sent just before the background of a cell is about to be drawn. The background consists of the cell's background color or the selection background if the item is selected. This event allows a client to custom draw one or both of these. Also, this event allows the client to indicate whether the cell's default foreground should be drawn following the drawing of the background.

When this event is received the cell has been filled with either the table's background color or the portion of its background image that intersects with the cell. This event comes pre-configured with the following fields:

  • item: the item
  • index: the column index of item being drawn
  • x, y: the table-relative co-ordinates of the top-left corner of the cell
  • width, height: the width and height of the full cell, or the content width of the cell if the table has no columns; if these values were previously set by an SWT.MeasureItem listener then they are the same here
  • gc: the GC configured with the default foreground, background, font and clipping for the cell
  • detail: the logical OR of one or more of the following bits, indicating what will be drawn by default:
    • SWT.FOREGROUND: this bit will be set if the default cell foreground will be drawn once the background has been drawn (default is true)
    • SWT.BACKGROUND: this bit will be set if either a cell-specific or item-specific background color will be drawn for this cell (ie.- a color has previously been set with either TableItem.setBackground(Color) or TableItem.setBackground(int, Color))
    • SWT.SELECTED: this bit will be set if the selection will be drawn for this cell, implying that this item is selected
    • SWT.FOCUSED: this bit will be set if the focus rectangle will be drawn for this cell, implying that this item is the focus item in the table
    • SWT.HOT: (@since 3.3) this bit will be set if the mouse hover background will be drawn for this cell (not all platforms draw this)
  • doit: this boolean indicates whether the table will do the drawing specified in the detail field once this listener has completed (default is true)

The listener is responsible for modifying the event to specify the elements that will be custom drawn (if any), and then doing the work. This is done by clearing certain bits in the detail field, or by setting the doit field to false to indicate that the listener will do all drawing for the cell (usually in combination with an SWT.PaintItem listener).

Example 3: Custom drawing item selection

Listing 3 (snippet) demonstrates the use of SWT.EraseItem to custom draw the item selection rectangle in a table.

1 Display display = new Display();
2 Shell shell = new Shell(display);
3 final Color red = display.getSystemColor(SWT.COLOR_RED);
4 final Color yellow = display.getSystemColor(SWT.COLOR_YELLOW);
5 final Table table = new Table(shell, SWT.FULL_SELECTION);
6 table.setHeaderVisible(true);
7 new TableColumn(table, SWT.NONE).setWidth(100);
8 new TableColumn(table, SWT.NONE).setWidth(100);
9 new TableColumn(table, SWT.NONE).setWidth(100);
10 for (int i = 0; i < 5; i++) {
11    TableItem item = new TableItem(table, SWT.NONE);
12    item.setText(0, "item " + i + " col 0");
13    item.setText(1, "item " + i + " col 1");
14    item.setText(2, "item " + i + " col 2");
15 }
16 table.pack();
17 table.addListener(SWT.EraseItem, new Listener() {
18    public void handleEvent(Event event) {
19       event.detail &= ~SWT.HOT;
20       if ((event.detail & SWT.SELECTED) == 0) return; /* item not selected */
21       int clientWidth = table.getClientArea().width;
22       GC gc = event.gc;
23       Color oldForeground = gc.getForeground();
24       Color oldBackground = gc.getBackground();
25       gc.setForeground(red);
26       gc.setBackground(yellow);
27       gc.fillGradientRectangle(0, event.y, clientWidth, event.height, false);
28       gc.setForeground(oldForeground);
29       gc.setBackground(oldBackground);
30       event.detail &= ~SWT.SELECTED;
31    }
32 });
33 shell.pack();
34 shell.open();
35 while (!shell.isDisposed()) {
36    if (!display.readAndDispatch()) display.sleep();
37 }
38 display.dispose();

Listing 3: Custom drawing item selection

Lines 1-2:
Creates a display and shell.

Lines 3-4:
Obtains the system's red and yellow colors, which will be used for drawing the custom selection.

Lines 5-6:
Creates the table and sets its header to be visible. The table's style is specified to be SWT.FULL_SELECTION since the custom-drawn selection will span the full table width.

Lines 7-9:
Creates three table columns and sets the initial width of each to 100 pixels.

Lines 10-15:
Creates the table's items.

Line 16:
Packs the table to its preferred size.

Lines 17-18:
Adds an SWT.EraseItem listener to the table, which will be invoked whenever the background of a cell is about to be drawn.

Line 19:
Clears the SWT.HOT bit from the event's detail field to ensure that hover backgrounds are not natively drawn.

Line 20:
Checks the detail field for the SWT.SELECTED bit, and returns out of the listener if it is not there since there is no selection to draw.

Line 21:
Gets the table's client width, to be used for drawing the cell's selection.

Lines 22-24:
Obtains the GC to draw on from the event and stores its foreground and background colors for the purpose of restoring them later.

Lines 25-27:
Draws the custom selection rectangle using a gradient that spans from red to yellow. Line 26 specifies the full width of the item as the gradient bounds so that the color range will span the table width properly. Since the GC's clipping is pre-configured to the bounds of the cell, only this portion of this gradient drawing will appear.

Lines 28-29:
Restores the GC's foreground and background colors to their previous values.

Line 30:
Clears the SWT.SELECTED bit from the event's detail field to indicate that the default selection should not be drawn for this cell. Note that this item is still considered to be logically selected in the table.

Lines 33-38:
Packs and opens the shell, runs the event loop until the shell has been disposed, and disposes the display just before exiting.

Figure 5 shows a screenshot of the snippet in Listing 3 running. Though the selection gradient appears to be one continuous rectangle, it is actually drawn three times, each clipped to its respective cell.


Figure 5. Screenshot of Listing 3 running, which uses an SWT.EraseItem listener to draw a custom selection

Example 4: Custom drawing cell backgrounds

Listing 4 (snippet) demonstrates the use of SWT.EraseItem to custom draw cell backgrounds in a table with no columns. This example modifies the default clipping of the GC to display gradient rectangles that represent temperature ranges.

1 final String[] MONTHS = {
2    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4 }
5 final int[] HIGHS = {-7, -4, 1, 11, 18, 24, 26, 25, 20, 13, 5, -4};
6 final int[] LOWS = {-15, -13, -7, 1, 7, 13, 15, 14, 10, 4, -2, -11};
7 final int SCALE_MIN = -30; final int SCALE_MAX = 30;
8 final int SCALE_RANGE = Math.abs(SCALE_MIN - SCALE_MAX);
9 Display display = new Display();
10 Shell shell = new Shell(display);
11 shell.setBounds(10,10,400,350);
12 shell.setText("Ottawa Average Daily Temperature Ranges");
13 final Color blue = display.getSystemColor(SWT.COLOR_BLUE);
14 final Color white = display.getSystemColor(SWT.COLOR_WHITE);
15 final Color red = display.getSystemColor(SWT.COLOR_RED);
16 final Image parliamentImage = new Image(display, "./parliament.jpg");
17 final Table table = new Table(shell, SWT.NONE);
18 table.setBounds(10,10,350,300);
19 table.setBackgroundImage(parliamentImage);
20 for (int i = 0; i < 12; i++) {
21    TableItem item = new TableItem(table, SWT.NONE);
22    item.setText(MONTHS[i] + " (" + LOWS[i] + "C..." + HIGHS[i] + "C)");
23 }
24 final int clientWidth = table.getClientArea().width;
25 table.addListener(SWT.MeasureItem, new Listener() {
26    public void handleEvent(Event event) {
27       int itemIndex = table.indexOf((TableItem)event.item);
28       int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
29       event.width = rightX;
30    }
31 });
32 table.addListener(SWT.EraseItem, new Listener() {
33    public void handleEvent(Event event) {
34       int itemIndex = table.indexOf((TableItem)event.item);
35       int leftX = (LOWS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
36       int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
37       GC gc = event.gc;
38       Rectangle clipping = gc.getClipping();
39       clipping.x = leftX;
40       clipping.width = rightX - leftX;
41       gc.setClipping(clipping);
42       Color oldForeground = gc.getForeground();
43       Color oldBackground = gc.getBackground();
44       gc.setForeground(blue);
45       gc.setBackground(white);
46       gc.fillGradientRectangle(
         event.x, event.y, event.width / 2, event.height, false);
47       gc.setForeground(white);
48       gc.setBackground(red);
49       gc.fillGradientRectangle(
         event.x + event.width / 2, event.y, event.width / 2, event.height, false);
50       gc.setForeground(oldForeground);
51       gc.setBackground(oldBackground);
52       event.detail &= ~SWT.BACKGROUND;
53       event.detail &= ~SWT.HOT;
54    }
55 });
56 shell.open();
57 while (!shell.isDisposed()) {
58    if (!display.readAndDispatch()) display.sleep();
59 }
60 parliamentImage.dispose();
61 display.dispose();

Listing 4. Custom drawing item backgrounds

Lines 1-8:
Defines constants that will be used to set the table's item data and to draw item backgrounds.

Lines 9-12:
Creates a display and shell, and sets the shell's bounds and title.

Lines 13-15:
Obtains the system's blue, white and red colors, which will be used for drawing item backgrounds.

Line 16:
Loads an image that will be set into the table as the background.

Lines 17-18:
Creates the table with no columns and sets its bounds.

Line 19:
Sets the background image into the table.

Lines 20-23:
Creates the table's items.

Line 24:
Stores the table's client width for later use when drawing the item backgrounds.

Lines 25-26:
Adds an SWT.MeasureItem listener to the table so that item sizes can be specified.

Lines 27-29:
Computes the right bound of the item in the event's item field and sets this value into the event's width field.

Lines 32-33:
Adds an SWT.EraseItem listener to the table so that item backgrounds can be custom drawn.

Lines 34-36:
Gets the item from the event's item field and computes the left and right bounds that its temperature bar should be drawn with.

Lines 37-41:
Updates the clipping of the GC in the event's gc field to the bounds that were computed for this item's temperature bar.

Lines 42-43:
Stores the GC's foreground and background colors for the purpose of restoring them later.

Lines 44-46:
Draws the left half of the custom background rectangle with a gradient that spans from blue to white. The portion of this rectangle that intersects with the GC's clipping bounds that were set in line 41 will ultimately appear.

Lines 47-49:
Draws the right half of the custom background rectangle with a gradient that spans from white to red. The portion of this rectangle that intersects with the GC's clipping bounds that were set in line 41 will ultimately appear.

Lines 50-51:
Restores the GC's foreground and background colors to their previous values.

Line 52:
Clears the SWT.BACKGROUND bit from the event's detail field to indicate that the default background should not be drawn for this cell.

Line 53:
Clears the SWT.HOT bit from the event's detail field to ensure that hover backgrounds are not natively drawn.

Lines 56-61:
Opens the shell, runs the event loop until the shell has been disposed, and disposes the background image and display just before exiting.

Figure 6 shows a screenshot of the snippet in listing 4 running.


Figure 6. Screenshot of Listing 4 running, which uses an SWT.EraseItem listener to draw custom item backgrounds


SWT.PaintItem

SWT.PaintItem is sent for a cell just after its default foreground contents have been drawn. This event allows a client to augment the cell, or to completely draw the cell's content. This event always comes pre-configured with the following fields:

  • item: the item
  • index: the column index of item being drawn
  • x, y: the table-relative co-ordinates of the top-left corner of the cell's content (ie.- its image or text)
  • width, height: the width and height of the cell's content; if these values were previously set by an SWT.MeasureItem listener then they are the same here
  • gc: the GC configured with the default foreground, background, font and clipping for the cell
  • detail: the logical OR of zero or more of the following bits:
    • SWT.SELECTED: this bit will be set if the item is selected
    • SWT.FOCUSED: this bit will be set if the item is the table's focus item
    • SWT.HOT: (@since 3.3) this bit will be set if the mouse hover background will be drawn for this cell (not all platforms draw this)

The purpose of the x and y fields are to indicate the location for custom drawing. These values take into account decorations such as checkboxes and tree indentation.

Example 5: Enhancing the native content

Listing 5 (snippet) demonstrates the use of SWT.PaintItem to augment the default drawing of tree items. It uses the x, y and widthfields in the SWT.PaintItem event to draw an image to the right of alternating items. This is an example of a simple drawing enhancement that enriches an item's default content while still maintaining its native appearance.

1 Display display = new Display();
2 Shell shell = new Shell(display);
3 shell.setBounds(10, 10, 350, 200);
4 Image xImage = new Image (display, 16, 16);
5 GC gc = new GC(xImage);
6 gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
7 gc.drawLine(1, 1, 14, 14);
8 gc.drawLine(1, 14, 14, 1);
9 gc.drawOval(2, 2, 11, 11);
10 gc.dispose();
11 final int IMAGE_MARGIN = 2;
12 final Tree tree = new Tree(shell, SWT.CHECK);
13 tree.setBounds(10, 10, 300, 150);
14 TreeItem item = new TreeItem(tree, SWT.NONE);
15 item.setText("root item");
16 for (int i = 0; i < 4; i++) {
17    TreeItem newItem = new TreeItem(item, SWT.NONE);
18    newItem.setText("descendent " + i);
19    if (i % 2 == 0) newItem.setData(xImage);
20    item.setExpanded(true);
21    item = newItem;
22 }
23 tree.addListener(SWT.MeasureItem, new Listener() {
24    public void handleEvent(Event event) {
25       TreeItem item = (TreeItem)event.item;
26       Image trailingImage = (Image)item.getData();
27       if (trailingImage != null) {
28          event.width += trailingImage.getBounds().width + IMAGE_MARGIN;
29       }
30    }
31 });
32 tree.addListener(SWT.PaintItem, new Listener() {
33    public void handleEvent(Event event) {
34       TreeItem item = (TreeItem)event.item;
35       Image trailingImage = (Image)item.getData();
36       if (trailingImage != null) {
37          int x = event.x + event.width + IMAGE_MARGIN;
38          int itemHeight = tree.getItemHeight();
39          int imageHeight = trailingImage.getBounds().height;
40          int y = event.y + (itemHeight - imageHeight) / 2;
41          event.gc.drawImage(trailingImage, x, y);
42       }
43    }
44 });
45 shell.open();
46 while (!shell.isDisposed()) {
47    if (!display.readAndDispatch()) display.sleep();
48 }
49 xImage.dispose();
50 display.dispose();

Listing 5. Using SWT.PaintItem to augment the default drawing of items

Lines 1-3:
Creates a display and shell, and sets the shell's bounds.

Lines 4-11:
Creates the image that will be used in this example, and defines a constant that will be used when drawing item foregrounds.

Lines 12-13:
Creates the tree with no columns and sets its bounds.

Lines 14-22:
Creates the tree's items. Note that line 19 sets the trailing image as the item data for alternating items. This data will be used when custom drawing the item foregrounds.

Lines 23-24:
Adds an SWT.MeasureItem listener to the tree so that item sizes can be specified.

Lines 25-29:
Gets the item from the event's item field, and if it has a trailing image, updates the event's width field to include space for the item's default content plus the trailing image.

Lines 32-33:
Adds an SWT.PaintItem listener to the tree so that the default foreground can be augmented.

Lines 34-42:
Gets the tree item from the event's item field, and if it has a trailing image set, draws the image to the right of the item's text. The event's x, y and width fields are used to compute the position of the image.

Lines 45-50:
Opens the shell, runs the event loop until the shell has been disposed, and disposes the images and display just before exiting.

Figure 7 shows a screenshot of the snippet in listing 5 running. It has the appearance of a native tree but also includes trailing images.


Figure 7. Screenshot of Listing 5 running, which uses an SWT.PaintItem listener to augment the default drawing of items in a tree

Example 6: Custom drawing complete item contents

Listing 6 (snippet) demonstrates the use of SWT.PaintItem to draw items with multiple lines of text, which is not currently supported in tables. It clears the SWT.FOREGROUND bit from the detail field in the SWT.EraseItem event, and then draws the text in theSWT.PaintItem event.

1 final int COLUMN_COUNT = 4;
2 final int ITEM_COUNT = 8;
3 final int TEXT_MARGIN = 3;
4 Display display = new Display();
5 Shell shell = new Shell(display);
6 final Table table = new Table(shell, SWT.FULL_SELECTION);
7 table.setHeaderVisible(true);
8 table.setLinesVisible(true);
9 for (int i = 0; i < COLUMN_COUNT; i++) {
10    new TableColumn(table, SWT.NONE);
11 }
12 for (int i = 0; i < ITEM_COUNT; i++) {
13    TableItem item = new TableItem(table, SWT.NONE);
14    for (int j = 0; j < COLUMN_COUNT; j++) {
15       String string = "item " + i + " col " + j;
16       if ((i + j) % 3 == 1) {
17          string +="\nnew line1";
18       }
19       if ((i + j) % 3 == 2) {
20          string +="\nnew line1\nnew line2";
21       }
22       item.setText(j, string);
23    }
24 }
25 table.addListener(SWT.MeasureItem, new Listener() {
26    public void handleEvent(Event event) {
27       TableItem item = (TableItem)event.item;
28       String text = item.getText(event.index);
29       Point size = event.gc.textExtent(text);
30       event.width = size.x + 2 * TEXT_MARGIN;
31       event.height = Math.max(event.height, size.y + TEXT_MARGIN);
32    }
33 });
34 table.addListener(SWT.EraseItem, new Listener() {
35    public void handleEvent(Event event) {
36       event.detail &= ~SWT.FOREGROUND;
37    }
38 });
39 table.addListener(SWT.PaintItem, new Listener() {
40    public void handleEvent(Event event) {
41       TableItem item = (TableItem)event.item;
42       String text = item.getText(event.index);
43       /* center column 1 vertically */
44       int yOffset = 0;
45       if (event.index == 1) {
46          Point size = event.gc.textExtent(text);
47          yOffset = Math.max(0, (event.height - size.y) / 2);
48       }
49       event.gc.drawText(text, event.x + TEXT_MARGIN, event.y + yOffset, true);
50    }
51 });
52 for (int i = 0; i < COLUMN_COUNT; i++) {
53    table.getColumn(i).pack();
54 }
55 table.pack();
56 shell.pack();
57 shell.open();
58 while (!shell.isDisposed()) {
59    if (!display.readAndDispatch()) display.sleep();
60 }
61 display.dispose();

Listing 6. Using SWT.PaintItem to draw items with multiple lines of text

Lines 1-3:
Defines constants that will be used for creating and drawing the table's items.

Lines 4-5:
Creates a display and shell.

Lines 6-8:
Creates the table and sets its header and lines to be visible.

Lines 9-11:
Creates the table's columns.

Lines 12-24:
Creates the table's items. Item texts are set to values with one, two, or three lines of text.

Lines 25-26:
Adds an SWT.MeasureItem listener to the table so that item sizes can be specified.

Lines 27-31:
Gets the item and column index from the event, computes the bounds of its text, and uses this value to set the event's width and heightfields. TEXT_MARGIN is added to the bounds to create space for a small margin around the item's content.

Lines 34-38:
Adds an SWT.EraseItem listener to the table for the purpose of clearing the SWT.FOREGROUND bit from the event's detail field. This indicates that the default drawing of item foregrounds should not occur because the SWT.PaintItem listener will do this in full.

Lines 39-40:
Adds an SWT.PaintItem listener to the table so that item foregrounds can be custom drawn.

Lines 41-49:
Gets the text for the cell and draws it. The text is centered vertically within the cell for column 1, and draws top-aligned otherwise.

Lines 52-54:
Packs the table's columns to their preferred widths, using the values provided by the SWT.MeasureItem listener.

Lines 55-56:
Packs the table and shell to their preferred sizes.

Lines 57-61:
Opens the shell, runs the event loop until the shell has been disposed, and disposes the display just before exiting.

Figure 8 shows a screenshot of the snippet in Listing 6 running.


Figure 8. Screenshot of Listing 6 running, which uses an SWT.PaintItem listener to custom draw the table's items

 

分享到:
评论

相关推荐

    基于S7-300PLC与MCGS6.2的饮料罐装生产线自动化控制系统设计,包含仿真、程序、IO表与电气原理,实现自动操作、灌装报警及瓶数记录功能 ,基于PLC的饮料罐装生产线控制系统设计 S7-30

    基于S7-300PLC与MCGS6.2的饮料罐装生产线自动化控制系统设计,包含仿真、程序、IO表与电气原理,实现自动操作、灌装报警及瓶数记录功能。,基于PLC的饮料罐装生产线控制系统设计。 S7-300PLC MCGS6.2仿真 仿真,程序,IO表,电气原理图,6500字说明。 实现功能有: (1)系统通过开关设定为自动操作模式,一旦启动,则传送带的驱动电机启动并一直保持到停止开关动作或罐装设备下的传感器检测到一个瓶子时停止;瓶子装满饮料后,传送带驱动电机必须自动启动,并保持到又检测到一个瓶子或停止开关动作。 (2)当瓶子定位在灌装设备下时,停顿1秒,罐装设备开始工作,灌装过程为5秒钟,罐装过程应有报警显示,5秒后停止并不再显示报警。 (2)用两个传感器和若干个加法器检测并记录空瓶数和满瓶数,一旦系统启动,必须记录空瓶和满瓶数,设最多不超过99999999瓶。 (4)可以手动对计数器清零(复位)。 ,关键词:S7-300PLC; MCGS6.2仿真; 传送带驱动电机; 传感器检测; 瓶装; 空瓶数; 满瓶数; 报警显示; 自动操作模式; 灌装设备。,基于S7-300PLC的饮料罐装

    python加密货币时间序列预测源码+数据集-最新出炉.zip

    python加密货币时间序列预测源码+数据集-最新出炉 加密货币分析: 对各种加密货币的数据进行分析和研究。可能会使用到从各种来源收集的数据,包括但不限于加密货币的价格、市值、交易量、交易时间等信息。 探索加密货币市场的趋势和模式,例如价格的波动情况、不同加密货币之间的相关性等。 数据处理与操作: 可能使用 Python 语言(Kaggle 上常用的数据分析语言),并运用一些数据处理和分析的库,如 pandas 用于数据的读取、清洗、整理和转换操作,将原始的加密货币数据转换为更易于分析的格式。 可视化展示: 通过可视化工具,如 matplotlib 或 seaborn 库,将加密货币的信息以图表的形式展示出来,以帮助直观地理解数据中的关系和趋势。 统计分析或预测: 可能会进行一些基本的统计分析,如计算加密货币价格的均值、中位数、标准差等统计量,以描述数据的特征。 或者使用机器学习或时间序列分析的方法对加密货币的价格进行预测,根据历史数据预测未来价格走势。 例如,使用 scikit-learn 进行简单的回归分析: 数据挖掘与特征提取: 挖掘加密货币数据中的特征,如找出影响价格的关键因素,对数据中的特征进行筛选和提取,以帮助更好地理解加密货币的市场行为。

    面对程序设计GJava

    类和对象、继承、封装、多态、接口、异常

    TF_demo1_keras.ipynb

    gee python相关教程

    夜间灯光数据 2023年全球_中国夜间灯光数据合集(数据权威)

    夜间灯光强度(平均灯光强度)的高低反映了一个地区城市化发展的水平,平均灯光强度越高,说明该地区城市群越多,城市化程度越高。夜间灯光数据现在越来越广泛地应用于经济增长分析、经济地理、城市经济学、数字经济等众多领域。 本数据包括三套: [1]中国类DMSP-OLS灯光数据1992-202 [2]中国超长序列灯光数据1984-2020 [3]全球类NPP-VIIRS夜间灯光数据2000-2022 包括:全国各省、市、县夜间灯光数据 矫正后夜间灯光数据 细分:标准差、平均值、总值、最大值和最小值

    工程项目总监绩效考核表.xls

    工程项目总监绩效考核表

    (数据权威)各省份一般公共预算转移支付数据(附送地级市转移支付)

    首先解释一下什么叫转移支付。其实,这和养老金的中央调剂是一样的。 每年,地方都要向中央缴纳财政。而中央又要根据各地方的财政实力,给予转移支付。比如一些经济弱省,本身财政收入就不够支出的,还得上交一部分给中央,怎么维持财政运转?由于各省市直接的财政收入能力存在差异,中央为实现各个地方的公共服务水平平等,于是便有了财政转移支付制度。 简单理解就是富省养穷省。 2022年全国一般预算内财政收入203703亿元,给地方转移支付了97144.75亿元,转移支付数额创下新高。

    基于门控卷积和堆叠自注意力的离线手写汉字识别算法研究.pdf

    基于门控卷积和堆叠自注意力的离线手写汉字识别算法研究.pdf

    逐月中国工业用水空间分布数据集(数据权威)

    【数据介绍】   作为第二大人类部门用水,高质量的工业用水格网数据对于水资源研究和管理至关重要。中国工业用水格网数据(China Industrial Water Withdrawal dataset, CIWW)基于超过 40 万家企业数据、月度工业产品产量数据和连续工业用水统计数据制作得到的一套1965-2020年逐月中国工业用水数据集,其空间分辨率为 0.1°和 0.25°。数据集包括工业用水、企业数量和企业生产总值(辅助数据)等变量,可被用于水文、地理学、环境、可持续发展等方面科学研究。 【数据来源】   数据来源为《中国经济普查年鉴》(省级工业取水量、工业产出)、《中国工业企业数据库》(企业地理位置、产值)、《中国工业产品产量数据库》(工业产品月生产量),以及《中国水资源公报》和(Zhou et al, 2020, PNAS)的工业用水量数据。 【数据处理】 首先通过2008年企业分布数据、经济普查年鉴中分省分部门的工业用水量和工业产值计算得到分省分部门工业用水效率和工业产品产量数据,得到了2008年逐月工业用水数据。然后结合中国水资源公报和相关文献中省级工业用水数据,以2008年工业用水的时空格局作为基础分配工业用水数据,最终得到1965-2020年逐月工业用水的格网数据。详细方法见High-resolution mapping of monthly industrial water withdrawal in China from 1965 to 2020 (Hou et al, 2024, ESSD). 将数据集与统计数据记录和其他数据集进行了验证,结果表示在时间尺度和空间尺度上都与统计数据具有一致性,相比已有工业用水数据有更好的精度。

    65 -质量管理部经理绩效考核表1.xlsx

    65 -质量管理部经理绩效考核表1

    11 -电脑部经理绩效考核表1.xlsx

    11 -电脑部经理绩效考核表1

    大英赛写作必备:实用英语万能句及其应用技巧

    内容概要:本文提供了针对大学生英语竞赛写作准备的重要资源——一系列通用的英文句子模板。这些模板涵盖了现代经济社会的各种话题,从科技进步到环境保护,以及个人品质和社会责任等,并且适用于论述类文章、观点对比和个人见解的表达。文章通过对每一句话的应用环境解释和语法提示,确保使用者可以在实际写作中正确且有效地应用这些表达方式。 适合人群:正在准备参加大学生英语竞赛的学生及其他希望提高书面表达能力的学习者。 使用场景及目标:考生能够在竞赛时间内迅速构建思路完整的文章,增强语言表达的流利性和规范性;帮助学习者积累高级词汇,提升英语写作水平并培养良好的思维逻辑。 阅读建议:结合历年优秀范文进行深入学习,熟悉不同类型话题下的表述方法;练习将提供的句子融入自身创作的文章中,通过不断修订和完善来巩固记忆。同时也可以用于日常的英语写作训练当中。

    法律事务专员绩效考核表.xls

    法律事务专员绩效考核表

    apache-commons-digester-javadoc-1.8.1-19.el7.x64-86.rpm.tar.gz

    1、文件内容:apache-commons-digester-javadoc-1.8.1-19.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/apache-commons-digester-javadoc-1.8.1-19.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装

    永磁同步电机磁场定向控制(矢量控制)Simulink仿真模型波形展现与解析,永磁同步电机的磁场定向控制(矢量控制)simulink仿真模型,波形完美 ,核心关键词:永磁同步电机; 磁场定向控制(矢量控

    永磁同步电机磁场定向控制(矢量控制)Simulink仿真模型波形展现与解析,永磁同步电机的磁场定向控制(矢量控制)simulink仿真模型,波形完美 ,核心关键词:永磁同步电机; 磁场定向控制(矢量控制); Simulink仿真模型; 波形完美;,永磁同步电机矢量控制仿真模型:磁场完美调控,波形精确无误

    07 -储运部经理绩效考核表1.xlsx

    07 -储运部经理绩效考核表1

    OQC检验员(成品出货检验员)绩效考核表.xls

    OQC检验员(成品出货检验员)绩效考核表

    基于Matlab2020b的电机控制算法:无传感FOC算法Simulink仿真模型及实践指导,定位+电流闭环强拖+ 角度渐变切+ 速度电流双闭环+ 无传感器角度估算SMO+ PLL 控制方式 Sim

    基于Matlab2020b的电机控制算法:无传感FOC算法Simulink仿真模型及实践指导,定位+电流闭环强拖+ 角度渐变切+ 速度电流双闭环+ 无传感器角度估算SMO+ PLL 控制方式 Simulink 仿真模型 (Matlab2020b版本)以及教授模型搭建 这是一种常用的无传感FOC电机控制算法,掌握这种算法的基本原理,并有仿真模型在手,就可以用它来指导实践中的程序调试,做到实际项目不盲目调试。 模型特点: 1. 所有模块都做到了模块化,各个模块分区清楚,结构清晰。 2. 所有电机和控制参数均在m文件中体现,变量注释清楚,随用随改。 3. 速度环和电流环PI参数均实现自动整定。 4. 模型采用标幺值系统。 5. 各状态切使用stateflow,模型结构清晰。 6.通用表贴和内嵌式电机。 ,定位;电流闭环强拖;角度渐变切换;速度电流双闭环;无传感器角度估算SMO;PLL控制方式;Simulink仿真模型;Matlab2020b版本建模;教授模型搭建;模块化设计;参数自动整定;标幺值系统;Stateflow应用;通用表贴和内嵌式电机。,基于Matlab 2020b的FOC电机

Global site tag (gtag.js) - Google Analytics