Images
[Framework practical 7 of 7]
We now have a perfectly decent little application, however, there are a few of things we could do to improve it.
Firstly, we could resize the frame so that it showed the whole of the image whatever its size.
The code to
do this isn't especially hard; you just setSize
to something appropriate
in the Analyst
's paint
method. But what to set it to?
All Image objects have getWidth
and getHeight
methods that
take in an ImageObserver
. The best ImageObserver
is the frame
itself, so you can get the width of the image, thus:
int width = image.getWidth(this);
And height similarly. You can then use these to set the Analyst
's height and width.
Remember, you may also want to use Insets
, as we saw in the lecture.
Secondly, you may find that your images flicker quite a lot when displayed.
To be honest you'd rarely draw an image directly onto a frame: they're not really set up for
it. You may find it better to make a java.awt.Canvas
object as an instance variable within Analyst
,
and add it to the frame using Analyst
's inherited add
method just below
where you set up the menu etc. You can then draw on this in paint
. Canvas
is a chunk of
screen for drawing on. It will resize with the Analyst
frame and you shouldn't need to resize it.
public void paint (Graphics g) {
Image image = store.getDataAsImage();
Graphics gc = canvas.getGraphics();
// Resize Analyst here if we want.
gc.drawImage(image, 0, 0, this);
// note x and y now relative to canvas so no insets needed.
}
Thirdly, we might want to wait to display an image until we've read a proper one in.
At the moment the application shows a black square because we set the data
array in
Storage
up thus:
double data[][] = new double[300][300];
This fills it with zeros (primitive types have a default value of zero; objects have a default value of null
, i.e. "not set up").
This was because in earlier practicals we weren't reading data in, and I didn't want it throwing a whole bunch of "not set up" exceptions if your code
went wrong. However, now we're reading data in, we could do this:
double data[][] = null;
leaving the array not set up until the user uses the "Open..." MenuItem, thereby calling setData
with
a suitable data array. If we did this, we could then do the following to our
getDataAsImage
method:
public Image getDataAsImage() {
if (data != null) {
// Our Image making code.
return image;
} else {
return null;
}
}
And in our Analyst
's paint
method, this:
public void paint (Graphics g) {
Image image = store.getDataAsImage();
if (image != null) {
// Resize here if we want.
// drawImage
}
}
i.e. don't do anything if the image == null
, which it will be if store.getDataAsImage
has returned null
because the data
array is null
.
(if you do this, you might like to add the lines:
if (data == null) {
data = new double[300][300];
} else {
data = new double[data.length][data[0].length];
}
to the top of your setRandomData
method, so it still works if there's no data set up.)
Finally, you might like to try and link all your practical code with the code from the first assessment.
You've got code to do lots of jobs. It would be nice if you could could read some data in (or had a
menu item to generate some random data if you didn't have any), and then run your first assignment
process over the data and see the result. We'll leave that for you to play with, but feel free to
talk it through with us. In the meantime, here's a version of the IO
class (IO.java) that reads
in image files like gifs
and jpgs
and writes these formats as well, along with a satellite image of an
important and mysterious continent to manipulate
(sat.jpg), should you be interested.