Check out
http://www.nyx.net/~jbuzbee/font.html.
Jim has some code to do exactly this. A good way to do it is to draw the
text to an offscreen image and write an ImageFilter to rotate the image.
Also, from JDK 1.2 on, the Java 2D API handles arbitrary shapes, text, and images and allows all of these to be rotated, scaled, skewed, and otherwise transformed in a uniform manner. A code example would be:
import java.awt.*;
import java.awt.geom.*;
public class r extends Frame {
public static void main(String args[]) { new r(); }
r() { setSize(200,200); setVisible(true); }
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
AffineTransform aft = new AffineTransform();
aft.setToTranslation(100.0, 100.0);
g2D.transform(aft);
aft.setToRotation(Math.PI / 8.0);
String s = "Rotated Hello World";
for (int i = 0; i < 16; i++) {
g2D.drawString(s, 0.0f, 0.0f);
g2D.transform(aft);
}
}
}
There is more info about the 2D API at
http://java.sun.com/products/java-media/2D/index.html
and
http://developer.javasoft.com/developer/technicalArticles/
Like this.
myTextArea.setFont(new Font("NAME", <STYLE>, <SIZE>));
where:
Example: new Font("TimesRoman", Font.PLAIN, 18);
No. If you're trying to write a word processor, use the
Swing JText classes.
TextArea just uses the corresponding widget of the underlying window
system. It will be bounded by the limit imposed in the native window
system. In Windows 95 TextAreas can hold about 28Kb. The native widget
allows 32Kb, but there is some overhead which reduces the amount available
to the programmer. The limit is removed in JTextComponent in Swing (JDK
1.2) which dispenses with peer controls.
Set it to an empty String with this:
area.setText("");
TextField.setEchoChar('\0') works on most Windows-based browsers...but for
most other platforms (i.e. Netscape under UNIX), it just locks up the
textfield.
There is only one good solution, and that is to make two TextFields on top of each other, one normal, and one with .setEchoChar('*'), and switch between them.
It's a little obscure. Creating a TextArea with no horizontal scrollbar
causes wrapping to occur automatically. The idea is that if you ask for a
scroll to scroll viewing over to the right, there is no reason for the
widget to do word wrap. So take away the scrollbar, and word wrap will be
done instead.
Supply TextArea.SCROLLBARS_NONE or TextArea.SCROLLBARS_VERTICAL_ONLY to the TextArea constructor to get word wrap. By default, a TextArea is created with both horizontal and vertical scrollbars.
The approach is to look at keystrokes as they happen, and disallow input
that does not meet your criteria.
A neat variation is to extend the basic AWT component, and in your subclass also include the handler that will look at the keystrokes. This bundles everything neatly in one place. The code may look like:
import java.awt.*;
import java.awt.event.*;
public class XCTextField extends java.awt.TextField implements
java.awt.event.TextListener {
public XCTextField(int columns) {
super(columns);
enableEvents(AWTEvent.FOCUS_EVENT_MASK);
addTextListener(this);
}
// other constructors may be useful, too
public void textValueChanged(java.awt.event.TextEvent event) {
int col = this.getColumns();
int len = getText().length();
// int caret = getCaretPosition();
if (col > 0 && len > col) {
// or if the char just entered is not numeric etc.
String s = this.getText();
Toolkit.getDefaultToolkit().beep();
this.setText(s.substring(0,col));
this.setCaretPosition(col-1); // caret at end
}
}
public void processFocusEvent(java.awt.event.FocusEvent e) {
// this routine highlights according to focus gain/loss.
super.processFocusEvent(e);
int id = e.getID();
if (id==java.awt.event.FocusEvent.FOCUS_GAINED)
this.selectAll();
else if (id==java.awt.event.FocusEvent.FOCUS_LOST)
this.select(0,0);
}
}
Here is a much briefer example, which very cleverly does the work in the
Listener. Oracle really dislikes the "apostrophe" character in a data text
fields, as it is interpreted as part of an SQL statement. Here is the code
that James Cloughley wrote to suppress apostrophes ("ticks") in a TextField.
import java.awt.*;
import java.awt.event.*;
public class NoTick extends KeyAdapter {
final char tick = '\'';
public void keyPressed( KeyEvent event ) {
TextComponent tc = ( TextComponent )event.getSource();
char c = event.getKeyChar();
if ( c == tick ) { event.consume(); }
}
}
Use it like this:
TextField sometextfield = new TextField();
sometextfield.addKeyListener( new NoTick() );
Brief and clever - make the event handler consume unwanted characters.
However, it doesn't filter out text that arrives in the
component via cut & paste! If you use ctrl-v to paste, you
get key events for the ctrl and v, but not for the characters that
are pasted.
Finally, check out iDate, iTime, and iNumeric from IBM's alphaworks javabeans, available free at http://www.alphaworks.ibm.com/alphaBeans/. These beans do the kind of validation you want.
JDK 1.0 has no way to explicitly set the z-order of components. You can try
it heuristically, based on the browser you're using, or you can use
CardLayoutManager to ensure the panel you want is at the front.
In JDK 1.1, the z-order of components ("z-order" means "front-to-back" order, i.e. which window is in front of which) can be controlled by using the method add(Component comp, int index). By default, components are added 0 to N. The method paint of class Container paints its visible components from N to 0.
Use
java.awt.Toolkit.getDefaultToolkit().getScreenSize()or
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()Screen resolution is in dots-per-inch.
Take a look in the Toolkit class for other useful methods.
Toolkit.getDefaultToolkit().getColorModel().getPixelSize()gets you the color model in terms of bits per pixel.
Math.pow(2, Toolkit.getDefaultToolkit().
getColorModel().getPixelSize())
gets you the color model in terms of number of colors. Or use this:
1 << Toolkit.getDefaultToolkit().
getColorModel().getPixelSize()
That does a shift left to calculate the power of two.
An alternative used provided by JDK 1.3 is to use the GraphicsConfiguration class to provide the information. GraphicsConguration config = ... // magically acquired reference Rectangle bounds = config.getBounds(); If you are dealing with multiheaded displays, the getDefaultToolkit() method will return wrong values (particularly if you are using screens with different resolutions). See question 19 on how to get instances of the GraphicsConfiguration.
Use MyFrame.getInsets(). This returns a java.awt.Insets object which has
four ints: top, left, bottom, right, giving the number of pixels each of
those margins are inset from the top. You can use these value to adjust the
Dimension object returned by component.getSize().
If you are doing this in the constructor you need to ensure that the Frame's peer object is created first. Otherwise the Insets object returned by getInsets() will have all zero values. Make a call to Frame.addNotify() to have the peer created.
List tlist = new List(10);but the Strings in the list were 80 characters long and only the first 15 were being shown. I was not able to resize the List to display the contents without using the scroll bar.
A List cannot be resized in a constructor, so add the following to the
Applet (or wherever):
public void paint (Graphics g) {
tlist.setSize(200,200);
}
Then before showing panel/frame with the List:
tlist.resize(400,400);
Add a ComponentListener to the window and fill in the componentResized()
method with what you want to do when the window is resized.
A less-satisfactory alternative is to
override the setBounds(int,int,int,int) method of Component to do what you
want. Of course, have it call super.setBounds() as well. Note that
setBounds() replaces reshape() which is deprecated.
Note the new APIs call the deprecated APIs instead of the other way round. For example, Component.setBounds calls Component.reshape, instead of reshape calling setBounds. This is because the AWT sometimes needs to call these for its own purposes. If it called the old one which then called the new one, and you overrode the new one, the AWT would (wrongly) not call your routine. By having the AWT call the new one (and then the new one call the old one), any overrides of the new one will correctly be called by the AWT as needed. If that didn't make sense, forget I mentioned it.
You cannot currently get the applet's absolute screen coordinates. Its
location (0,0) is relative to the browser, not the screen itself. But you
can center something that it pops up or displays centered on the screen
with code like this:
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); my_window.move( ( screen.width - my_window.size().width ) / 2, ( screen.height - my_window.size().height ) / 2 ); my_window.show().In a related fashion, you can center something on its parent like this. Note the intelligent use of APIs like translate() to do the work for you.
void center(Component parent) {
pack();
Point p = parent.getLocation();
Dimension d = parent.getSize();
Dimension s = getSize();
p.translate((d.width - s.width) / 2,
(d.height - s.height) / 2);
setLocation(p);
}
You mean, if the browser is about 640x480, you want a y-coord between 0 and
480. If the browser window is about 800x600 you want a y-coord between 0
and 600. This might be needed for a pop-up menu, where you want to pop up
at the absolute mouse position.
The approach is to sum up the event's (x,y) and the locations of the target and its parents until there is no parent. Though on some browsers, it seems this is not reliable. [Better suggestions are solicited.]
If you are using JDK 1.0.2, you can override the
reshape(int, int, int, int) method of Component to do what you want;
of course, have it call super.reshape() as well.
In JDK 1.1.x, setBounds() replaces reshape(), which is deprecated -
however, there is a better way of detecting the resize using the new
event model, than overriding setBounds().
Note the new APIs call the deprecated one.
The proper way to detect the resize in 1.1.x is to register a ComponentListener on the Frame, like this:
import java.awt.*;
import java.awt.event.*;
class MyFrame extends Frame {
public MyFrame() {
addComponentListener(new CmpAdapter());
}
class CmpAdapter extends ComponentAdapter {
public void componentResized(ComponentEvent evt) {
//doSomething();
}
}
}
Alternatively, the same effect can be achieved like this:
class MyFrame extends Frame implements ComponentListener {
public MyFrame() {
addComponentListener(this);
}
public componentHidden(ComponentEvent evt) { }
public componentMoved(ComponentEvent evt) { }
public componentShown(ComponentEvent evt) { }
public componentResized(ComponentEvent evt) {
//doSomething
}
}
Or even with an anonymous inner class
public MyFrame() {
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent evt) {
// doSomething;
}
} );
}
Those methods allow a LayoutManager to calculate the preferred and minimum
sizes of the Components it is arranging. You can control the values that
the LayoutManager gets by creating subclasses of the Components you are
using and overriding these methods. You don't call them; you override
them and they are called on your behalf.
The initial sizes of components are not always exactly what the
programmer would expect. When a component doesn't show up, often it is
getting added to its parent, but with a size of 0x0. Even when
getPreferredSize gives a non-zero value. If this seems to be what's
happening, try calling setSize(getPreferredSize()).
If that doesn't seem to be the problem, then sometimes the fix is to call validate() after the components have been added. This causes the layout manager to re-layout the components and make them visible. Sometimes this is an issue if many components are removed from a container and another set is added, while the container remains visible.
JDK 1.3 provides a way to set the screen from within your code.
String desired_display = "myhost:0.0";
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devs = env.getScreenDevices();
GraphicsConfiguration config = null;
int i;
int size = (devs == null) ? 0 : devs.length;
for(i = 0; i < size; i++)
{
int type = devs[i].getType();
if(type == GraphicsDevice.TYPE_RASTER_SCREEN)
{
String id = devs[i].getIDstring();
if(id.equals(desired_display))
config = devs[i].getDefaultConfiguration();
}
}
if(config != null)
Frame myFrame = new Frame(config);
Prior to JDK 1.3, and if you're running on X, set the environment variable DISPLAY (e.g. setenv DISPLAY mymachine:0.0). You might have to use xhost on the target to permit the connection to be made.
If you're using windows, mac or some other system then you're stuck with VNC. See http://www.uk.research.att.com/vnc
Use g.drawLine(x1,y1,x1,y1) to draw a line one pixel in length. If you are
drawing a very large number of individual pixels, consider using a
java.awt.MemoryImageSource object and measure whether this offers better
performance.
JDK 1.1 doesn't have support for this. The standard workaround for
drawing a thick line is to draw a filled polygon. The standard workaround
for drawing a thick polygon is to draw several polygons.
There is a useful class at http://www.apl.jhu.edu/~hall/java/GraphicsUtil.html which extends the drawxxx and fillxxx methods of java.awt.Graphics. It adds a Line Width argument to most of the drawxxx methods, a Color argument to most of the drawxxx and fillxxx methods, and a Font argument to drawString and drawChars.
JDK 1.2 introduces the java.awt.BasicStroke class. You set the stroke on a Graphics object, and line rendering is done using that info.
BasicStroke bs = new BasicStroke(width, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 1.0f, null, 0.0f);
g.setStroke(bs);
g.drawLine( ... );
None of these things can be done in JDK 1.1.
Most (possibly all, subject to confirmation) can be done in JDK 1.2.
The code in JDK 1.1 behaves as though there were two unrelated types of Image. The first type are those created by the Component.createImage(int, int) call, known as "offscreen" images, and the second are those created by the Component.createImage(ImageProducer) call, or by the Toolkit/Applet.getImage() calls, which I will call "produced" images.
The only common ground between these kinds of Image in JDK 1.1 is the following:
There are some relevant bugs shown in the Java Developer Connection: Bug ID 4098505. Apparently, from the report from the Sun engineer, PixelGrabber is specified to work with offscreen images, just it is currently buggy, and invariably gets the wrong color model. No fix has been scheduled yet.
Bug ID 4077718 reports that setting transparent Colors in offscreen images has been available since Java 1.2b1. I am personally unable to verify this.
There is an incorrect answer from Sun to the third matter, of getGraphics() on produced images, in article 1501 in Questions&Answers.
This is the purpose of the java.awt.image.PixelGrabber class. A fragment of
code showing its use is:
import java.awt.image.PixelGrabber;
import java.awt.Image;
...
public static int pixelValue(Image image, int x, int y) {
// precondition: buffer must not be created from ImageProducer!
// x,y should be inside the image,
// Returns an integer representing color value of the x,y pixel.
int[] pixel=new int[1];
pixel[0]=0;
// pixel grabber fills the array with zeros if image you are
// trying to grab from is non existent (or throws an exception)
PixelGrabber grabber = new PixelGrabber(image,
x, y, 1, 1, pixel, 0, 0);
try {
grabber.grabPixels();
} catch (Exception e) {System.err.println(e.getMessage());}
return pixel[0];
}
By the way, one issue on working with images is that the Java VM will
consume virtual memory pretty fast if you are loading lots of images
without calling the Image.flush() method when done. The getImage() method
probably caches old images so they aren't garbage collected.
The popup trigger is platform dependent.
On Windows, the MOUSE_RELEASED event identifier is the popup trigger.
On Unix, the MOUSE_PRESSED identifier triggers the popup.
To keep your code cross-platform, you need to use the isPopupTrigger()
method in both the mousePressed() and mouseReleased() event handlers:
public void mousePressed(MouseEvent me) {
if (me.isPopupTrigger())
doPopupStuff();
else
doRegularMousePressedStuff();
}
public void mouseReleased(MouseEvent me) {
if (me.isPopupTrigger())
doPopupStuff();
else
doRegularMouseReleasedStuff();
}
Just use
f.setIconImage( Toolkit.getDefaultToolkit().getImage(iconfilename) );On Windows, the icon must be 16-by-16 pixels.
You can do that, and it might work up to a point (or it might not). A
problem arises when the window system wants to refresh that component e.g.
because it has been partially obscured and is now revealed. It calls
paint(), and paint() has no knowledge of the other g.drawing() you have
just done.
Possibly it could, but how do you unremember something that has been drawn?
How do you start drawing over again with different contents? You could
solve these by creating extra methods, but that is not how it works. In
practice it is a lot simpler to be able to look at the paint method, and
see explicitly all the things that will be done to draw that component.
Bottom line: Use paint(), not g=getGraphics(); g.drawString( ...
repaint() just tells the AWT that you'd like a paint to happen. AWT will
fold several adjacent repaint requests into one, so that only the most
current paint is done. One possible workaround might be to use a clip
rectangle and only paint the different areas that have changed.
java.lang.NullPointerException at sun.awt.motif.MFramePeer.<init>(MFramePeer.java:59) at sun.awt.motif.MToolkit.createFrame(MToolkit.java:153) at java.awt.Frame.addNotify(Frame.java) at java.awt.Window.pack(Window.java)
There's a missing font on your system. Move font.properties from the "lib"
subdirectory aside to font.properties.bak. Then it won't look for the font
and fail to find it.
The problem occurs because the Motif AWT libraries use the Font "plain Dialog 12 point" as a fall-back default font. Unfortunately, when using a remote X server sometimes this font isn't available.
On an X terminal, the diagnostic may be slightly different, a segv
% appletviewer HelloWorldApplet.html SIGSEGV 11* segmentation violation si_signo [11]: SIGSEGV 11* segmentation violation si_errno [0]: Error 0 si_code [1]: SEGV_ACCERR [addr: 0x14]To determine which fonts you have, issue a command such as
xlsfonts > ~/fonts.txtThen pick through the long list of fonts to determine which ones you want to use. The xfd program will let you look at a font:
xfd -fn "your font name here" &
There are two reasons. First, while simple layouts are easy.
detailed GUI layout is difficult. Second, GridBagLayout
wasn't designed with human factors and ease of use
in mind. If that bothers you (it bothers me) then don't use it.
Create your GUI on several panels and use the other layout managers as
appropriate to get the exact effect you want. The official story from the
project leader of the AWT project, as explained to the Mountain View
Java Users Group on December 4 1996, is:
For alternative Java layout managers, take a look at: http://www.softbear.com/people/larry/javalm.htm - the layout manager page. If you're not a fan of nesting panels, and none of the other layout managers do what you want (or you're working with legacy code that already uses it), you might find it worth looking at the GridBagLayout tutorial buried in Swing: http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html
You probably specified a font name that isn't available under your Win95
installation; this is one of those cross-platform differences that can bite
you if you over-specify for one platform, like specifying "Arial" as a font
and expecting it to work on something other than Windows.
On both Windows 95 and Solaris 2.6, these fonts
import java.awt.*;
class foonly {
static public void main(String s[])
{
String n[]= new Frame().getToolkit().getFontList();
for (int i=0;i<n.length; i++)
System.out.println(n[i]);
System.exit(0);
}
}
In other words, You can get a String array of the names of the fonts by
String[] fonts = Toolkit.getDefaultToolkit().getFontList()The names of actual fonts like Helvetica, TimesRoman, and Courier are deprecated in JDK 1.1 in favor of font styles like SansSerif, Serif, and Monospaced (respectively). The font style will be mapped into the nearest actual font on a platform.
The font styles are now mapped into a system font name using the entries in one of the font.properties files in $JAVAHOME/lib. There are multiple font.properties files corresponding to different locales. If you wanted a quick hack for testing, you could modify the file or add to it so a different mapping is done to a new font you want to try.
Lightweight Components, since they are notionally meant to be
"transparent", aren't painted directly in response to repaint(), but
in fact, Component.repaint() goes up the stack of Components until it
finds an "Opaque" Heavyweight Component (necessarily a Container),
and then calls repaint() on *that*.
At this point, a call is eventually scheduled to Container.update(). His first action is to call super.update, plunging us into Component.update(), which clears the component to the background color, since it has been called on a heavyweight, and returns. Then Container.update() proceeds merrily to call update on all contained Lightweight Components, recursively.
The bottom line: "transparency" of lightweight components will only work correctly (without flickering) if the first upwardly accessible heavyweight component in the containment hierarchy is
Another important point is that if your Container has its own paint() method, that paint method of the container must call super.update/paint(), otherwise the contained lightweight components will never be painted. Putting this all together, the minimal alteration to code to cause it to work in this case is to place the method
public void update(Graphics g) {
super.paint(g);
}
in the most closely containing heavyweight Container, in a Component
hierarchy where you want to smoothly render lightweights that
do not paint areas extending past that painted by their parents,
i.e. ones that are not "transparent". This is dirty, but quick.
If you want smooth transparency, the call above should read
public void update(Graphics g) {
// standard offscreen generation here.
offg.fillRect(required background colour, full size);
super.paint(offg);
g.drawImage(myimage, 0, 0, null);
}
public void paint(Graphics g) {
// can generally expect resizes will hit update() first.
super.paint(offg);
g.drawImage(myimage, 0, 0, null);
}
It's possible to intertwine these, by having this.update() calling
this.paint(), with various replacings of the argument, but it is
clearest to override them separately, as in the example.
First of all, these methods do the same thing: Set the foreground color to
the value of the parameter. The difference lies in where you use them.
There is also a Component.setBackground that will set the background color.
If you are in a constructor or an event handler (e.g. "click here to turn the canvas blue") you have a Component and should use the setForeground() method. If you are in a paint() method, that takes a Graphics context as its argument so you will typically use g.setColor(c).
Unlike a Component, a Graphics object doesn't have a background color and a foreground color that you can change independently. A Graphics object arrives in the color(s) inherited from the drawing surface. From then on, any rendering (drawLine(), drawRect(), fillOval(), etc.) will be done in the setColor() color. Because they do different things, the Component and Graphics methods have different names.
No, it is the specified behavior. The Java API documentation says:
Here's how to make your program do that.
This is done by the sync() method in Toolkit. So just use:
AnyComponent.getToolkit().sync();
In JDK 1.0, you have to read the key press, and program it explicitly. JDK
1.1 supports tab and shift-tab (previous field) automatically. The tab
order is the order that the components were added to the container.
Low-level events are tied to a specific component (resizing a window,
dragging the mouse, striking a key, adding a Component to a Container,
etc.). Semantic events are those generated when you frob a control (move a
scrollbar, click on a button, select from a menu, etc.), and the same kind
of event can be generated by several different components. A Button and a
List both fire an Action event when they are clicked on.
To the programmer, the important difference is that you can change a low-level event such as the key value in a keypress, and it will display the new value. You can also consume low level events so that they do not appear in the widget. You can't do these things with semantic events - they have already "occurred" to the widget.
Semantic events: Use the method addXListener() to add a listener object which implements the XListener interface to get XEvent objects delivered (usually via the AWTEventMulticaster). Low level events: Use the method enableEvents() and override performX() to grab those events in the object itself.
On MS Windows, a Window object floats above all other windows, unlike a
Frame, which is layered in with ordinary windows. This behavior yields a
"floating" effect. Whether a Window object is really supposed to float is
another question entirely.
On Mac, a Window object is either layered in with other windows, just like a Frame is, or else it is entirely modal - depending on which VM you use. In Java - there appears to be no easy way to get floating behavior. If anyone knows otherwise, please send in your comments.
JDK 1.1 had no way to write code to force a window to iconify or
deiconify. Support was added in JDK 1.2.
MyFrame.setState( Frame.ICONIFIED );
MyFrame.setState( Frame.NORMAL );
will do the trick. There is a corresponding getState();
To handle mouse events you have to implement the MouseListener interface,
or derive from the MouseAdapter class in order to use one of the
mouse-handling methods. The MouseEvent argument passed to the handling
methods contains fields that say which button was pressed, and the click
count. Use code like this.
public void mouseClicked(MouseEvent m) {
boolean leftButtonPush =
(m.getModifiers() & java.awt.event.InputEvent.BUTTON1_MASK) != 0;
boolean centerButtonPush =
(m.getModifiers() & java.awt.event.InputEvent.BUTTON2_MASK) != 0;
boolean rightButtonPush =
(m.getModifiers() & java.awt.event.InputEvent.BUTTON3_MASK) != 0;
int click = m.getClickCount(); // might be 1,2,3 clicks or more
You can also call at m.isPopupTrigger(). If it returns a true value, the
user has asked for a pop-up menu. On a lot of window systems, the right
mouse button is the trigger for pop-up menus.
You can overload processMouseEvent for your component.
public void processMouseEvent(MouseEvent e) {
if (e.isPopupTrigger()) {
// do what you want
}
else
super.processMouseEvent(e);
}
The code above applies to JDK 1.1. You can also call
java.awt.swing.SwingUtilities.isRightMouseButton(MouseEvent me).
See also question 15.10.
Swing technology is a new GUI toolkit bundled with JDK 1.2, and available as an add-on
extension library for JDK 1.1. Swing technology is part of the Java Foundation Classes
and supports a GUI toolkit that lets developers create components that have
a pluggable look-and-feel. From an architectural standpoint, the Swing
component set extends - but does not completely replace - the Abstract
Windowing Toolkit (AWT).
Swing technology has many components that can be used in place of components in the AWT (e.g. JFrame instead of Frame, JButton instead of Button, JApplet instead of Applet, JPanel instead of Panel). It also has many components that don't exist in the AWT (e.g. tool tips, toolbars, and progress bars). However Swing technology relies on the underlying AWT being there.
The Swing toolkit allows the creation of GUI's that are every bit as sophisticated as native code toolkits like MFC -- with the Java technology advantage that they run on every platform. The pluggable look and feel means that they can have the same appearance on every platform, or you can choose to have it look like Windows on a PC, like Motif on a Unix box, etc, just as the user chooses.
Swing technology also supports the Accessibility API. That API allows the adaptive software used by disabled computer users to directly query the Java VM and extract information about the running program, the usual purpose for this being to determine the UI components. Then the existing adaptive software can interpret it to the user (e.g. read the contents of a window, etc). Swing technology doesn't use native components, and the adaptive software taps into native components, so the accessibility API has a real role in bringing the two together. The beauty of the Accessibility API is that developers need to do little work to support it, but they do need to be made aware of it if they implement new components.
With Swing technology, native window behavior is confined to external window frames (and their borders) and a few other things such as fonts and the buffers used to hold window contents. The composition, layout, and drawing of controls is now all handled by Java code. So identical code is executed to create and manage your user interface on every platform. Swing provides a much greater consistency of behavior across different platforms.
Swing works with JDK 1.1 if you download the swing.jar file and add it to your path. Swing is built in to JDK 1.2, and Javasoft has just changed its 1.2 Swing package-naming strategy. It is now called javax.swing.
Use Swing technology to build your apps now instead of AWT components, wherever you
have a choice.
Swing is a GUI toolkit that is at least as good as other commercial GUI
toolkits, and better in several respects.
With Swing technology, it is easier to build an application that is portable between Mac, Solaris, Windows 95 and NT, than it is to use Win32 and build an application that just runs on Windows 95 and NT.
There is a tutorial at
http://java.sun.com/docs/books/tutorial/ui/swing/index.html
which is part of this tutorial:
http://java.sun.com/docs/books/tutorial/ui/TOC.html
There is also a Swing technology FAQ at
http://www.drye.com/java/faq.html
See also
http://www.codeguru.com/java/Swing/index.shtml
There is a Swing Developer Connection website with white papers and
examples at
http://www.theswingconnection.com/.
Please let this FAQ maintainer know about other good Swing tutorials
and online resources.
Model/View/Controller is a design pattern
or framework originally developed by
Prof. Trygve Reenskaug at Xerox PARC in 1978/9. MVC was developed
to allow Smalltalk to conveniently support GUIs.
Model/View/Controller is used in Swing in the more complicated widgets like JTree and JTable. Basically, the "model" contains your data, the "view" is the graphical representation, and the "controller" is responsible for the interaction between the other two. As an example, think of visually editing the Tree widget that represents a directory. The display is the view. Selecting a file, and dragging it to the trash can will delete the file. In order for the delete to happen, the controller must tell the model what just happened in the view.
In practice, inter-communication between the view and the controller is complex, so the two are bundled together in one category in Swing. The model (data) is separate though.
There's a reasonable white paper on MVC in Swing at
http://java.sun.com:81/products/jfc/swingdoc-static/swing_arch.html
.
There is information on other OO design patterns on the web
available by searching.
That's because you don't have enough space for your DOS environment. You
can fix this with:
Odd painting behavior (such as "mouse trails")
on one MS Windows system, when the program works
fine on another system is usually caused by some of the following:
Most current browsers have to be specifically set up to run Swing applets.
Read the article at
http://java.sun.com/products/jfc/tsc/web/applets/applets.html
for information about this. The article also contains a simple Swing
example applet, so you can confirm that that's your problem.
Another approach is to use the Java plug-in, which automatically gives
Swing technology in the browser. See
http://java.sun.com/products/jfc/tsc/swingdoc-current/java_plug_in.html
The answer relates to lightweight and heavyweight (peer-based) components.
There is a good article about it at
http://www.javasoft.com/products/jfc/swingdoc-current/mixing.html
For those who want the quick fix, and will read the article later, adding the line:
javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false);before you create any menus will probably fix it (even if you're using menus other than JPopupMenu).
The summary answer is that a Lightweight component will not appear over a heavyweight component by default.
Use a JPanel as a Swing replacement for Canvas.
All Swing components have a paint(Graphics) routine that you can
override, just as you would have with Canvas,
(but you probably want to override paintComponent(Graphics)
instead, see next question).
Swing technology splits painting into several different routines:
In most cases, what you really want to do is override paintComponent() instead of paint().
Assume that you have a Swing JFrame component, and you handle the
windowClosing event, but do nothing in the handler. You will see that the
JFrame disappears anyway.
The reason is that JFrame's have default handling of the system close
operation, separate from the windowClosing event. You have to override
that by calling:
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);on your JFrame.
(This answer comes from the Swing Connection, see
http://java.sun.com/products/jfc/tsc/swingdoc-current/911.html).
Sun has not determined that it has the right to deliver the Mac look
and feel on platforms other than MacOS.
If Apple were to confirm Sun's right to deliver this look and feel
on other operating systems, Sun would be delighted to remove the lock.
To date, Apple has declined to do this.
Although you cannot use the new Mac L&F on non-Macintosh platforms, there is a way to examine the source code so developers can use it as an example of how to create a custom L&F. The Mac L&F is distributed in "stuffed-binhexed" format, which is standard for the Macintosh. If you develop on a MS-Windows platform and would like to examine the source code for the Mac L&F then you can do that by downloading and using a program called Aladdin Expander for Windows. You can download Aladdin Expander from this URL: http://www.aladdinsys.com/expander/index.html When you have downloaded Aladdin Expander, you can use it to decode the Mac L&F file posted on the JDC.
A recent posting on comp.lang.java.gui suggested the following user workaround:
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
class MyOwnWindowsLookAndFeel extends WindowsLookAndFeel {
public isSupportedLookAndFeel() { return true; }
}
The desire on Sun's part to avoid infringing the Windows
Look and Feel is also the reason why the JTree uses colored
circles (and soon, little circles with a short line coming out
of them) for the nodes to indicate whether they are open or not.
The Swing team could have used
the '+' and '-' as Windows does, or even the triangles that
MacOS uses, but decided against it.
In JDK 1.0.2 only the awt Frame could change its Cursor. With
the advent of JDK 1.1 Cursor manipulation has moved
to the Component class. Now all Components have access to the
Cursor class.
You could change your Cursor to a WAIT_CURSOR for each Component. This could be time-consuming. You could have a potentially large number of Components. With the advent of the JFC Swing, there is a mechanism to change the Cursor over the entire Window regardless of the number of components. The Swing component JFrame has a method:
public void setGlassPane(Component glassPane)which sets an awt Component as the 'glassPane' for the JFrame.
This Component will cover the entire JFrame's visible user accessible (when visible), area excluding the border set by the underlying windowing system. With the 'glassPane' Component you can set the 'WAIT_CURSOR' over an entire JFrame, prohibiting user input (the 'glassPane' Component gets all user input) and blocking the user until your 'other' processing is complete.
NOTE: You must spawn a Thread to accomplish your 'other' work if you want to see the WAIT_CURSOR while the 'other' processing is happening. When the 'other' work is being accomplished, the 'glassPane' is visible with a WAIT_CURSOR and gobbling up all user input. When the 'other' work is finished, the Thread uses your waitCursor() method to hide your 'glassPane' until its needed again.
In American English there are two acceptable spellings: "canceled" and
"cancelled". Note that the first one has one "el" and the second two "el's".
Sun spells this "canceled" for ProgressMonitors but many of
the secondary sources of documentation spell it "cancelled". To make
matters worse, Sun spells it "cancelled" at other times, such as the method
"isCancelled()" for PrinterJob.
The default keymap for Swing text components (derived from JTextComponent)
binds the Enter key (VK_ENTER) to the ActionEvent for text fields.
This was done to be compatible with the behavior of java.awt.Textfield.
To enable use of
the Enter key to activate the default button, remove the Enter
key binding from the default text component keymap as follows:
static {
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Keymap map =
JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
map.removeKeyStrokeBinding(enter);
}
Take a look at the following example that comes with the JDK:
$JAVAHOME\demo\awt-1.1\lightweight\RoundButtons\example.html
Sun left maximize / minimize / deiconify methods out of the AWT,
and resisted putting them in for a long time. They finally
added setState(NORMAL) and setState (ICONIFIED) in JDK 1.2,
and the maximize call came in JDK 1.3 (the so-called Merlin" release).
So get the screen size using Toolkit.getScreenSize(), and then use setBounds() or setLocation() / setSize() to move and resize the frame.
You can set things up to run Swing classes and applets
in a browser without
using the plug in. You have to place the swing.jar library on the client,
and tell the browser how to find it, but it works.
In general, see http://www.webstandards.org/ which is a coalition aimed at encouraging browser standards. Also see http://bugzilla.mozilla.org/ which is a bug database that allows users to search for and vote on reported bugs in Netscape 6 (similar to Sun's Java bug database).
Netscape 4 and Internet Explorer 5 have only JDK 1.1 support. This means
they won't be able to run applets that use any classes or methods that
were added in JDK 1.2 or 1.3, including Swing (aka Java Foundation
Classes) and the Java 2 Collections classes (e.g. ArrayList, HashMap).
Netscape 6 will have JDK 1.3 support, but it seems likely that Microsoft Internet Explorer will never advance beyond JDK 1.1 support. For now, the most portable way to get JDK 1.2 or 1.3 support for an applet is with Sun's Java Plug-in, available at http://java.sun.com/products/plugin/ Note that for the Plug-in to work, you need to change the HTML on the web page that contains the applet. The HTML Converter, located at the above URL, will do this automatically for you.
Java technology supporter Dave Postill did the work to get this answer.
The life cycle of an applet is illustrated by logging calls to init(),
start(), stop() and destroy(). Use caution when your applets have threads
since in most sample applet code, the stop() method calls stop on any
separate threads within the applet, and then sets them to null.
This reckless threadicide is because most people think of the stop() method as something called only when the user leaves the page and wants to forget about it. But since Netscape calls stop() when you resize the window, your users would lose the applet's state when they thought they were only making a minor adjustment.
See "Java Tip 8: Threads, Netscape, and the resize problem - How to deal with applet resizing in Netscape Navigator", JavaWorld http://www.javaworld.com/javatips/jw-javatip8.html. Sadly the JavaWorld workaround does not completely fix the problem, since it relies on start() being called soon after stop() to identify a resize. However if you minimise the browser it may send a stop() to the Applet and then may not send a start() until the Browser is either restored or maximised. In this case, using the workaround results in the Applet being destroyed following minimising of the Browser - unless the Browser gets un-minimised within the killThreads timeout.
| Netscape
[4.04/JDK 1.1.4] [4.05/JDK 1.1.5] |
Netscape with Plug-In [4.05/ JDK 1.1.5/ Plugin 1.1] | Applet- Viewer
[JDK 1.1.5] [JDK 1.1.6] |
Internet Explorer 4 SP1 4.72.3110.8
on NT 4.0 SP3 |
Internet Explorer
with Plug-In [5.00.0518.10 / Plugin 1.1] on NT 4.0 SP3 |
|
| 1. Clear browser cache | nothing | nothing | nothing | nothing | nothing |
| 2. Initial load of .html | init(), start() or init(), start(), stop(), start() [1] | init(), start() | init(), start() | init(), start() | init(), start() |
| 3. Back | stop() | stop(), destroy() | [4] | stop(), destroy() | stop(), destroy() |
| 4. Forward | start() | init(), start() | [4] | init(), start() | init(), start() |
| 5. Reload | stop(), destroy(), init(), start() | stop(), destroy(), init(), start() | [4] | stop(), destroy(), init(), start() | stop(), destroy(), init(), start() |
| 6. <shift> reload [NS], <ctrl> reload [IE] |
stop(), destroy(), init(), start() | stop(), destroy(), init(), start() | [4] | stop(), destroy(), init(), start() | stop(), destroy(), init(), start() |
| 7. Resize | stop(), start() | [3] | [3] | [3] | [3] |
| 8. Minimize | [2] | [3] | stop() | [2] | [3] |
| 9. Restore | [2] | [3] | start() | [2] | [3] |
| 10. Exit | stop(), destroy() | stop(), destroy() | stop(), destroy() | stop(), destroy() | stop(), destroy() |
Notes:
[1] Results not repeatable.
[2] Not tested.
[3] Tested, and found that no logged methods are called.
[4] Test not applicable.
Short answer: no, at least not in applets.
Longer answer: probably no in applets, but yes in servlets.
Ultimate answer:
A cookie is a morsel of tasty data that a server sends back to the client,
and can retrieve on demand. It allows the server to retain some state
information for each of its clients. The information is typically something
like "what pages has the user seen?" or "is this a privileged user?".
Servletscan set and retrieve cookies with
HttpServletResponse.addCookie() and HttpServletRequest.getCookies()
The DevEdge site on Netscape's home page has a Javascript-Java
programming language example on
getting cookies. Also
http://www.geocities.com/SiliconValley/Vista/1337/
has info on connecting an applet with JavaScript functions. It's quite
involved. Stick to just Java programming language if you can.
Note: a reader reports that as of Netscape Communicator 4.05 it
is possible to force the browser to reload the applet by holding
down "control"+"shift" while clicking "Reload"
In the past Netscape has completely failed to improve the defective code
that does this monstrously wrong thing. It has been like this for many
successive releases.
Flushing the network cache will make no difference; that isn't where the
caching is taking place. Although applets are sometimes "pruned" and their
ClassLoaders garbage-collected, this doesn't happen predictably, so
restarting Netscape is the only reliable work-around at the moment.
For the applet to be reloaded, the new version would have to be loaded in a
different ClassLoader. Navigator/Communicator's policy for assigning
ClassLoaders to applets doesn't take into account whether a reload has been
done (although there is no technical reason why it couldn't).
Some versions of Netscape reload the Applet if you
use Edit/Preferences/Advanced/Cache to Clear Memory Cache and Clear Disk
Cache, then
<Shift> while you click on reload.
In Explorer, use View/Options/General/Delete Files,
then <Control> 'Reload' button to reload the
page containing the applet.
Until they fix it, use the appletviewer to test applets. And send them mail - developers can only fix the bugs they know about.
The question contains its own answer.
CAB format is a Microsoft-only format. So do not use it as it destroys
software portability.
JAR format is the Java programming language
standard format, based on PKZIP format including
data compression. JARs were introduced with JDK 1.1.
See
http://www.ibm.com/java/community/viewarchive4.html
for more information.
You should use the Java standard format JAR (Java Archive) files, not a
vendor-specific format. JAR files are not just a Java standard, they are in
industry-standard PKZIP format. One reader comments that both formats can
be used with this tag:
See
http://java.rrzn.uni-hannover.de/insel/beispiele/vertest.html.
This page tells you whether your browser supports JDK 1.1.
You can open the Java Console and type a "?" to get a list of
all the commands/options available to you in Netscape's
built-in JVM.
An application is a standalone program.
An applet is a downloadable program that runs in a web browser.
Typically an applet has restricted access to
the client system for reasons of security. Other than that it is virtually
no different from a regular Java technology-enabled program.
Look at skyview
for an example of an excellent applet.
A servlet is a Java technology-enabled
program whose input comes from a server and whose
output goes to a server. Other than that it is virtually no different from
a regular Java technology-enabled
program. Think of a servlet as an application, but one that
(like an applet) requires a context in which to run, namely web server
software. Servlets are used like CGI scripts, but take much less
processor resources, and they allow the server end
to be written in the Java programming language as well as the client.
There is a page with much servlet information at:
http://www.frontiernet.net/~imaging/servlets_intro.html
There is a servlet tutorial at
http://java.sun.com/docs/books/tutorial/servlets/index.html
and another servlet tutorial at
http://www.novocode.com/doc/servlet-essentials/
There is a servlet FAQ at
http://www.saint-elie.com/
The web server starts up a servlet when the URL is referenced, and now your
applets have something that they can talk to (via sockets) on the server
that can write files, open connections to other servers, or whatever.
There is also a software technology from IBM called an "Aglet".
An aglet
is a mobile agent that can go from machine to machine, performing tasks,
serializing data collected, and "shipping itself" (code and data) to the
next machine. It's too early to say if aglets are a flash in the pan or
a dawning technology. Read about aglets at
http://www.trl.ibm.co.jp/aglets/
Finally, there is the ticklet (Tcl/Tk) plugin for your browser (Netscape or
Explorer) available at
http://sunscript.sun.com/plugin/
Don't confuse Sun's JWS "Java Web Server" with JWS "Java Workshop
SM". Java
Web Server supports servlets, as does the lightweight and free server at
Acme.com:
http://www.acme.com/java/software/Acme.Serve.Serve.html
It could be one of several reasons, and unfortunately the messages that you
get in this situation aren't much help. In general, you can assume that
either your applet's class files are corrupted somehow, or the web server
can't find one or more of them when the browser needs them.
Be careful of the following things:
Use code like this,
getAppletContext().showDocument(
new URL("http://www.here.com") );
Or, to show the page in another window or frame,
getAppletContext().showDocument(
new URL("http://www.here.com"), "windowname" );
You can simply do a g.drawImage(yourImage, x, y, this) in the
paint() routine of your applet. If the image isn't big enough to
fill the entire background, tile it or scale it. Here is some code to
tile it
// The background image is named "bg".
int w = 0, h = 0;
while (w < size().width) {
g.drawImage(bg, w, h, this);
while ((h + bg.getHeight(this)) < size().height) {
h += bg.getHeight(this);
g.drawImage(bg, w, h, this);
}
h = 0;
w += bg.getWidth(this);
}
Alternatively, the AWT can scale your background image to the
size of the applet. The result quality will depend on the kind of image.
Inside an applet class, you can use:
drawImage(img, 0, 0, size().width, size().height, this);You can set the background color to match the background color of the browser by passing the value in as a parameter, like this:
String colparam = getParameter("BrowserColor");
int col = Integer.valueOf(colparam,16).intValue();
setBackground( new Color(col) );
An applet cannot override the size imposed by the HTML. If you make the
applet larger, the browser will still clip to the original size. If you
need more room, open up a new Frame, Window or Dialog to show your output.
There is no way to give an applet a transparent background that lets the
web browser background show through. You can simulate it by giving the
applet a background that matches the underlying browser background.
(For a straight color, it will be the value
of <BODY BGCOLOR=nnnnnn> in the HTML file).
It doesn't produce satisfactory results with a patterned background
because of problems aligning the edges.
Lightweight components (new in JDK 1.1) have a transparent background,
but that merely allows other components to show through. A lightweight
component is always ultimately positioned in a heavyweight component.
Unsigned applets are simply not allowed to read or write files on the
local file system (see answer to question 7.8).
Unsigned applets can, however, read (but not write) non-class files bundled with your applet on the server, called resource files.
See answer to question 7.8 and question 7.9.
[Question has been retired, in favor of question Q7.9]
But note the BUG listed for JDK 1.2.2 at
http://developer.java.sun.com/developer/bugParade/bugs/4251549.html
[Question has been retired in favor of Q7.9]
In your applet's init() method, create a Frame instance and then attach the
Menus, Menubar etc to that frame. You cannot attach the Menu or a Menubar
to an applet directly.
Or get the parent Frame like this (doesn't work in all execution
environments):
Container parent = getParent();
while (! (parent instanceof Frame) )
parent = parent.getParent();
Frame theFrame = (Frame) parent;
This second suggestion definitely doesn't work in the appletviewer, and
probably won't work on Macs (where would the Menubar go?) or in some
browsers. In JDK 1.1, just use a popup menu, which isn't attached to a
Frame.
This is a security feature that prevents the applet programmer from popping
up a window that looks like it came from the native OS and asking for
passwords or credit card info (etc.). Users must always be aware of when
they are talking to an unsigned applet. You can get rid of it by signing
the applet, if the user accepts signed applets from you.
In Netscape (only), using the Capabilities API to make the call
PrivilegeManager.enablePrivilege("UniversalTopLevelWindow");
before creating the Frame eliminates the message, if the security manager
passes it.
The browser invokes your constructor, then setStub, then init(). Hence when
your constructor is invoked, the AppletStub (and through it the
AppletContext) is not yet available. Although in principle you can do
things in the constructor that don't rely (even indirectly) on the
AppletStub or AppletContext, it is less error-prone to simply defer all
setup to the init() method. That way you know that anything that needs the
stub/context will have it available.
The truth is that 95% of the material is the same, whichever your book
chooses to focus on. Some people write their apps to work completely in a
Panel, then depending on whether they're running stand-alone or in a
browser the Panel is either added to a Frame or an Applet. The trick is
that you need to add a listener to the application's Frame to handle the
WINDOW_CLOSING (previously WINDOW_DESTROY) event yourself.
If you fail to do this, when running as an application, the window won't
close.
In this scenario the following code will tell you which environment you're
running in:
public boolean isRunningInBrowser() {
Component p = getParent();
while(p != null && !(p instanceof Frame)) {
p = p.getParent();
}
return (p == null);
}
Browsers are starting to introduce support for this. Until they all have
it, your best bet is to print a screendump. Using the browser to print the
page may leave a blank where the applet is. Putting print support in the
applet will print the applet only, not the rest of the browser page.
Also in the FAQ: Q5.2.
Use some code like this:
void center(Component parent) {
pack();
Point p = parent.getLocation();
Dimension d = parent.getSize();
Dimension s = getSize();
p.translate((d.width - s.width) / 2, (d.height - s.height) / 2);
setLocation(p);
}
This is the purpose of the InfoBus protocol. See
http://java.sun.com/beans/infobus/index.html
The older way to do it was as follows. In your HTML page, give a NAME in the APPLET tag for the applet receiving the message, say <APPLET ... NAME=someName ...>. In the Java code of the other applet do
Applet anotherApplet = getAppletContext.getApplet("someName");
Cast anotherApplet to the correct applet subclass, and you can call any
methods in the applet subclass. Don't forget to use appropriate
synchronization when two threads tweak variables.
This only works when the applets are truly on the same page.
If they are in different frames, it doesn't work.
Applet otherApplet;
AppletContext ac =getAppletContext;
Enumeration applets = null;
for (applets=ac.getApplets(); applets.hasMoreElements(); ) {
otherApplet=(Applet)applets.nextElement();
if (otherApplet!=this) break;
// do something with otherApplet, e.g.
// if (otherApplet instanceof FooApplet) ...
}
Some people suggest using the static members of a common class to
communicate information between the applets. This is not recommended as it
relies on class-loading behavior that may change in future.
Netscape changed it in one Beta so it didn't work, then changed it
back again so it did. It doesn't work if you use the "mayscript" tag
though.
If you want resizing behavior from an applet, you should launch an external
Frame that can be resized independently.
One programmer suggests using percentages for the height/width parameters
in an applet tag, like this:
<APPLET CODE="lewinsky.class" WIDTH="100%" HEIGHT="100%">
You can't resize the applet directly, but it does get resized when you
resize the browser window (tested with Netscape 3.04 and 4.04, but does not
work with appletviewer). If you have nothing else on your HTML page and use
100% for your width and height, the browser window looks almost like a real
application.
The browser vendors have produced independent and different solutions
for applet signature (alas).
Here are some URLs on this topic.
See the Java Signing FAQ (do a web search for it).
Read the basics of signing at:
http://www.javareport.com/html/features/archive/9802/somers.shtml
Be aware that the mechanism of signing and administering signed code
changed significantly between Java 1.1 and Java 2.
Netscape signing:
http://developer.netscape.com/docs/manuals/signedobj/javadoc/netscape_security_Target.html
https://certs.netscape.com/client.html
http://developer.netscape.com/docs/manuals/signedobj/capabilities/contents.htm
http://developer.netscape.com/docs/manuals/signedobj/targets/contents.htm
Microsoft signing:
http://www.microsoft.com/java/sdk/20/tools/signcode.htm
From JDK 1.2 on use the standard extension Java Advanced Imaging API.
It lets your Java technology-based programs read and
write many graphics file formats (PNG, JPG, BMP, GIF, TIFF, etc).
For Java 1.1 and earlier, use JIMI, available from http://java.sun.com/products/jimi/.
See also this list of links to Java image resources: http://www.geocities.com/marcoschmidt.geo/java-image-coding.html
Java 1.1 and earlier releases use one audio format exclusively. The audio
file must be in .au format, recorded at 8 KHz, mono, in mu-law encoding. If
your audio clip is in a different format (e.g., .wav) or a different
frequency it must be converted to the exact specifications above before
Java can play it. Support for .wav and other formats is part of the Java
Media Framework coming in JDK 1.2.
Search at
http://www.yahoo.com
for GoldWave for Win 95, sox for Unix and similar conversion utilities for
other systems.
Other sites:
That is the purpose of StreamBean. See
http://www.hellonetwork.com/streambean/
Java 1.0.2 and earlier releases use GIF and JPEG formats, and do not use
the GIF89 animated GIF format. (An animated GIF is one that contains
successive frames of an image, so when they are displayed in quick sequence
the image appears to contain movement). When you display an animated GIF in
Java 1.0.2, you will just get the first frame. There doesn't appear to be
any easy way to get other frames from the image.
The advantage of an animated GIF file is that there is only one file to
download, and it is simple to do simple animations. The advantage of
programmatic control over individual frames is that you control the rate
and order of displaying them.
JDK 1.1 nominally supports the animated display of animated GIFs.
However, there are several bugs which preclude the user of animated
GIFS in practice. You can (perhaps) workaround them, use a commercial
Java animated GIF toolkit, or forego them. The bugs still exist in JDK 1.3,
and you can vote on them at the JDC. See bugs 4088017, 4302818, 4339995.
For simple animations animated GIFs would be a lot easier and lighter-weight
than coding an animation explicitly.
Use GIFanimator from ULead (said to be the best)
http://www.ulead.com/,
or GIF Construction Set from Alchemy Mindworks
The problem is most likely that in your paint method you have
g.drawImage(img, ix, iy, this);
You should change this to
g.drawImage(img, ix, iy, getBackground(), this);
This will change all the transparent regions of the image to the background
color before painting to the screen. If you paint transparent images
directly to the screen they flicker.
public boolean imageUpdate(Image img, int flags, int x, int y,
int width, int height) {
if ((flags & (FRAMEBITS|ALLBITS))!= 0) repaint();
return (flags & (ALLBITS|ABORT)) == 0;
}
update is
public void update(Graphics g) { paint(g); }
If you have a background Image behind the partly transparent animated GIF
you will have to double buffer. You can crop the background image so you
won't have to double buffer the full app and waste too much memory.
GIF89a images with a transparent background show up as transparent without
further filtering. Animated GIFs and transparent GIFs both display correctly
Even better, you can fill the transparent pixels with a color (so they
appear non-transparent). Just pass the fill color explicitly:
drawImage(img, x, y, w, h, fillcolor, this);
Use the Java Media Framework Player API.
Other sites:
A new static method was introduced in JDK1.2 in the class Applet:
public final static AudioClip newAudioClip(URL url) {
The method turns a URL (pointing to an audio file) into an AudioClip. Since
the method is static it can be used without any objects of class Applet
needing to exist, e.g. in an application. Once you have an AudioClip, you
can play it with:
MyAudioClip.play();
The Java Media Framework provides a richer API for playing sounds in an
application.
import sun.audio.*;
URL url; ...
AudioStream audiostream = new AudioStream(url.openStream());
AudioPlayer.player.start(audiostream);
...
AudioPlayer.player.stop(audiostream);
Also in the FAQ:
Use
Image img = Toolkit.getDefaultToolkit().getImage(fname);
A peer component needs to exist for your component before you can get its
image. This is done by the method addNotify() (surely one of the most
poorly named methods of all -- it doesn't mean "add a Notify". It
means "Notify that the Component has been added to a Container". It tells
the system, "you need to create the peer for this Component now").
addNotify will be called for you when you add your component to a
container.
Note that most applications do not call addNotify() directly.
It is called for you when you add the component to a container.
If you have any code that requires peer resources, you
can move it into a thread
that is started from a conditional branch of the paint() or update()
method. That way the peer will definitely exist when the code is executed.
A common reason for seeming to require peer resources in a constructor, or
alternatively in the getPreferredSize() method, (which is also usually
before the peer is created) is to measure the area required for your
window, in terms of font and image sizes. Font sizes may be obtained by
calling Toolkit.getDefaultToolkit().getFontMetrics(somefont).
This does not require a peer. Image sizes may be obtained by waiting for
the relevant Image to load from the ImageProducer by using an
ImageObserver, or a MediaTracker (see 8.15), also without requiring a peer.
See 15.4 for more discussion of this problem.
If you override addNotify(), don't forget to call super.addNotify() in your
overriding version.
Originally it was thought that you could turn off caching for the URL.
URL url = null;
URLConnection con;
try {
url = new URL(getDocumentBase(),"image.jpg");
con = url.openConnection();
con.setUseCaches(false);
} catch (MalformedURLException e1) {
System.err.println(e1.getMessage());}
catch (IOException e2) {
System.err.println(e2.getMessage());}
However that it caches anyway, even if you do this!
The reason that the setUseCaches(false) doesn't work is because the
default image loaders actually use Toolkit.getImage() to create an
image. getImage() caches copies of the image in memory and hence it will
not rebuild the image even if the source has changed. The only
workaround for this is to use createImage() within your code rather than
getImage().
createImage() guarantees that it will not cache the image.
$ appletviewer m.html
Premature end of JPEG file
sun.awt.image.Im...Exception: JPEG datastream contains no image
at sun.awt.image. ... .produceImage(JPEGImageDecoder.java:133)
at sun.awt.image.Inpu...mageSource.doFetch(
InputStreamImageSource.java:215)
at sun.awt.image.ImageFetcher.run(ImageFetcher.java:98)
There's a known bug in early releases of the JDK which can cause the above
failure when reading a JPEG across a slow connection. The failure only
occurs if the JPEG contains a large application data block (APPn marker) -
the problem is that the JPEG decoder is trying to skip over the APPn and
failing if not all of the APPn has been received yet. The quoted error
message is only one of several possible complaints, but they all stem from
the same root.
Photoshop is the most common source of JPEGs containing oversize APPn
blocks. In particular, if you allow Photoshop 4 to save a thumbnail
(preview) in a JPEG, the thumbnail plumps up Photoshop's private APPn
marker to several K, which is usually enough to cause this problem.
There are several possible workarounds:
In a word: don't.
There's hardly any overlap between the set of images that JPEG works well
on and the set that GIF works well on. Sometimes, with enough care, you can
get an acceptable conversion...but most of the time GIF<->JPEG
conversion will just turn your image to mush. It's better to pick the right
format in the first place.
Other sites:
Use the createImage() method in Toolkit that takes the InputStream directly.
Note that because createImage does not cache the image loaded, if you
need that image a second time it will have to either rewind the stream
to the beginning or make the connection again.
Image img = Toolkit.createImage(my_stream);
The Java Media Framework will eventually support this, but it does not yet.
JMF 1.0.1 only supports playback.
JMF 1.0.1 is bundled with JDK 1.2, and available as a separate download for
JDK 1.1 and Netscape Communicator 4 with Java 1.1.
Other sites:
JDK 1.1 supports rendering HTML using the unbundled JFC 1.1 package
javax.swing. The Swing package is bundled in JDK 1.2. It has an elementary
(graphics, tables, text) HTML bean that is good enough for simple rendering
(help files, email, etc).
Other sites:
The behaviour of the AWT on creating images in this way is to do nothing at
all.
When the image is first drawn using Component.drawImage(), or its size is
requested, the image begins to load in a different Thread.
As the image loads, the ImageObserver specified in the
drawImage()/getHeight() call is periodically notified of the loading status
of the image, by calls to its imageUpdate() method.
In the case of Component.drawImage() call, the default behavior of
Component.imageUpdate() is to schedule *another* repaint() call when the
image has fully loaded. This means that, in particular the following code
will not work:
class MyComponent extends Component {
...
public void paint(Graphics g) {
ImageFilter cropper=new CropImageFilter(0,0,16,16);
Image cropped_image=createImage(new
FilteredImageSource(image.getSource(),cropper));
g.drawImage(image,10,400,this); // this line works
// this line doesn't -
g.drawImage(cropped_image,400,15,this);
}
}
The cropped_image will not be created in time to be painted, and when it is
finally created, another call will be scheduled to paint, which will try to
draw another one, etc.
If you are using win95/nt, you could use
SoundBite - Audio Recording in Applets.
See
http://www.scrawl.com/store/
It provides easy access to audio data in arrays:
short[] left, right;
The PNG format is specified in RFCs 1950, 1951, and 2083, and is unencumbered by licenses or patents. See also the PNG-1.1 specification at ftp://swrinde.nde.swri.edu/pub/png/documents.
The PNG format is supported by JDK 1.3