Programmatically scroll a scrollable JTable to a specific cell or row

The scrollRectToVisible method is the magic one you need. The code fragment below assumes that selectedColumn and selectedRow indicate the cell that you want to make sure is visible. If your rows/columns are not all the same height/width you will have to change the calculations, but the concept is the same.

   table.scrollRectToVisible(
      new Rectangle(columnWidth*selectedColumn,
                    table.getRowHeight()*(selectedRow),
                    columnWidth,
                    table.getRowHeight()));

Determining when a page in a JEditorPane has finished loading

Add a PropertyChangeListener and listen for the property page.

   htmlPane.addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
         if (!evt.getPropertyName().equals("page")) return;
         System.out.println("Page loaded!");
      }
   });

Main.java:

import javax.swing.text.html.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.net.*;
import java.awt.*;
import java.io.*;
 
public class Main extends JFrame
{
   // need to be final to allow the inner class to access it!
   final JTextField urlTextField = new JTextField();
   final JEditorPane htmlPane = new JEditorPane();
   JButton urlButton = new JButton("Go!");
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
 
   public Main() { 
      htmlPane.setEditable(false);
      urlTextField.setText("http://www.yahoo.com");
  
      urlButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            loadPage(urlTextField.getText());
         }
      });
 
      htmlPane.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            if (!evt.getPropertyName().equals("page")) return;
            System.out.println("Page loaded!");
         }
      });
 
      htmlPane.addHyperlinkListener(new HyperlinkListener() {
         public void hyperlinkUpdate (HyperlinkEvent event) {
            if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
               urlTextField.setText(event.getURL().toString());

               if (event instanceof HTMLFrameHyperlinkEvent) {
                  HTMLDocument doc = (HTMLDocument) htmlPane.getDocument();
                  doc.processHTMLFrameHyperlinkEvent ((HTMLFrameHyperlinkEvent) event);
               }
               else {
                  loadPage(urlTextField.getText());
               }
            }
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      JPanel topPanel = new JPanel(new BorderLayout());
      topPanel.add(BorderLayout.CENTER, urlTextField);
      topPanel.add(BorderLayout.EAST, urlButton);
 
      getContentPane().add(BorderLayout.NORTH, topPanel);
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(htmlPane));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      setSize(400, 400);
   }
 
   public void loadPage(String url) {
      try {
         htmlPane.setPage(new URL(urlTextField.getText()));
      }
      catch(Exception e) {
         System.out.println(e);
      }
   }
}

Change to a Mac Look and Feel on a Windows Machine

There are two ways to implement Mac L&F on Windows. The first consists of modifying the main L&F class to return true when the isSupportedLookAndFeel is called. This is against the Swing/JDK license agreement, though.

Another way is to use a 3rd party Mac look & feel. Check out the website in the related URLs section for more information. Remember that you can dynamically load a look and feel without having to modify a properties file.

Turn off copy/paste in a JTextArea

Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      JTextArea ta = new JTextArea();
      getContentPane().add(new JScrollPane(ta));
 
      ta.getInputMap().put(KeyStroke.getKeyStroke("control C"), "none");
      ta.getInputMap().put(KeyStroke.getKeyStroke("control V"), "none");
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Monitoring specific AWT events

The following example monitors Window events and Key events and prints them out.

Main.java:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
class Main extends JFrame
{
   public Main() {
      Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
         public void eventDispatched(AWTEvent e) {
            System.out.println(e);
         }
      }, AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK );
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.setDefaultCloseOperation( EXIT_ON_CLOSE );
      main.setSize(200, 200);
      main.setVisible(true);
   }
}

Detecting a deadlock with ThreadMBean in JDK 1.5

This example shows how to use the ThreadMBean class in JDK 1.5 to detect a deadlock. ThreadMBean is a management class (package java.lang.management) that provides functionality to query the thread system of the JVM.

The example creates three threads A, B and C which end up in a deadly embrace: A waits for a lock that B holds, B waits for a lock that C holds and C waits for a lock that A holds. The method findMonitorDeadlockedThreads returns the list of Thread ids involved in the deadlock.

FindDeadlock.java:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMBean;
import java.lang.management.ThreadState;
 
public class FindDeadlock
{
   Object a = new Object();
   Object b = new Object();
   Object c = new Object();
   
