Java Reference
In-Depth Information
files. Next, the
showOpenDialog
method is called to display an Open File dialog.
JFileChooser
also has a lot of additional options you can configure, such as filtering which files to show. The
result of this method is an integer determining whether the user selected a file or cancelled the
dialog, or an error occurred. Next, the
getSelectedFile
method retrieves your file. Note that
JFileChooser
still utilizes the legacy
File
class. Next, a built‐in utility class called
ImageIO
does
the heavy lifting regarding reading image files. This class reads in common file formats, such as
PNG, JPG, BMP, and GIF files, and returns a
BufferedImage
object to store the image data. Next,
it iterates over all pixels in the image and applies a simple trick to determine whether the pixel
color should be converted to a black pixel. Dark colors are converted to black, whereas light colors
are not; that is what the
if ((c.getBlue() < 128 || c.getRed() < 128 || c.getGreen()
< 128) && c.getAlpha() == 255)
line does. Once all the black pixels are gathered, the
paintPanel
object is instructed to add them.
6.
The
save
method works similarly. Here, a fresh image is constructed with the width and height
equal to the current width and height of the paint panel. Next, it loops over each pixel again and
sets them to black when necessary. Note that some additional logic is applied to make the filename
selected with
showSaveDialog
end in
.png
, as there is no way to force the
JFileChooser
to do
this for you. (This is because file extensions are just a convention to tell the operating system what
the default program should be to open files ending in a particular suffix. There is nothing prevent-
ing you from saving a PNG image as
image.txt
and opening it with an image editor afterward.)
7.
Now take a look at the
SimplePaintPanel
class. This class extends
JPanel
and implements a
mouse and mouse motion event listener by using the
MouseAdapter
class.
8.
The mouse‐related methods that are implemented are
mouseDragged
and
mousePressed
. The lat-
ter determines which button (left or right) is being pressed. When the mouse is dragged, it looks
at the mouse button currently being pressed and determines whether black pixels should be added
or removed. You might wonder why you can't just use
ev.getButton()
in the
mouseDragged
method to determine which mouse button is being pressed. The reason for this is that this will
always return 0, as
getButton()
only returns the button number when the state has changed.
Since you keep holding down the mouse button whilst dragging, no button state is changing. You
can, however, use
SwingUtilities.isLeftMouseButton(ev)
instead, which will work, but here
things were done manually to show off how the mouse event listener works as well.
9.
The second interesting aspect to note is the custom
paint
method for this class. First, the whole panel
surface is filled out with white, after which a pixel is drawn for each point in the
blackPixels
set.
10.
Finally, it is important to know that you should tell Java when “my surface has changed; you
should draw me again.” This is what is done with the
invalidate
method. A
repaint
call is
placed right after this to instruct Java to redraw the component (which will have Java make a call
to the
paint
method).
11.
You will notice this yourself when drawing quickly; the drawing code is horribly inefficient. There
are many reasons for this. First, working with a set of pixels is not ideal, especially not for larger
images. Second, Swing components were never really designed to perform high‐speed drawing
updates, which is what is done here while dragging. In a real painting application, you need to look
for better-suited drawing components (those exist). That said, this example helps to explain various
concepts, and custom drawing code can still be helpful whenever you know components will not
need to be redrawn continuously.
Search WWH ::
Custom Search