- Usage
- Development
Thanks for giving Balloon tip a try! You can now spice up your Java Swing applications with the balloon tip components provided by this small library. If you're new to Balloon tip, be sure to read the Getting started and Using Balloon tip sections to get familiar with the basics.
Requirements: You need Java 1.5 (or higher) to make use of Balloon tip.
Before diving in, let's take a quick look at the things that are included in the project's .zip-file:
Now that you know what is available in this release, let's get familiar with the features Balloon tip has to offer. The quickest way to do this is to try out the demo application. Simply double-click the balloontip-examples- … .jar-file to open the demo application.
If this doesn't work, you'll have to open up a console/command-line window and navigate into the Balloon tip-directory. Just enter the following command to start the demo application:
java -jar balloontip-examples- ... .jar
(Replace ”…” with the right version number.)
Balloon tip demo application
Once the application has started, you can start exploring many of Balloon tip's features. Just toy around with all possible settings and see what happens; this probably is the easiest way to learn the terminology that is used by the Balloon tip API.
Once you're done tinkering in the demo application, proceed to the Using Balloon tip section, which will teach you the basics in creating your own balloon tips.
The BalloonTip
class implements a basic balloon tip which is suited for most uses. A BalloonTip
instance can attach itself to about any visual component: a JButton
, JLabel
, JTextField
, … In order to create and show a BalloonTip
instance, all you need to do is construct one. Like most components in Swing, the BalloonTip
class comes with several constructors.
Starting off with the easiest constructor:
BalloonTip(JComponent attachedComponent, String text)
The attachedComponent
parameter is the JComponent
you want to attach your balloon tip to. The text
parameter is the text to be shown inside the balloon tip. For example, if the attached component were a JButton
called myButton
and you want the balloon to say “Hello world!”, you can do this as follows:
BalloonTip myBalloonTip = new BalloonTip(myButton, "Hello world!");
The newly created balloon tip would then look like this:
A BalloonTip
attached to a JButton
Note that clicking the balloon tip's close button will permanently close it. A BalloonTip
instance should not be used anymore once it's closed! This is because, by default, the close button will call closeBalloon()
, which detaches the balloon tip and removes all of its listeners.
If you prefer the close button to behave differently, you can use the setCloseButton
methods.
For example, add the following statement to set a close button that merely hides the balloon tip:
myBalloonTip.setCloseButton( BalloonTip.getDefaultCloseButton(), false);
If you want to have control over the balloon tip's looks, you can use this constructor:
BalloonTip(JComponent attachedComponent, String text, BalloonTipStyle style, boolean useCloseButton)
The style
parameter sets a balloon tip's BalloonTipStyle
, which defines the balloon tip's looks. Several different styles can be found in the package net.java.balloontip.styles
. As an example, I'll make a BalloonTip
with the simplest style, the EdgedBalloonStyle
:
BalloonTipStyle edgedLook = new EdgedBalloonStyle(Color.WHITE, Color.BLUE); BalloonTip myBalloonTip = new BalloonTip(myButton, "Hello world!", edgedLook, true);
Now we'll get something looking like this:
A BalloonTip
with an EdgedBalloonStyle
You can preview all styles that come bundled with Balloon tip in the “Looks” tab of the demo application; just change the “Style” combo box. If you haven't tried the demo application yet, see the Getting started section for more information.
Balloon tips can also contain other components beside just text. In fact, just about any JComponent
can serve as the contents of a balloon tip. The following constructor allows you to add a JComponent
as the contents of a balloon tip:
BalloonTip(JComponent attachedComponent, JComponent contents, BalloonTipStyle style, boolean useCloseButton)
For example, you could set a balloon tip's contents to a JTable
:
BalloonTipStyle edgedLook = new EdgedBalloonStyle(Color.WHITE, Color.BLUE); BalloonTip myBalloonTip = new BalloonTip(myButton, new JTable(3,2), edgedLook, true);
This creates the following result:
A BalloonTip
with a JTable
as its contents
If you use components such as a JPanel
or JTabbedPane
,
you can build entire user interfaces inside a balloon tip. (Why yes,
you can even attach balloon tips to the components inside a balloon
tip!)
If you also need control over the balloon tip's position, you can use the following constructor:
BalloonTip(JComponent attachedComponent, JComponent contents, BalloonTipStyle style, Orientation orientation, AttachLocation attachLocation, int horizontalOffset, int verticalOffset, boolean useCloseButton)
This constructor has four new parameters:
orientation
: Determines
whether you want the tip of the balloon on the left or right side of
the balloon, and whether the balloon itself should be above or below the
attached componentattachLocation
: Should
the balloon tip align itself with the attached component? Or should it
put the balloon's tip on a fixed location? (e.g. fix the balloon's tip
in the center of the attached component)horizontalOffset
: The amount of space (in pixels) between the balloon's left (or right) side and the tip of the balloonverticalOffset
: The amount of space (in pixels) between the balloon's bottom (or top) side and the tip of the balloon
In order to clarify the horizontalOffset
and verticalOffset
parameters a bit better, have a look at this picture:
The horizontal and vertical offset of a BalloonTip
Here's a snippet of code that creates a balloon tip using this constructor:
BalloonTipStyle edgedLook = new EdgedBalloonStyle(Color.WHITE, Color.BLUE);BalloonTip myBalloonTip = new BalloonTip(myButton, new JLabel("Hello world!"), edgedLook, Orientation.RIGHT_BELOW, AttachLocation.ALIGNED, 40, 20, false);
This snippet will produce the following picture:
A BalloonTip
with Orientation.RIGHT_BELOW
and AttachLocation.ALIGNED
Finally, if you want full control over your balloon tip, use this constructor:
BalloonTip(JComponent attachedComponent, JComponent contents, BalloonTipStyle style, BalloonTipPositioner positioner, boolean useCloseButton)
Even though this constructor has fewer parameters than the previous one, it is more powerful. This is because of the positioner
parameter. A BalloonTipPositioner
defines the way a balloon tip should behave. More specifically: it
determines where a balloon tip should position itself, whether the
balloon tip should flip, what happens when the balloon tip collides with
something, …
What the previous constructors actually did was simply instantiating the appropriate BalloonTipPositioner
for you. However, this constructor will allow you to supply your own instance of BalloonTipPositioner
. Here's another example snippet that produces exactly the same result as the example in the previous section:
BalloonTipStyle edgedLook = new EdgedBalloonStyle(Color.WHITE, Color.BLUE); BalloonTipPositioner rightBelowPositioner = new Right_Below_Positioner(40, 20); BalloonTip myBalloonTip = new BalloonTip(myButton, "Hello world!", edgedLook, rightBelowPositioner, false);
This concludes the basic usage of BalloonTip
. The other methods BalloonTip
has to offer should now be quite straightforward to use. If you
require more information, you can always refer to the project's Javadoc.
Most methods in BalloonTip
are getters and setters that you can use to access or alter a balloon tip after it has been constructed.
One common scenario where these setters can come in handy is when you
want to ensure that only one balloon tip is visible at the same time:
Simply create a single BalloonTip
instance and use the setContents
/setText
, setAttachedComponent
and setVisible
methods whenever the balloon tip is needed elsewhere. In such a
scenario, you'll also want to set the close button such that it hides
the balloon tip, as explained in an earlier tip.
Regular BalloonTip
instances attach themselves to an entire JComponent
.
In some cases however, it may be desired to attach a balloon tip to a
particular part of a JComponent. Several subclasses have been provided
to take these cases into account:
CustomBalloonTip
: Attach a balloon tip to a rectangular offset of a JComponent
.TableCellBalloonTip
: Attach a balloon tip to a particular cell in a JTable
.ListItemBalloonTip
: Attach a balloon tip to a particular item in a JList
.TreeNodeBalloonTip
: Attach a balloon tip to a particular node in a JTree
.
The CustomBalloonTip
is just like a regular BalloonTip
, but you can attach it to a rectangular shape within a component, instead of attaching it to the entire component.
This can be very useful in case you're creating your own JComponent
, such as a timeline or a calendar.
An application with a custom JComponent
that displays a timeline; it has a CustomBalloonTip
attached to it
Just take a look at this snippet of code, which was used in the demo application, just to see how it works:
// Create a custom JComponent that draws a large white canvas with a small blue rectangle in it final Rectangle customOffset = new Rectangle(640, 320, 50, 16); final JComponent customComponent = new JComponent() { protected void paintComponent(Graphics g) { Rectangle clip = g.getClipBounds(); g.setColor(Color.WHITE); g.fillRect(clip.x, clip.y, clip.width, clip.height); g.setColor(Color.BLUE); g.fillRect(customOffset.x, customOffset.y, customOffset.width, customOffset.height); } }; customComponent.setPreferredSize(new Dimension(1280, 640)); // Now create the CustomBalloonTip, such that it attaches itself to the blue rectangle customBalloon = new CustomBalloonTip(customComponent, "I'm a CustomBalloonTip!", customOffset, new EdgedBalloonStyle(Color.WHITE, Color.BLUE), BalloonTip.Orientation.LEFT_ABOVE, BalloonTip.AttachLocation.ALIGNED, 20, 20, false);
A TableCellBalloonTip
is a balloon tip that attaches itself to a JTable
cell. The TableCellBalloonTip
class is similar to CustomBalloonTip
:
Instead of specifying a rectangular offset, you specify a cell row
and column. The row and column will determine which table cell the
balloon tip should attach itself to. Note that the balloon tip will
adjust its position when columns are moved or modified.
A ListItemBalloonTip
is a balloon tip that attaches itself to an item within a JList
. The ListItemBalloonTip
class is similar to CustomBalloonTip
:
Instead of specifying a rectangular offset, you can specify the
list item's index. Note that the balloon tip will also adjust its
position when the JList is modified.
A TreeNodeBalloonTip
is a balloon tip that attaches itself to a node within a JTree
. The TreeNodeBalloonTip
class is similar to CustomBalloonTip
: Instead of specifying a rectangular offset, you can specify the desired tree node by means of a TreePath
. Note that the balloon tip will also adjust itself when the tree is modified, or when nodes are expanded/collapsed.
Any balloon tip can be automatically closed after a certain period of time using the TimingUtils
class. Here's an example:
BalloonTip balloonTip = new BalloonTip(someComponent, "Hello world"); // Now make the balloon tip disappear in 3000 milliseconds TimingUtils.showTimedBalloon(balloonTip, 3000);
The FadingUtils
class allows you to add a simple linear fade-in or fade-out effect to balloon tips. An example:
BalloonTip balloonTip = new BalloonTip(someComponent, "Hello world"); // Perform a fade-in effect lasting 300 ms, at 24 frames per second and trigger finishedAction once the effect has finished FadingUtils.fadeInBalloon(balloonTip, finishedAction, 300, 24);
If you desire something more advanced than a linear fading function, you
could quite easily implement your own fade effects using the setOpacity
method of BalloonTip
in combination with, for example, timingframework.
You can turn any balloon tip into a tooltip with the ToolTipUtilsclass
.
If you hover over the attached component, the balloon tip will show up
after an initial delay and then stay visible until the mouse no longer
hovers over the component or a timeout occurs, just like a regular
tooltip. A quick example:
tooltipBalloon = new BalloonTip(someComponent, "Hello world"); // Now convert this balloon tip to a tooltip, such that the tooltip shows up after 500 milliseconds and stays visible for 3000 milliseconds ToolTipUtils.balloonToToolTip(tooltipBalloon, 500, 3000);
Because Balloon tip is suited for use with Maven, it's quite easy to import it as a Maven project into Eclipse. This can be done as follows:
net.java.balloontip.examples.complete.CompleteExample
or any of the other supplied examples in the balloontip-examples project.It doesn't matter much if you're not familiar with Maven; you can use the balloontip and balloontip-examples projects just like they were regular Java projects. The only difference with regular projects is that Maven projects have the added bonus of Maven's functionality, which is now at your disposal.
You can import Balloon tip as a regular Java project by following these steps:
net.java.balloontip.examples.complete.CompleteExample
or any of the other supplied examples.Balloon tip comes with its set of Maven POM files; you can use them as follows:
mvn package
.While Balloon tip doesn't come with any Ant build files, it's quite easy to automatically generate them if you have Maven installed:
mvn ant:ant
to generate Ant build files for Balloon tip. (You'll need Maven to be able to execute this command.)
Creating a new balloon tip style is fairly easy if you're a bit familiar with Java's Graphics
API. To start making your own balloon tip style, you should extend the BalloonTipStyle
class. In this class, you should at least override these two methods:
public Insets getBorderInsets(Component c)
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
getBorderInsets
is a method that determines where the
actual contents of the balloon tip (the text, the close button, …)
should go. (If you're familiar with Cascading Style Sheets (CSS), you should think of getBorderInsets
as a method that returns the padding of your balloon tip.) What you should do is return an Insets
object, which holds four integers. To determine these four, take a look at this picture:
These four values are needed by getBorderInsets
Suppose the green rectangle in the above picture represents where the
contents of the balloon tip should come. The implementation of getBorderInsets
then looks like this:
return new Insets(top, left, bottom, right);
The second method you should implement, paintBorder
, draws the balloon tip on a Graphics
instance. You've got a couple of different values to work with here. The obvious ones are the x
, y
, width
and height
-parameters. x
and y
determine the top-left coordinate of your drawing canvas, whereas width
and height
obviously represent the width and height of the drawing canvas.
Beside these parameters, you should also take into account the current values of the fields in BalloonTipStyle
: horizontalOffset
, verticalOffset
, flipX
and flipY
. The meaning of these fields should become clear when looking at this image:
A BalloonTipStyle
should respect the current values of horizontalOffset
, verticalOffset
, flipX
and flipY
Keep in mind that you must take into account flipX
and flipY
when implementing getBorderInsets
, as they have their effect on border insets!
Apart from getBorderInsets
and paintBorder
, you may also want to override the methods getMinimalHorizontalOffset
and isBorderOpaque
. Override getMinimalHorizontalOffset
to define the minimum value of the horizontal offset. You may want to
do this if your balloon tip starts to look funny if you go below (or
above) a certain horizontal offset. Balloon tip positioners will then
respect the minimum horizontal offset you've defined. Secondly, you
should override isBorderOpaque
if you wish to use
transparency effects. If so, simply make the method return false and
you're allowed to use transparent colors.
Apart from all of the above, there really is nothing else to know about
balloon tip styles. However, I did assume you are familiar with the Java
Graphics
API. If you're not, I recommend you to take a couple of tutorials (such as http://java.sun.com/docs/books/tutorial/2d/index.html), or take a look at the code of the existing styles in Balloon tip.
The task of a balloon tip positioner is to define the behaviour of a
balloon tip. This means it controls the position of the balloon tip, the
horizontal and vertical offset of the balloon tip and whether the
balloon tip should be flipped or not. The best way to learn how to
create your own BalloonTipPositioner
is by looking at an
example. The following example demonstrates a very simple positioner
that will place the balloon tip at a fixed location relative to the
attached component:
public class SimpleTipPositioner extends BalloonTipPositioner { int x = 0; // Current X-coordinate of the top-left corner of the bounding box around the balloon tip int y = 0; // Current Y-coordinate of the top-left corner of the bounding box around the balloon tip /* The balloon tip will call this method every time it wants to re-draw itself. * The parameter of this function, attached, is the Rectangle that the balloon tip should attach itself to. */ public void determineAndSetLocation(Rectangle attached) { /* Calculate the coordinates of the top-left corner of the bounding box around the balloon tip * This positioner will place the balloon tip above the attached Rectangle. */ x = attached.x; y = attached.y - balloonTip.getPreferredSize().height; // Now move the balloon tip to the position we've just calculated balloonTip.setBounds(x, y, balloonTip.getPreferredSize().width, balloonTip.getPreferredSize().height); balloonTip.validate(); } /* This method should return the location of the balloon's tip */ public Point getTipLocation() { /* You may use the last position calculated in determineAndSetLocation to calculate the tip's location. * The fields x and y now contain the position of the top-left corner of the bounding box of the balloon tip. */ return new Point(x + 20, y + balloonTip.getPreferredSize().height); } /* Whenever a balloon tip's style is changed (This includes setting it for the first time..), this method is called. * Within this method, the positioner should take care of properly setting up this new style. */ protected void onStyleChange() { balloonTip.getStyle().setHorizontalOffset(20); balloonTip.getStyle().setVerticalOffset(20); balloonTip.getStyle().flipX(false); balloonTip.getStyle().flipY(false); } }
Using this positioner will produce the following result:
A BalloonTip
with a simple custom-made BalloonTipPositioner
Here's the same picture once more, but this time it also shows the various variables that were used:
The variables that were used when calculating the balloon tip's position
This image may also prove useful; it shows the different settings of the balloon tip's style:
Don't forget to set these variables of the balloon tip's style: horizontalOffset
, verticalOffset
, flipX
and flipY
After examining this example, you can conclude that:
balloonTip.getTopLevelContainer().getWidth()
) If you do need extra information, you'll need to ask for it in your positioner's constructor.getTipLocation
.Lastly, a couple of pointers that you may find useful:
While this particular example did not produce anything spectacular, you can do some neat things with your own balloon tip positioner. You could implement a positioner that, for example: always puts the balloon's tip in the center, or tries to avoid overlapping with some other components, or tries to never move the balloon tip outside a certain area, or …
ListItemBalloonTip
, which can be attached to items in a JList
.TreeNodeBalloonTip
, which can be attached to nodes in a JTree
.BalloonTip.setCloseButton(JButton)
no longer alters the button's behaviour. BalloonTip.setCloseButton(JButton,boolean,boolean)
changed to BalloonTip.setCloseButton(JButton,boolean)
.TablecellBalloonTip
renamed to TableCellBalloonTip
. (Note the upper case C)TableCellBalloonTip
s now adjust themselves whenever the columns of the associated JTable
are modified.TableCellBalloonTip.setCellPosition()
CardLayout
, Balloon tip visiblity is now adjusted when switching cards.isValid()
on the attached component returns false, but is displayable.JScrollPane
, the balloon tip's viewport listener now takes into account the column/row header of this JScrollPane
. (Thanks mquiot)ToolTipUtils
now takes into account the rectangle a balloon tip is attached to,
rather than assuming the dimensions of the attached component. (This is
mainly relevant for instances of CustomBalloonTip.)closeBalloon()
is called before the balloon tip is initialized, not all listeners were removed.useCloseButton
parameter in CustomBalloonTip
's constructor now works correctly. (Thanks Adrian)refreshLocation()
call when constructing a CustomBalloonTip
.IsometricBalloonTipStyle
and ToolTipBalloonTipStyle
.ToolTipUtils.toolTipToBalloon()
to turn balloon tooltips back to normal.BalloonTip
can now be just about any type of JComponent
. (You can even add balloon tips to components within balloon tips..)setVisible(false)
to hide a balloon tip.BalloonTipPositioner
has been more simplified.enableClickToHide()
and enabledClickToClose()
are replaced by addDefaultMouseListener()
.BalloonTipStyle
: Create new looks for balloon tips by extending the BalloonTipStyle
-classBalloonTipPositioner
: Control the way a balloon tip positions itself by extending the BalloonTipPositioner
-classCustomBalloonTip
: allows you to attach a balloon tip to a certain offset rectangle within a JComponentTablecellBalloonTip
: allows you to attach a balloon tip to a JTable cellTimingUtils
: Automatically close a balloon tip after a certain timeToolTipUtils
: Turn a balloon tip into a tooltipCompleteExample
application shows off most of the project's featuresNullPointerException
if you try to create it before calling pack() on the top level containerJInternalFrame
was missingBalloonTip
component was miscalculated in more complex layoutsIf you find Balloon tip useful or have suggestions, feel free to drop Tim or Bernhard an e-mail!
If you already have a java.net account, the preferred way to report bugs and feature requests is the project's JIRA bug tracker. Alternatively, you can also use the project's mailing lists.