   public static void main(String []args) {
      final FindDeadlock fd = new FindDeadlock();
   
      Thread t1 = new Thread() {
         public void run() {
            while (true) { fd.m1(); }
         }
      };
      
      Thread t2 = new Thread() {
         public void run() {
            while (true) { fd.m2(); }
         }
      };
      
      Thread t3 = new Thread() {
         public void run() {
            while (true) { fd.m3(); }
         }
      };      
      
      t1.setName("First thread");
      t2.setName("Second thread");
      t3.setName("Third thread");
      
      t1.start();
      t2.start();
      t3.start();
      
      // give the time for the threads to go into a deadlock
      try { Thread.sleep(1000); } catch(Exception e) { } 
      
      ThreadMBean mbean = ManagementFactory.getThreadMBean();
      long[] threads = mbean.findMonitorDeadlockedThreads();
      if (threads != null) {
         for (int i=0; i<threads.length; i++) { 
            ThreadInfo threadInfo = mbean.getThreadInfo(threads[i]);
            ThreadState threadState = mbean.getThreadState(threads[i]);
            
            System.out.print(threadInfo.getThreadName() + "(" + threadState + ") is waiting for ");
            System.out.print(threadInfo.getLockOwnerName() + " to release ");
            System.out.println("the lock " + threadInfo.getLockName());
         }
      }
   }
   
   public void m1() {
      synchronized(a) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(b) {
            System.out.println("m1 got through");
         }
      }
   }
   
   public void m2() {
      synchronized(b) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(c) {
            System.out.println("m2 got through");
         }
      }
   }
   
   public void m3() {
      synchronized(c) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(a) {
            System.out.println("m3 got through");
         }
      }
   }   
}

outputs:

Third thread(Blocked) is waiting for First thread to release the lock java.lang.Object@d9f9c3
First thread(Blocked) is waiting for Second thread to release the lock java.lang.Object@1a46e30
Second thread(Blocked) is waiting for Third thread to release the lock java.lang.Object@3e25a5

Getting a list of all display modes

From JDK1.4, you can use the class DisplayMode. Get the current GraphicsDevice, and call the method getDisplayModes.

Main.java:

import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public static void main(String[] args) {
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
 
      GraphicsDevice gd = ge.getDefaultScreenDevice ();
 
      DisplayMode dp[] = gd.getDisplayModes();
 
      for (int i=0; i<dp.length; i++) {
         int width = dp[i].getWidth();
         int height = dp[i].getHeight();
         int bitDepth = dp[i].getBitDepth();
         int refreshRate = dp[i].getRefreshRate();
         System.out.println(width + "x" + height + " " + 
                            bitDepth + "bit " + 
                            (refreshRate == 0 ? "unknown" : ""+refreshRate + "hz"));
      }
   } 
}

outputs on my machine:

640x480 8bit unknown
800x600 8bit unknown
1024x768 8bit unknown
1152x864 8bit unknown
1280x1024 8bit unknown
640x480 16bit unknown
800x600 16bit unknown
1024x768 16bit unknown
1152x864 16bit unknown
1280x1024 16bit unknown
640x480 32bit unknown
800x600 32bit unknown
1024x768 32bit unknown
1152x864 32bit unknown
1280x1024 32bit unknown

Combining two shapes in Swing

Cast the shapes to areas where you have the methods add, subtract, intersect and exclusiveOr.

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      Shape shape1 = new Rectangle2D.Double(80, 50, 40, 40);
      Shape shape2 = new Rectangle2D.Double(20, 60, 160, 20);
 
      g2d.setColor(Color.black); 
      g2d.drawString("normal:", 20, 40);
      g2d.draw(shape1); 
      g2d.draw(shape2); 
 
      g2d.translate(0, 70);
      g2d.setColor(Color.yellow); 
      g2d.fill(combine("add", shape1, shape2));
      g2d.setColor(Color.black); 
      g2d.drawString("area add:", 20, 40);
      g2d.draw(shape1); 
      g2d.draw(shape2); 
 
      g2d.translate(0, 70);
      g2d.setColor(Color.yellow); 
      g2d.fill(combine("subtract", shape1, shape2));
      g2d.setColor(Color.black); 
      g2d.drawString("area subtract:", 20, 40);
      g2d.draw(shape1); 
      g2d.draw(shape2); 
 
      g2d.translate(0, 70);
      g2d.setColor(Color.yellow); 
      g2d.fill(combine("intersect", shape1, shape2));
      g2d.setColor(Color.black); 
      g2d.drawString("area intersect:", 20, 40);
      g2d.draw(shape1); 
      g2d.draw(shape2); 
 
      g2d.translate(0, 70);
      g2d.setColor(Color.yellow); 
      g2d.fill(combine("exclusiveOr", shape1, shape2));
      g2d.setColor(Color.black); 
      g2d.drawString("area exclusiveOr:", 20, 40);
      g2d.draw(shape1); 
      g2d.draw(shape2); 
   }
 
   public Shape combine(String op, Shape shape1, Shape shape2) {
      Area area1 = new Area(shape1);
      Area area2 = new Area(shape2);
      
      if (op.equals("add")) area1.add(area2);
      else if (op.equals("subtract")) area1.subtract(area2);
      else if (op.equals("intersect")) area1.intersect(area2);
      else if (op.equals("exclusiveOr")) area1.exclusiveOr(area2);
 
      return area1;
   }
  
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(200, 400);
      main.setVisible(true);
   }
}

