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