11/*
2- * Copyright (c) 1999, 2014 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 1999, 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2222 */
2323
2424import java .awt .Color ;
25- import java .awt .Container ;
2625import java .awt .Dimension ;
26+ import java .awt .Point ;
27+ import java .awt .Rectangle ;
28+ import java .awt .Robot ;
29+ import java .awt .event .InputEvent ;
30+ import java .awt .event .KeyEvent ;
2731
2832import javax .swing .DefaultCellEditor ;
29- import javax .swing .JApplet ;
3033import javax .swing .JComboBox ;
34+ import javax .swing .JFrame ;
3135import javax .swing .JLabel ;
3236import javax .swing .JScrollPane ;
3337import javax .swing .JTable ;
4044import javax .swing .table .TableColumn ;
4145import javax .swing .table .TableModel ;
4246
43- /**
47+ /*
4448 * @test
4549 * @bug 4128521
46- * @summary
47- * Tabbing test
48- * @author milne
49- * @run applet/manual=yesno TAB.html
50+ * @key headful
51+ * @summary Verify focus changes correctly when tab is pressed while editing
52+ * a JTextField in a JTable
53+ * @run main Tab
5054 */
51- public class TAB extends JApplet
52- {
53- static void initTest (Container contentPane )
54- {
55+
56+ public class Tab {
57+ private static Robot robot ;
58+ private static JFrame frame ;
59+ private static JTable tableView ;
60+ private static volatile Point tableLoc ;
61+ private static volatile Rectangle cellRect ;
62+ private static volatile int selectedRowBeforeTabPress ;
63+ private static volatile int selectedColumnBeforeTabPress ;
64+ private static volatile int selectedRowAfterTabPress ;
65+ private static volatile int selectedColumnAfterTabPress ;
66+
67+ public static void main (String [] args ) throws Exception {
68+ UIManager .setLookAndFeel ("javax.swing.plaf.metal.MetalLookAndFeel" );
69+ robot = new Robot ();
70+ robot .setAutoDelay (50 );
71+ try {
72+ SwingUtilities .invokeAndWait (Tab ::createAndShowUI );
73+ robot .waitForIdle ();
74+ robot .delay (1000 );
75+
76+ SwingUtilities .invokeAndWait (() -> {
77+ tableLoc = tableView .getLocationOnScreen ();
78+ cellRect = tableView .getCellRect (2 , 1 , true );
79+ });
80+
81+ robot .mouseMove (tableLoc .x + cellRect .x + cellRect .width / 2 ,
82+ tableLoc .y + cellRect .y + cellRect .height / 2 );
83+ robot .mousePress (InputEvent .BUTTON1_DOWN_MASK );
84+ robot .mouseRelease (InputEvent .BUTTON1_DOWN_MASK );
85+ robot .mousePress (InputEvent .BUTTON1_DOWN_MASK );
86+ robot .mouseRelease (InputEvent .BUTTON1_DOWN_MASK );
87+ robot .waitForIdle ();
88+ robot .delay (20 );
89+
90+ SwingUtilities .invokeAndWait (() -> {
91+ selectedRowBeforeTabPress = tableView .getSelectedRow ();
92+ selectedColumnBeforeTabPress = tableView .getSelectedColumn ();
93+ });
94+
95+ robot .keyPress (KeyEvent .VK_TAB );
96+ robot .keyRelease (KeyEvent .VK_TAB );
97+ robot .waitForIdle ();
98+ robot .delay (20 );
99+
100+ SwingUtilities .invokeAndWait (() -> {
101+ selectedRowAfterTabPress = tableView .getSelectedRow ();
102+ selectedColumnAfterTabPress = tableView .getSelectedColumn ();
103+ });
104+
105+ if (selectedRowAfterTabPress != selectedRowBeforeTabPress
106+ && selectedColumnAfterTabPress != (selectedColumnBeforeTabPress + 1 )) {
107+ throw new RuntimeException ("JTable's cell focus didn't move to next" +
108+ " cell on TAB press" );
109+ }
110+ } finally {
111+ SwingUtilities .invokeAndWait (() -> {
112+ if (frame != null ) {
113+ frame .dispose ();
114+ }
115+ });
116+ }
117+ }
118+
119+ static void createAndShowUI () {
120+ frame = new JFrame ("Test JTable's Focus Component" );
55121 // Take the dummy data from SwingSet.
56122 final String [] names = {"First Name" , "Last Name" , "Favorite Color" ,
57123 "Favorite Number" , "Vegetarian" };
58124 final Object [][] data = {
59- {"Mark" , "Andrews" , "Red" , new Integer ( 2 ), new Boolean ( true ) },
60- {"Tom" , "Ball" , "Blue" , new Integer ( 99 ), new Boolean ( false ) },
61- {"Alan" , "Chung" , "Green" , new Integer ( 838 ), new Boolean ( false ) },
62- {"Jeff" , "Dinkins" , "Turquois" , new Integer ( 8 ), new Boolean ( true ) },
63- {"Amy" , "Fowler" , "Yellow" , new Integer ( 3 ), new Boolean ( false ) },
64- {"Brian" , "Gerhold" , "Green" , new Integer ( 0 ), new Boolean ( false ) },
65- {"James" , "Gosling" , "Pink" , new Integer ( 21 ), new Boolean ( false ) },
66- {"David" , "Karlton" , "Red" , new Integer ( 1 ), new Boolean ( false ) },
67- {"Dave" , "Kloba" , "Yellow" , new Integer ( 14 ), new Boolean ( false ) },
68- {"Peter" , "Korn" , "Purple" , new Integer ( 12 ), new Boolean ( false ) },
69- {"Phil" , "Milne" , "Purple" , new Integer ( 3 ), new Boolean ( false ) },
70- {"Dave" , "Moore" , "Green" , new Integer ( 88 ), new Boolean ( false ) },
71- {"Hans" , "Muller" , "Maroon" , new Integer ( 5 ), new Boolean ( false ) },
72- {"Rick" , "Levenson" , "Blue" , new Integer ( 2 ), new Boolean ( false ) },
73- {"Tim" , "Prinzing" , "Blue" , new Integer ( 22 ), new Boolean ( false ) },
74- {"Chester" , "Rose" , "Black" , new Integer ( 0 ), new Boolean ( false ) },
75- {"Ray" , "Ryan" , "Gray" , new Integer ( 77 ), new Boolean ( false ) },
76- {"Georges" , "Saab" , "Red" , new Integer ( 4 ), new Boolean ( false ) },
77- {"Willie" , "Walker" , "Phthalo Blue" , new Integer ( 4 ), new Boolean ( false ) },
78- {"Kathy" , "Walrath" , "Blue" , new Integer ( 8 ), new Boolean ( false ) },
79- {"Arnaud" , "Weber" , "Green" , new Integer ( 44 ), new Boolean ( false ) }
125+ {"Mark" , "Andrews" , "Red" , 2 , true },
126+ {"Tom" , "Ball" , "Blue" , 99 , false },
127+ {"Alan" , "Chung" , "Green" , 838 , false },
128+ {"Jeff" , "Dinkins" , "Turquois" , 8 , true },
129+ {"Amy" , "Fowler" , "Yellow" , 3 , false },
130+ {"Brian" , "Gerhold" , "Green" , 0 , false },
131+ {"James" , "Gosling" , "Pink" , 21 , false },
132+ {"David" , "Karlton" , "Red" , 1 , false },
133+ {"Dave" , "Kloba" , "Yellow" , 14 , false },
134+ {"Peter" , "Korn" , "Purple" , 12 , false },
135+ {"Phil" , "Milne" , "Purple" , 3 , false },
136+ {"Dave" , "Moore" , "Green" , 88 , false },
137+ {"Hans" , "Muller" , "Maroon" , 5 , false },
138+ {"Rick" , "Levenson" , "Blue" , 2 , false },
139+ {"Tim" , "Prinzing" , "Blue" , 22 , false },
140+ {"Chester" , "Rose" , "Black" , 0 , false },
141+ {"Ray" , "Ryan" , "Gray" , 77 , false },
142+ {"Georges" , "Saab" , "Red" , 4 , false },
143+ {"Willie" , "Walker" , "Phthalo Blue" , 4 , false },
144+ {"Kathy" , "Walrath" , "Blue" , 8 , false },
145+ {"Arnaud" , "Weber" , "Green" , 44 , false }
80146 };
81147
82148 // Create a model of the data.
@@ -98,7 +164,7 @@ public void setValueAt(Object aValue, int row, int column) {
98164 };
99165
100166 // Create the table
101- JTable tableView = new JTable (dataModel );
167+ tableView = new JTable (dataModel );
102168 // Turn off auto-resizing so that we can set column sizes programmatically.
103169 // In this mode, all columns will get their preferred widths, as set blow.
104170 tableView .setAutoResizeMode (JTable .AUTO_RESIZE_OFF );
@@ -150,20 +216,10 @@ public void setValue(Object value) {
150216 scrollpane .setBorder (new BevelBorder (BevelBorder .LOWERED ));
151217 scrollpane .setPreferredSize (new Dimension (430 , 200 ));
152218
153- contentPane .add (scrollpane );
154- }
155-
156-
157- public void init () {
158- SwingUtilities .invokeLater (() -> {
159- try {
160- UIManager .setLookAndFeel (
161- "javax.swing.plaf.metal.MetalLookAndFeel" );
162- } catch (Exception e ) {
163- throw new RuntimeException (e );
164- }
165-
166- initTest (getContentPane ());
167- });
219+ frame .getContentPane ().add (scrollpane );
220+ frame .pack ();
221+ frame .setLocationRelativeTo (null );
222+ frame .setDefaultCloseOperation (JFrame .EXIT_ON_CLOSE );
223+ frame .setVisible (true );
168224 }
169225}
0 commit comments