Skip to content

Commit 468b36a

Browse files
committed
8236907: JTable added to nested panels does not paint last visible row
Backport-of: bae0d5e7174fed8ffa8a30408c3cffa6e4dd3ddc
1 parent c7d6411 commit 468b36a

File tree

3 files changed

+228
-21
lines changed

3 files changed

+228
-21
lines changed

src/java.desktop/share/classes/javax/swing/TablePrintable.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,14 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
395395
// draw a box around the table
396396
g2d.setColor(Color.BLACK);
397397

398+
Rectangle bounds = table.getBounds();
399+
bounds.x = bounds.y = 0;
400+
398401
// compute the visible portion of table and draw the rect around it
399-
Rectangle visibleBounds = clip.intersection(table.getBounds());
402+
Rectangle visibleBounds = clip.intersection(bounds);
400403
Point upperLeft = visibleBounds.getLocation();
401-
Point lowerRight = new Point(visibleBounds.x + visibleBounds.width,
402-
visibleBounds.y + visibleBounds.height);
404+
Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
405+
visibleBounds.y + visibleBounds.height - 1);
403406

404407
int rMin = table.rowAtPoint(upperLeft);
405408
int rMax = table.rowAtPoint(lowerRight);
@@ -410,7 +413,7 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
410413
rMax = table.getRowCount();
411414
}
412415
int rowHeight = 0;
413-
for(int visrow = rMin; visrow < rMax; visrow++) {
416+
for(int visrow = rMin; visrow <= rMax; visrow++) {
414417
rowHeight += table.getRowHeight(visrow);
415418
}
416419
// If PrintMode is FIT_WIDTH, then draw rect for entire column width while

src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,23 +1884,6 @@ public void paint(Graphics g, JComponent c) {
18841884
comp = comp.getParent();
18851885
}
18861886

1887-
if (comp != null && !(comp instanceof JViewport) && !(comp instanceof JScrollPane)) {
1888-
// We did rMax-1 to paint the same number of rows that are drawn on console
1889-
// otherwise 1 extra row is printed per page than that are displayed
1890-
// when there is no scrollPane and we do printing of table
1891-
// but not when rmax is already pointing to index of last row
1892-
// and if there is any selected rows
1893-
if (rMax != (table.getRowCount() - 1) &&
1894-
(table.getSelectedRow() == -1)) {
1895-
// Do not decrement rMax if rMax becomes
1896-
// less than or equal to rMin
1897-
// else cells will not be painted
1898-
if (rMax - rMin > 1) {
1899-
rMax = rMax - 1;
1900-
}
1901-
}
1902-
}
1903-
19041887
// Paint the grid.
19051888
paintGrid(g, rMin, rMax, cMin, cMax);
19061889

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
/*
24+
* @test
25+
* @key headful
26+
* @bug 8236907
27+
* @summary Verifies if JTable last row is visible.
28+
* @run main LastVisibleRow
29+
*/
30+
31+
import java.awt.BorderLayout;
32+
import java.awt.Container;
33+
import java.awt.Dimension;
34+
import java.awt.event.InputEvent;
35+
import java.awt.image.BufferedImage;
36+
import java.awt.Point;
37+
import java.awt.Rectangle;
38+
import java.awt.Robot;
39+
import java.lang.reflect.InvocationTargetException;
40+
41+
import javax.print.attribute.HashPrintRequestAttributeSet;
42+
import javax.print.attribute.PrintRequestAttributeSet;
43+
44+
import javax.swing.BorderFactory;
45+
import javax.swing.JFrame;
46+
import javax.swing.JPanel;
47+
import javax.swing.JTable;
48+
import javax.swing.SwingUtilities;
49+
import javax.swing.WindowConstants;
50+
51+
public class LastVisibleRow {
52+
static JFrame frame;
53+
static JTable table;
54+
static Robot testRobot;
55+
56+
public static void main(String[] args) throws Exception {
57+
Point clkPoint;
58+
try {
59+
testRobot = new Robot();
60+
61+
SwingUtilities.invokeAndWait(new Runnable() {
62+
63+
public void run() {
64+
createAndShowGUI();
65+
}
66+
});
67+
testRobot.delay(1000);
68+
testRobot.waitForIdle();
69+
BufferedImage bufferedImageBefore = testRobot.createScreenCapture(getCaptureRect());
70+
testRobot.delay(1000);
71+
testRobot.waitForIdle();
72+
clkPoint = getMousePosition();
73+
mouseEvents(clkPoint);
74+
testRobot.waitForIdle();
75+
clearSelect();
76+
testRobot.waitForIdle();
77+
BufferedImage bufferedImageAfter = testRobot.createScreenCapture(getCaptureRect());
78+
testRobot.delay(1000);
79+
80+
if (!compare(bufferedImageBefore, bufferedImageAfter)) {
81+
throw new RuntimeException("Test Case Failed!!");
82+
}
83+
} finally {
84+
if (frame != null) SwingUtilities.invokeAndWait(() -> frame.dispose());
85+
}
86+
}
87+
88+
/*
89+
*
90+
* Get clickable screen point for particular row and column of a table
91+
* param row Row Number
92+
* param column Column Number
93+
* return Point
94+
*/
95+
private static Point getCellClickPoint(final int row, final int column) {
96+
Point result;
97+
98+
Rectangle rect = table.getCellRect(row, column, false);
99+
Point point = new Point(rect.x + rect.width / 2,
100+
rect.y + rect.height / 2);
101+
SwingUtilities.convertPointToScreen(point, table);
102+
result = point;
103+
104+
return result;
105+
}
106+
107+
private static void createAndShowGUI() {
108+
final PrintRequestAttributeSet printReqAttr = new HashPrintRequestAttributeSet();
109+
printReqAttr.add(javax.print.attribute.standard.OrientationRequested.LANDSCAPE);
110+
frame = new JFrame();
111+
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
112+
Container contentPane = frame.getContentPane();
113+
JPanel centerPane = new JPanel(new BorderLayout());
114+
centerPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
115+
JPanel tablePaneContainer = new JPanel(new BorderLayout());
116+
JPanel tablePane = new JPanel(new BorderLayout());
117+
table = new JTable(new Object[][]{{"row_1_col_1", "row_1_col_2", "row_1_col_3"}, {"row_2_col_1", "row_2_col_2", "row_2_col_3"}, {"row_3_col_1", "row_3_col_2", "row_3_col_3"}, {"row_4_col_1", "row_4_col_2", "row_4_col_3"}}, new String[]{"Col1", "Col2", "Col3"});
118+
table.setPreferredSize(new Dimension(0, (table.getRowHeight() * 3)));
119+
120+
tablePane.add(table.getTableHeader(), BorderLayout.NORTH);
121+
tablePane.add(table, BorderLayout.CENTER);
122+
tablePaneContainer.add(tablePane, BorderLayout.CENTER);
123+
centerPane.add(tablePaneContainer, BorderLayout.NORTH);
124+
contentPane.add(centerPane, BorderLayout.CENTER);
125+
frame.setSize(400, 120);
126+
frame.setVisible(true);
127+
frame.setLocationRelativeTo(null);
128+
129+
}
130+
131+
/*
132+
*
133+
* mouseEvents for last row click
134+
*/
135+
136+
private static void mouseEvents(Point clkPnt) {
137+
testRobot.mouseMove(clkPnt.x, clkPnt.y);
138+
testRobot.delay(50);
139+
testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
140+
testRobot.delay(50);
141+
testRobot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
142+
testRobot.delay(50);
143+
}
144+
/*
145+
*
146+
* getMousePosition Actions for last row click
147+
* returns Point
148+
* throws Exception
149+
*/
150+
151+
private static Point getMousePosition() throws Exception {
152+
final Point[] clickPoint = new Point[1];
153+
SwingUtilities.invokeAndWait(new Runnable() {
154+
@Override
155+
public void run() {
156+
clickPoint[0] = getCellClickPoint(2, 0);
157+
}
158+
});
159+
return clickPoint[0];
160+
}
161+
162+
/*
163+
*
164+
* Clears the selected table row
165+
* throws Exception
166+
*/
167+
168+
private static void clearSelect() throws Exception {
169+
SwingUtilities.invokeAndWait(new Runnable() {
170+
@Override
171+
public void run() {
172+
table.getSelectionModel().clearSelection();
173+
table.setFocusable(false);
174+
}
175+
});
176+
}
177+
178+
/*
179+
* getCaptureRect Method - To Compute the Rectangle for
180+
* Screen Capturing the Last Row for comparison
181+
* return Rectangle
182+
*/
183+
184+
private static Rectangle getCaptureRect() throws InterruptedException, InvocationTargetException {
185+
final Rectangle[] captureRect = new Rectangle[1];
186+
SwingUtilities.invokeAndWait(new Runnable() {
187+
@Override
188+
public void run() {
189+
Rectangle cellRect = table.getCellRect(2, 0, true);
190+
Point point = new Point(cellRect.x, cellRect.y);
191+
SwingUtilities.convertPointToScreen(point, table);
192+
193+
captureRect[0] = new Rectangle(point.x, point.y, table.getColumnCount() * cellRect.width, cellRect.height);
194+
}
195+
});
196+
return captureRect[0];
197+
}
198+
199+
/*
200+
* Compare method - to compare two images.
201+
* param bufferedImage1 Buffered Image Before click
202+
* param bufferedImage2 Buffered Image After click
203+
* return Boolean
204+
*/
205+
206+
static Boolean compare(BufferedImage bufferedImage1, BufferedImage bufferedImage2) {
207+
if (bufferedImage1.getWidth() == bufferedImage2.getWidth()
208+
&& bufferedImage1.getHeight() == bufferedImage2.getHeight()) {
209+
for (int x = 0; x < bufferedImage1.getWidth(); x++) {
210+
for (int y = 0; y < bufferedImage1.getHeight(); y++) {
211+
if (bufferedImage1.getRGB(x, y) != bufferedImage2.getRGB(x, y)) {
212+
return false;
213+
}
214+
}
215+
}
216+
} else {
217+
return false;
218+
}
219+
return true;
220+
}
221+
}

0 commit comments

Comments
 (0)