Drawing a paragraph of text in Swing

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import javax.swing.*;
import java.text.*;
import java.awt.*;
 
public class Main extends JFrame {
   private String text;
   LineBreakMeasurer lineMeasurer;
   int beginIndex, endIndex;
   
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });  
 
      text = "It is, in fact, nothing short of a miracle that the modern methods " +
             "of instruction have not yet entirely strangled the holy curiosity " +
             "of inquiry; for this delicate little plant, aside from stimulation, " +
             "stands mainly in need of freedom; without this it goes to wrack and " +
             "ruin without fail. It is a very grave mistake to think that the " +
             "enjoyment of seeing and searching can promoted by means of coercion " +
             "and sense of duty. To the contrary, I believe that it would be " +
             "possible to rob even a healthy beast of prey of its voraciousness, " +
             "if it were possible, with the aid of a whip, to force the beast to " +
             "devour continuously, even when not hungry,especiallyif the food, " +
             "handed out under such coercion, were to be selected accordingly." +
             "n" +
             "Albert Einstein";
 
      AttributedString as = new AttributedString(text);
      AttributedCharacterIterator aci = as.getIterator();
 
      FontRenderContext frc = new FontRenderContext(null, false, false);
 
      beginIndex = aci.getBeginIndex();
      endIndex = aci.getEndIndex();
 
      // Create a new LineBreakMeasurer from the paragraph.
      lineMeasurer = new LineBreakMeasurer(aci, frc);
   }
 
   public void paint(Graphics g) {
      super.paint(g);
 
      Graphics2D g2d = (Graphics2D) g;
 
      Dimension size = getSize();
      float width = (float) size.width - 40;
 
      float x=10, y=30;
 
      g2d.setFont(new Font("Serif", Font.PLAIN, 24));
      lineMeasurer.setPosition(beginIndex);
      while (lineMeasurer.getPosition() < endIndex) {
         TextLayout layout = lineMeasurer.nextLayout(width);
 
         x = 10;   
         y += layout.getAscent() + layout.getDescent() + layout.getLeading();
       
         layout.draw(g2d, x, y);
     }
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(420, 230);
      main.setVisible(true);
   }
}

Converting an Image to a BufferedImage in Swing

This following example reads a JPEG imgage from disk, converts it to a bufferedimage and displays it onto the screen.

import java.awt.event.*;
import java.awt.image.*;
import java.awt.color.*;
import javax.swing.*;
import java.awt.*;
                           
public class Main extends JFrame
{
   public Main() throws Exception {
      BufferedImage bi = createBufferedImage("ally.jpg");
                       
      // add the image inside a JLabel component to the window
      getContentPane().add(new JLabel(new ImageIcon(bi)));
      pack();
                         
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public BufferedImage createBufferedImage(String filename) {
      Image img = Toolkit.getDefaultToolkit().getImage(filename);
      try {
         MediaTracker tracker = new MediaTracker(this);
         tracker.addImage(img, 0);
         tracker.waitForID(0);
      }
      catch ( Exception e ) {} 
 
      BufferedImage bi = 
         new BufferedImage(img.getWidth(this), img.getHeight(this),
                        BufferedImage.TYPE_INT_RGB);
      Graphics2D g2d = bi.createGraphics();
      g2d.drawImage(img, 0, 0, this);
 
      return bi;
   }
 
   public static void main(String args[]) throws Exception {
      Main main = new Main();
      main.show();
   }
}