In this chapter, you learn how to use certain controls to present numerical values. They are:
A scale is a selectable UI component that presents a range of continuous numeric integer values. A slider works much like a scale does, except the appearance of a slider differs from that of a scale. Unlike a scale or a slider, a progress bar is not a selectable UI object but it can be used to display the progress of a lengthy operation.
A scale is a selectable user interface object presenting a range of continuous numeric integer values. The Scale control can have two styles: SWT.VERTICAL and SWT.HORIZONTAL. These two scale styles are shown in Figure 13-1. The scale at the top has the SWT.HORIZONTAL style, whereas the scale below has the SWT.VERTICAL style. If you do not specify a style when you are creating a scale, the default is SWT.HORIZONTAL.
Figure 13-1
For a scale with the SWT.HORIZONTAL style, the minimum value is selected when the thumb (the small bar) is on the left end of the scale and the maximum is selected when the thumb is on the right end of the scale. If you rotate a horizontal scale 90 degrees clockwise, you'll get a vertical scale. For a vertical scale, the minimum value is selected when the thumb is on the top end of the scale. Sometimes, this value representation is awkward; the user usually likes to see the maximum value at the top and the minimum at the bottom. You cannot configure a scale to change its value representation behavior, but you can easily create an illusion (an example of this is given later in the chapter).
There is only one constructor in the Scale class:
public Scale(Composite parent, int style)
The Scale class provides several methods for you to access its minimum and maximum values:
public void setMinimum(int value) public void setMaximum(int value) public int getMinimum() public int getMaximum()
The default minimum and maximum values on Windows are 0 and 100, respectively.
You can select values on scales through the mouse or the keyboard. When you are using the keyboard, you can use Page Up and Page Down keys for coarse tuning and the down/up arrow keys for fine-tuning. The increment/decrement unit amount for coarse tuning can be gotten and set using the following methods:
public int getPageIncrement() public void setPageIncrement(int pageIncrement)
Similarly, you can use the following method to get/set the increment/decrement unit amount for fine-tuning:
public int getIncrement() public void setIncrement(int increment)
To get and set the current selected value, you can use the getSelection method and the setSelection method:
public int getSelection() public void setSelection(int value)
Finally, if you need to listen for selection events, you can register one or more selection listeners using the addListener method for untyped listeners or the addSelectionListener method for typed listeners:
public void addSelectionListener(SelectionListener listener)
The detail field of the Event object gives selection details, such as whether the selection is made through the mouse (SWT.DRAG) or the keyboard (SWT.ARROW_DOWN, SWT.PAGE_UP, SWT.HOME, and so on).
The following code creates a volume-adjusting utility, as shown in Figure 13-2.
Figure 13-2
... Scale scale; Text value; shell.setLayout(new GridLayout(1, true)); Label label = new Label(shell, SWT.NULL); label.setText("Volume:"); scale = new Scale(shell, SWT.VERTICAL); scale.setBounds(0, 0, 40, 200); scale.setMaximum(20); scale.setMinimum(0); scale.setIncrement(1); scale.setPageIncrement(5); scale.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int perspectiveValue = scale.getMaximum() - scale.getSelection() + scale.getMinimum(); value.setText("Vol: " + perspectiveValue); } }); value = new Text(shell, SWT.BORDER | SWT.SINGLE); ...
A vertical scale is created in the code. There are 20 levels of volume and an additional level 0 to represent the mute volume. The setIncrement method and the setPageIncrement method are used to configure the increment unit amounts for fine-tuning and coarse-tuning. A selection listener is added to listen to selection events. To overcome the awkward value presentation of vertical scales, you use "perspective" values instead of the raw values returned by the getSelection method. When a value is selected, its perspective value is printed in the text field.
A slider works exactly as a scale does, except that the appearance of a slider is different.
All the methods of the Scale class introduced previously apply to the Slider class, too. The Slider class offers the following additional methods over the Scale class:
public int getThumb() public void setThumb(int value) public void setValues(int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement)
The getThumb method and the setThumb method can be used to get/set the thumb size in pixels. However, not all operating systems support the setThumb method. The setValues method is a facade method that you can use to set various values in one call.
public void setValues(int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement)
Let's rewrite the volume adjusting program using a slider (see Figure 13-3).
Figure 13-3
... Slider slider; Text value; shell.setLayout(new GridLayout(1, true)); Label label = new Label(shell, SWT.NULL); label.setText("Volume:"); slider = new Slider(shell, SWT.VERTICAL); slider.setBounds(0, 0, 40, 200); slider.setMaximum(20); slider.setMinimum(0); slider.setIncrement(1); slider.setPageIncrement(5); slider.setThumb(4); slider.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int perspectiveValue = slider.getMaximum() - slider.getSelection() + slider.getMinimum(); value.setText("Vol: " + perspectiveValue); } }); value = new Text(shell, SWT.BORDER | SWT.SINGLE); ...
If you compare the preceding code with the code in the previous section, the only difference (with the exception of variable names and types) is that the setThumb method is highlighted in bold. If you look carefully at the UIs, you may find there is another difference. With the scale version of the volume adjusting program, you can adjust volume from level 0 to 20. However, the slider version allows you to set only levels 4 to 20. The cause of this problem is that the selectable range of a slider is [minimum, maximum – thumbSize]. To fix it, you need to set the maximum value to 24:
slider.setMaximum(24);
and replace the perspective calculation code with the following line:
int perspectiveValue = slider.getMaximum() - slider.getSelection() + slider.getMinimum() - slider.getThumb();
Now, you can select any level from 0 to 20 (see Figure 13-4).
Figure 13-4
Unlike a scale or a slider, a progress bar is an unselectable UI object that is usually used to display progress of a lengthy operation. In SWT, the ProgressBar class is used to represent a progress bar.
Styles supported by ProgressBar are as follows:
Figure 13-5
To get/set the minimum allowed value for a progress bar, you can use the following methods:
public int getMinimum() public void setMinimum(int value)
For the method setMinimum, if the passed argument is less than 0 or larger than the current maximum value, this method ignores the request. The default minimum and maximum values are 0 and 100, respectively.
Similarly, the following are methods to get/set the maximum allowed value:
public int getMaximum() public void setMaximum(int value)
If the value passed to setMaximum is not greater than the current minimum value, the request is ignored.
To get and set the current selected value, you can use the following methods:
public int getSelection() public void setSelection(int value)
To understand how progress bars work, let's build a simple number counting program, as shown in Figure 13-6.
Figure 13-6
When the user presses the button, the program starts to count numbers from 0 to 10 and the progress is shown in the progress bar under the button (see Figure 13-7).
Figure 13-7
The code to implement the preceding program is as follows:
... Button button = new Button(shell, SWT.BORDER); button.setText("Start to count"); ProgressBar progressBar = new ProgressBar(shell, SWT.SMOOTH); progressBar.setMinimum(0); progressBar.setMaximum(10); final Thread countThread = new Thread(){ public void run() { for(int i=0; i<=10; i++) { final int num = i; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } shell.getDisplay().asyncExec(new Runnable(){ public void run() { if(button.isDisposed() || progressBar.isDisposed()) return; button.setText("Counting: " + num); progressBar.setSelection(num); } }); } } }; button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { button.setEnabled(false); countThread.start(); } });
First, a button and a progress bar are created. We then set the minimum and maximum values for the progress bar to 0 and 10, respectively. A thread is created to perform the counting task in a separate nonUI thread. A selection listener is added to the button to listen to selection events. If the user clicks the button, the counting thread is triggered to start. When counting each number, the counting thread makes a UI update request using the asyncExec method. For a complete discussion of threading and UI updating, see Chapter 4.
In many cases, you may want to display a string representing the percentage of the job completed in the center of a progress bar (see Figure 13-8).
Figure 13-8
The simplest approach to implementing this behavior is to add a paint listener to the progress bar and draw the percentage in the graphics context of the progress bar:
progressBar.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { // The string to be drawn on the progress bar. String string = (progressBar.getSelection() * 1.0 / (progressBar.getMaximum()-progressBar.getMinimum()) * 100) + "%"; Point point = progressBar.getSize(); Font font = new Font(shell.getDisplay(),"Courier",10,SWT.BOLD); e.gc.setFont(font); e.gc.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_WHITE)); FontMetrics fontMetrics = e.gc.getFontMetrics(); int stringWidth = fontMetrics.getAverageCharWidth() * string.length(); int stringHeight = fontMetrics.getHeight(); e.gc.drawString(string, (point.x-stringWidth)/2 , (point.y-stringHeight)/2, true); font.dispose(); } });
First, the string to be displayed is determined. Then you set the font for the graphics context. To center the string, you need to know its width and height in pixels. To do this, you use the FontMetrics object obtained from the graphics context. The string is then drawn to the progress bar using the drawString method of the graphics context. Finally, the font object is disposed of.
You do not hard code any value in the paint listener so you can add the paint listener to any SWT progress bars without changing the code.
You'll also notice that the string in the progress bar looked ugly in the program you just ran (look closely at Figure 13-9).
Figure 13-9
In order for the string to be displayed properly, you have to mark the progress bar to be painted completely, including the background, by using the redraw method:
shell.getDisplay(). asyncExec(new Runnable(){ public void run() { if(button.isDisposed() || progressBar.isDisposed()) return; button.setText("Counting: " + num); progressBar.setSelection(num); progressBar.redraw(); } });
The new line added is highlighted in bold. Without calling the redraw method, the system will not repaint the background of the progress bar and, as a result, the string may not be displayed clearly (see Figure 13-9).
Now all three controls have been introduced. You use a scale or a slider to let the user select a value from a range of continuous numeric integer values. To display the progress of a lengthy operation, you can use a progress bar.
This chapter covered three SWT controls that are capable of presenting numerical values. The controls include Scale, Slider, and ProgressBar. A scale and a slider differ in their appearance; however, both of them function as a selectable UI component presenting a range of continuous numeric integer values. Unlike a scale or a slider, a progress bar is an unselectable UI component that is often used to display the progress of a lengthy operation. The next chapter covers the SWT widgets that have not been covered yet.
Part I - Fundamentals
Part II - Design Basics
Part III - Dynamic Controls
Part IV - Application Development