I have JTable with two scrollbars (horizontal and vertical). When I use scrollRectToVisible, it return me Rectangle and this action cause that vertical and horizontal scrollbars automatically move to specified rows/columns. How can I move automatically vertical scrollbar to desired place and horizontal scrollbar should stay inactive? This method should show me selected row but my JTable is very wide and I would like to avoid automatically movement (horizontal) at the beginning (left side) of track -> simple say, I expect that horizontal position is unchanged.
public void goToSelected() {
int selectedRow = this.getSelectedRow();
if (selectedRow >= 0)
this.scrollRectToVisible(this.getCellRect(selectedRow, 0, true));
}
The horizontal position might change because you are specifying a column index (0) and the specified column might be invisible. You can simply combine the values of the currently visible area and the cell’s vertical range to get the desired effect:
Rectangle target = getCellRect(selectedRow, 0, true), vis = getVisibleRect();
target.x = vis.x;
target.width = vis.width;
scrollRectToVisible(target);
Related
I'm currently working on a table and want all the values in each cell to be centered.
My current code is this:
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
cell.setHorizontalAlignment(HorizontalAlignment.CENTER);
cell.add(new Paragraph(text).setRotationAngle(hasRotation? rotation : 0));
cell.setBorder(Border.NO_BORDER);
return cell;
But my problem is, that the horizontal alignment doesn't work. It centers the text on the vertical length of the cell, but it's bound to the left side of the cell, even though I specified the horizontal alignment to be centered. You can see what I mean in the image below. Any help would be apprechiated
For anyone interested. The problem was, that you can't set the rotation and set the text to be centered. I replaced the code with this, which seems to work for me:
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
Paragraph p = new Paragraph(text);
p.setFontSize(fontSize);
p.setTextAlignment(TextAlignment.CENTER);
if (hasRotation) {
p.setRotationAngle(rotation);
p.setPaddingTop(factor * (cellWidth / 2) - fontSize / 1.5f);
}
cell.setBorder(Border.NO_BORDER);
cell.add(p);
return cell;
I have a RecyclerView that displays a vertical list of strings:
Row0
Row1
Row2
Row3
Row4
...
I'm using the function recyclerView.scrollToPosition(position); to jump to a row. However, the row I want to jump to, ends up on the BOTTOM of the view!
For example if I do recyclerView.scrollToPosition(17); I get:
Row13
Row14
Row15
Row16
Row17 <--- 17 is at bottom (last visible row)
What I want is:
Row17 <-- 17 to be on top (first visible row)
Row18
Row19
Row20
Row21
How can I achieve this?
The default behavior of the .scrollToPosition() is to stop scrolling once the row you scroll to shows up on the screen. You can use scrollToPositionWithOffset() with a fixed offset, so that it sums up to the scroll value.
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager != null) {
layoutManager.scrollToPositionWithOffset(position, 20);
}
UPDATE
how can I compute the offset value? Each row in my RecyclerView has a different height. Also I don't see how to measure it.
Now you can compute the difference between the first and last visible items on the screen and that will work only when the last visible item on the screen is current your item that you want to push to first.
layoutManager.scrollToPosition(position));
int firstItemPosition = ((LinearLayoutManager) recyclerview.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
int lastItemPosition = ((LinearLayoutManager) recyclerview.getLayoutManager())
.findLastCompletelyVisibleItemPosition();
layoutManager.scrollToPositionWithOffset(position,
Math.abs(lastItemPosition - firstItemPosition));
If the Table has more content, it displays its content within a ScrollPane.
If the TableView has less content, it fills itself with empty space.
How to achieve adaptive?
I can't use fixedCellSize,because my cell is wrapping.
We do this for Width just try it for Height
if(TableData.size() < 15) {// Format TableView to display Vertical ScrollBar
ptable.setPrefWidth(336);// 19 is the off set
}else {
ptable.setPrefWidth(355);
} ptable.setItems(TableData);
I have to check that horizontal scroll bar is scrollable or not. I tried by doing check element is displayed or not which comes after horizontal scroll using
Javascript scrollIntoView but how it can make sure that scrollbar is working.
Because scroll bar position not changing scrollIntoView only scrolling the element and making as displayed on the screen. But scroll bar not scrolling.
Try below options to scroll horizontally :
// scroll at a particular element
WebElement e1 =
driver.findElement(By.xpath(“//input [#id=’ElementID’]”));
((JavascriptExecutor)driver).executeScript(“arguments[0].scrollIntoView();”, e1);
Where ‘e1’ is the locator where you want to scroll.
// scroll at a particular coordinate,.
((JavascriptExecutor)driver).executeScript(“window.scrollBy(200,300)”);
// scroll horizontally in the right direction.
((JavascriptExecutor)driver).executeScript(“window.scrollBy(2000,0)”);
// scroll horizontally in the left direction.
((JavascriptExecutor)driver).executeScript(“window.scrollBy(-2000,0)”);
The idea is simple- first, try to move the scrollbar bar to either side and check whether it's actually moved or not.
//scrol 1px to the left
$(document).scrollLeft(1);
if($(document).scrollLeft() != 0){
//there's a scroll bar
}else{
//there's no scrollbar
}
//scroll back to original location
$(document).scrollLeft(0);
Let's convert it to a Java method and use it in your script.
/**
*
* #param js reference to JavascriptExecutor
* #param element is a string of locator (i.e. #scroll > span etc.)
* #return true if scrollbar is scrollable
*/
boolean testScrollBar(JavascriptExecutor js, String element){
String jq = String.format("return $('%s').scrollLeft()", element);
String jq1 = String.format("$('%s').scrollLeft(1)", element);
String jq2 = String.format("$('%s').scrollLeft(0)", element);
System.err.println("Test1: "+js.executeScript(jq));
js.executeScript(jq1);
Long currentPos = (Long)js.executeScript(jq);
System.err.println("Test2: " + currentPos);
js.executeScript(jq2);
return currentPos != 0;
}
I hope it helps you.
I'm working on my first Java Swing project (really my first GUI project, unless you count client-side web programming), and I'm having an aesthetic issue. I'm making a Sudoku board in a JPanel. The panel is laid out with a 3x3 GridLayout, with each of its nine cells containing JPanel filled with another 3x3 GridLayout. The outer grid has wider borders to indicate the "boxes" of a Sudoku board, and the inner grid thinner borders to display the "cells" (here's a screenshot if you need help visualizing it).
The problem is that I'm getting extra space between the borders of the inner and outer grids, which looks just terrible. I've tried setting the insets to zero explicitly, which didn't do anything. The only way I can think to fix it is to eliminate the GridLayout nesting altogether and instead use one 9x9 grid, setting the individual cell borders to be thicker at the top/bottom/left/right where appropriate; however, each cell's border changes color and thickness when it gains focus, and I can't think of a graceful way to implement that strategy. I've also been looking into other layouts, but GridLayout seems perfect for this purpose (each cell should be the same size).
Here's the constructor for BoardPanel (extends JPanel), I tried to omit any extraneous code:
BoardPanel(Board newBoardData)
{
/**
* Instance variable initializations, call to super(), etc. omitted.
*/
// Outer grid initialization
// In pictures, .getBoxWidth() and .getBoxHeight both return (int)3
setLayout(new GridLayout(boardData.getBoxWidth(), boardData.getBoxHeight(), 0, 0));
setBorder(new LineBorder(colorGridBorders, 2));
// Inner grid array; .getBoardSize() returns (int)9
JPanel innerBoxGridPanels[] = new JPanel[boardData.getBoardSize()];
GridLayout innerBoxGridLayout = new GridLayout(boardData.getBoxHeight(), boardData.getBoxWidth(), 0, 0);
LineBorder innerBoxLineBorder = new LineBorder(colorGridBorders, 1);
for (int columnIndex = 0; columnIndex < boardData.getBoardSize(); ++columnIndex)
{
for (int rowIndex = 0; rowIndex < boardData.getBoardSize(); ++rowIndex)
{
// CellPanel derives from JPanel; has a call to setBorder() to create inner grid lines
cellPanes[columnIndex][rowIndex] = new CellPanel(columnIndex, rowIndex, boardData.getCell(columnIndex, rowIndex));
}
}
for (int box = 0; box < boardData.getBoardSize(); ++box)
{
// Inner grid initialization
innerBoxGridPanels[box] = new JPanel(innerBoxGridLayout);
innerBoxGridPanels[box].setBorder(innerBoxLineBorder);
// Adding cells to inner grid
for (int cell = 0; cell < boardData.getBoardSize(); ++cell)
{
innerBoxGridPanels[box].add(cellPanes
[( cell % boardData.getBoxWidth() )
+ ( ( box % boardData.getBoxHeight() ) * boardData.getBoxWidth() )]
[( cell / boardData.getBoxWidth() )
+ ( (box / boardData.getBoxHeight() ) * boardData.getBoxHeight() ) ]);
}
// Adding inner grids to outer grid
add(innerBoxGridPanels[box]);
}
}
Here's a screenshot of the rendered board at various sizes. In the upper-right image, you can see that if you adjust the window size just right you can get rid of most of the extra space (there's still some at the edges though).
Has anyone had this sort of problem with nested GridLayouts before and found a solution? Any help would be greatly appreciated, I've been pulling my hair out over this for over a day now.
Seems like a problem with the window size. Let´s say there are 2 panels horizontally inside an outer panel. The outer pane has a border of size 2 and the inner panels have a border of size 1.
If the window has a size of 18 for example, we have
2px for outer border
1px for inner border
5px for panel content
1px for inner border
1px for inner border
5px for panel content
1px for inner border
2px for outer border
So there is no space and both inner panels have same size
If for whatever reason the window size is changed to 19, there is a need to create a gap between the panels to mantain them of equal size.
If the size is 20, both panels get +1 to his size and there is no gap needed.
To solve this you can use a fixed size of the window (one you know has no gaps), or add a padding to the outer panel when the window is resized so the padding makes the rest of the frame to have a size that produces no gaps. (in your case, if my maths are fine, should be 20 + x/3)
If you want to discard the use of nested panels and change the cell border when has the focus, you need a LineBorder instance for each cell. In your code, all cells are using the same LineBorder instance.