tag:blogger.com,1999:blog-44817815854188428402026-03-18T22:21:35.384+09:00Java Swing TipsIntroduce the GUI program of Java Swing using small source code examples.ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]Blogger228125tag:blogger.com,1999:blog-4481781585418842840.post-70988027041727299912025-06-30T19:29:00.001+09:002025-06-30T19:29:30.602+09:00Automatically open and close JPopupMenu without mouse click
download example.jar
download src.zip
repository
Code
/* If the mouse cursor goes out of the region at high speed, JPopupMenu may not close, use AWTEventListener to work around this problem. */
class AutoClosePopupMenu extends JPopupMenu {
private transient PopupMenuListener listener;
@Override public void updateUI() {
removePopupMenuListener(listener);
super.updateUI();
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-25551537348284611422025-05-31T23:32:00.001+09:002025-05-31T23:32:39.477+09:00Rounding the Title Background and Border Corners of TitledBorder
download example.jar
download src.zip
repository
Code
/*
- RoundedTitledBorder
- [TitledBorder(Border, String)](https://docs.oracle.com/javase/8/docs/api/javax/swing/border/TitledBorder.html#TitledBorder-javax.swing.border.Border-java.lang.String-) creates a `TitledBorder` that uses `RoundedBorder` for rounded corners.
- Additionally, it overrides `TitledBorder#paintBorder(...)` ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-46888478988792487882025-04-30T19:17:00.001+09:002025-04-30T19:17:22.044+09:00Switch JEditorPane's StyleSheet to Light or Dark Theme
download example.jar
download src.zip
repository
Code
public static void updateTheme(JEditorPane editor) {
updateTheme(editor, isDarkMode());
}
public static void updateTheme(JEditorPane editor, boolean isDark) {
EditorKit kit = editor.getEditorKit();
HTMLEditorKit htmlEditorKit;
if (kit instanceof HTMLEditorKit) {
htmlEditorKit = (HTMLEditorKit) kit;
} else {
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-61918555708816264582025-03-31T10:35:00.001+09:002025-03-31T10:35:14.740+09:00Rounds all corners of a JTextComponent's selection highlight polygon and fills it with a translucent background color
download example.jar
download src.zip
repository
Code
class RoundedSelectionHighlightPainter extends DefaultHighlightPainter {
protected RoundedSelectionHighlightPainter() {
super(null);
}
@Override public void paint(
Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-83060527711823238752025-02-28T18:59:00.000+09:002025-02-28T18:59:19.499+09:00Display the insert cursor for a new column on the boundary of a JTable column
download example.jar
download src.zip
repository
Code
class ColumnInsertLayerUI extends LayerUI<JScrollPane> {
private static final Color LINE_COLOR = new Color(0x00_78_D7);
private static final int LINE_WIDTH = 4;
private final Rectangle2D line = new Rectangle2D.Double();
private final Ellipse2D plus = new Ellipse2D.Double(0d, 0d, 10d, 10d);
@Override public void paint(ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-85024181896388180422025-01-31T18:27:00.003+09:002025-05-09T13:25:52.335+09:00Limit the area where TableColumns can be reordered by dragging
download example.jar
download src.zip
repository
Limit the area where JTableHeader column reordering drags can be initiated to the top half of the TableColumn and perform mouse cursor changes and draw drag handle icons on the JLayer.
Code
class ColumnDragLayerUI extends LayerUI<JScrollPane> {
private final Rectangle draggableRect = new Rectangle();
@Override public void ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-53418655742099801632024-12-31T17:12:00.002+09:002025-05-09T12:38:03.549+09:00Create a multi-line JToolTip using JTextArea's automatic line wrapping
download example.jar
download src.zip
repository
Code
class LineWrapToolTip extends JToolTip {
private static final double JAVA17 = 17.0;
private static final JLabel MEASURER = new JLabel(" ");
private static final int TIP_WIDTH = 200;
private final JTextArea textArea = new JTextArea(0, 20);
protected LineWrapToolTip() {
super();
textArea.setLineWrap(true);
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-27312736933223040462024-12-01T01:06:00.001+09:002025-05-09T12:38:23.847+09:00Implement sticky header in JList
download example.jar
download src.zip
repository
Code
class StickyLayerUI extends LayerUI<JScrollPane> {
private final JPanel renderer = new JPanel();
private int currentHeaderIdx = -1;
private int nextHeaderIdx = -1;
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-52634464059615256292024-10-31T14:00:00.001+09:002025-05-09T13:26:31.169+09:00Move and rotate strings to place them along the Shape curve
download example.jar
download src.zip
repository
Code
public static Shape createTextOnPath(Shape shape, GlyphVector gv) {
double[] points = new double[6];
Point2D prevPt = new Point2D.Double();
double nextAdvance = 0d;
double next = 0d;
Path2D result = new Path2D.Double();
int length = gv.getNumGlyphs();
int idx = 0;
PathIterator pi = new FlatteningPathIterator(
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-12339553843623204062024-09-30T21:22:00.002+09:002025-05-09T12:38:36.323+09:00Set the maximum number of items that can be selected in a group in JCheckBox
download example.jar
download src.zip
repository
Code
class GroupCheckBox extends JCheckBox {
protected GroupCheckBox(String title) {
super(title);
}
@Override public void updateUI() {
super.updateUI();
setModel(new ToggleButtonModel() {
private static final int GROUP_SIZE = 3;
@Override public void setSelected(boolean selected) {
if (selected) {
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-24716863334523047112024-08-31T17:30:00.002+09:002025-05-09T13:28:55.041+09:00Set JButton as cell renderer for JTableHeader
download example.jar
download src.zip
repository
Code
class ButtonHeaderRenderer extends JButton implements TableCellRenderer {
private int pushedColumn = -1;
private int rolloverColumn = -1;
@Override public void updateUI() {
super.updateUI();
setHorizontalTextPosition(LEFT);
}
@Override public Component getTableCellRendererComponent(
JTable table, Object valueateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-24717167133920258962024-07-31T16:47:00.001+09:002025-05-09T13:29:08.698+09:00Animates the effect of expanding and collapsing JTree nodes
download example.jar
download src.zip
repository
Code
JTree tree = new JTree() {
@Override public void updateUI() {
super.updateUI();
setRowHeight(-1);
setCellRenderer(new HeightTreeCellRenderer());
}
};
tree.addTreeWillExpandListener(new TreeWillExpandListener() {
@Override public void treeWillExpand(TreeExpansionEvent e) {
Object o = e.getPath().ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-18398964917558883672024-06-30T10:04:00.001+09:002025-05-09T13:29:20.686+09:00Drag and drop to rearrange nodes in the JTree
download example.jar
download src.zip
repository
Code
class TreeTransferHandler extends TransferHandler {
private final DataFlavor nodesFlavor = new DataFlavor(
List.class, "List of TreeNode");
@Override public int getSourceActions(JComponent c) {
return c instanceof JTree
&& TreeUtils.canStartDrag((JTree) c) ? COPY_OR_MOVE : NONE;
}
@Override ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-54510658355143029632024-05-31T14:40:00.002+09:002025-05-09T13:29:29.839+09:00Rounding the corners of a rectilinear polygon generated by node selection in a JTree
download example.jar
download src.zip
repository
Code
public static List<Point2D> flatteningStepsOnRightSide(
List<Point2D> list, double arc) {
int sz = list.size();
for (int i = 0; i < sz; i++) {
int i1 = (i + 1) % sz;
int i2 = (i + 2) % sz;
int i3 = (i + 3) % sz;
Point2D pt0 = list.get(i);
Point2D pt1 = list.get(i1);
Point2D pt2 = list.getateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-63315164602780485612024-04-30T17:44:00.002+09:002025-05-09T13:29:40.368+09:00Rounding the corners of a rectilinear polygon generated by a selection of calendar made with JList
download example.jar
download src.zip
repository
Code
public static Path2D convertRoundedPath(List<Point2D> list, double arc) {
double kappa = 4d * (Math.sqrt(2d) - 1d) / 3d; // = 0.55228...;
double akv = arc - arc * kappa;
int sz = list.size();
Point2D pt0 = list.get(0);
Path2D path = new Path2D.Double();
path.moveTo(pt0.getX() + arc, pt0.getY());
for (int i = 0; i &ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-85976459360129844862024-03-31T20:24:00.002+09:002025-05-09T13:29:51.972+09:00Switching between JToolBar and JMenuBar
download example.jar
download src.zip
repository
Click on the hamburger menu-like JButton placed on the JToolBar to switch this with the JMenuBar
Code
JMenuBar mainMenuBar = makeMenuBar();
JButton button = makeHamburgerMenuButton(mainMenuBar);
JMenuBar wrappingMenuBar = new JMenuBar();
wrappingMenuBar.add(makeToolBar(button));
EventQueue.invokeLater(() -> getRootPane().setJMenuBar(ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-30140103891855942582024-02-29T16:27:00.002+09:002025-05-09T13:30:00.201+09:00Paint JMenuItem selection rollover with rounded rectangle
download example.jar
download src.zip
repository
Code
class BasicRoundMenuItemUI extends BasicMenuItemUI {
@Override protected void paintBackground(
Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel m = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
if (ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-68661956020390393562024-01-31T14:33:00.003+09:002025-05-09T13:30:10.673+09:00Paint a JProgressBar with indeterminate progress status in a cell of a JTable
download example.jar
download src.zip
repository
Code
private final JTable table = new JTable(model) {
@Override public void updateUI() {
super.updateUI();
removeColumn(getColumnModel().getColumn(3));
JProgressBar progress = new JProgressBar();
TableCellRenderer renderer = new DefaultTableCellRenderer();
TableColumn tc = getColumnModel().getColumn(2);
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-53687887057178351462023-12-31T19:22:00.003+09:002025-05-09T13:30:19.087+09:00Create a 4-digit numeric PIN code input field using JPasswordField
download example.jar
download src.zip
repository
Code
class PinCodeDocumentFilter extends DocumentFilter {
public static final int MAX = 4;
@Override public void replace(
DocumentFilter.FilterBypass fb, int offset,
int length, String text, AttributeSet attrs) throws BadLocationException {
String str = fb.getDocument().getText(
0, fb.getDocument().getLength()) +ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-66186163798893864052023-11-30T16:34:00.003+09:002025-05-09T13:30:28.943+09:00Split TableColumn of JTableHeader with diagonal line Border
download example.jar
download src.zip
repository
Code
int size = 32;
JTable table = new JTable(model) {
@Override public void updateUI() {
super.updateUI();
setRowHeight(size);
TableCellRenderer hr = new VerticalTableHeaderRenderer();
TableColumnModel cm = getColumnModel();
cm.getColumn(0).setHeaderRenderer(
new DiagonallySplitHeaderRenderer());
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-6715441849481322692023-10-31T21:05:00.001+09:002025-05-09T13:30:37.646+09:00Sort JTable rows with multiple conditions
download example.jar
download src.zip
repository
Code
RowSorter<? extends TableModel> sorter = table.getRowSorter();
if (sorter instanceof TableRowSorter) {
TableRowSorter<? extends TableModel> rs
= (TableRowSorter<? extends TableModel>) sorter;
rs.setComparator(0, Comparator.comparing(RowData::getPosition));
rs.setComparator(1, Comparator.comparing(RowData:ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-14797190608105882832023-09-30T20:14:00.004+09:002025-05-09T13:30:49.297+09:00Move the selected item in JList up or down by clicking on the JButton placed on the JToolBar
download example.jar
download src.zip
repository
Since DefaultListModel does not have a move method like DefaultTableModel#moveRow(int start, int end, int to), the DefaultListModel#get(int index), DefaultListModel#remove(int index), and DefaultListModel#add(int index, E element) methods are used in combination to move selected items up and down the JList.
Code
JButton up = new JButtonateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-37539030688508250022023-08-31T17:43:00.001+09:002025-05-09T13:30:58.895+09:00Hide the check icon on the JRadioButtonMenuItem and reduce the text offset
download example.jar
download src.zip
repository
Code
UIManager.put(PRE + "minimumTextOffset", 10);
UIManager.put(PRE + "afterCheckIconGap", 0);
UIManager.put(PRE + "checkIconOffset", 0);
Icon checkIcon = getCheckIcon();
int height = checkIcon == null ? 22 : checkIcon.getIconHeight();
UIManager.put(PRE + "checkIcon", new EmptyIcon());
Dimension d = new Dimension(100, height);
JPopupMenu ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-30203812368699320692023-07-31T13:25:00.003+09:002025-05-09T13:31:06.965+09:00Add item check boxes to JList cells
download example.jar
download src.zip
repository
Code
@Override public void setSelectionInterval(int anchor, int lead) {
if (checkedIndex < 0 && isDragging()) {
super.setSelectionInterval(anchor, lead);
} else {
EventQueue.invokeLater(() -> {
if (checkedIndex >= 0 && lead == anchor && checkedIndex == anchor) {
ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0tag:blogger.com,1999:blog-4481781585418842840.post-69426443101433312162023-07-01T01:05:00.001+09:002025-05-09T13:31:17.169+09:00Click on the JCheckBox placed in the JTable cell to expand and collapss the row height
download example.jar
download src.zip
repository
Code
int defaultHeight = 20;
JTable table = new JTable(model) {
@Override public void updateUI() {
super.updateUI();
setAutoCreateRowSorter(true);
setSurrendersFocusOnKeystroke(true);
setRowHeight(defaultHeight);
setDefaultRenderer(RowHeader.class, new RowHeaderRenderer());
setDefaultEditor(RowHeader.class, new ateraihttp://www.blogger.com/profile/07647339065761407369[email protected]0