JTable resize table header does autoscroll - java

This is my issue. I have the code below. What it does is when I drag a column over the edge of the panel, my panel scrolls by itself.
However, the problem is, with this feature, every time I resize the column width, the panel also scrolls to the top.
For example, I have 1000 rows and I highlight the 999th row at the bottom. When I resize the column width, the panel scrolls to the top. How do I make the panel to stay at wherever I was?
I want my table to autoscroll horizontally, but not vertically.
table.getTableHeader().addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e)
{
Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
((JTableHeader)e.getSource()).scrollRectToVisible(r);
table.scrollRectToVisible(r);
}
});

You are resetting JTable's scroll bar position by this statement:
table.scrollRectToVisible(r);
Here x position of rectangle is correct, as it is same for JTableHeader and JTable. But y position should be different for both. But you are using y position from JTableHeader for JTable also.
To make it work correctly, get y position of JViewPort of JScrollPane used by JTable.
Use this y position for the rectangle used in above statement. This should correct the issue.

Related

How can I have my top level Jpanel set its location relative to a jlabel that is in another jpanel's grid?

The scenario: I have a UI that contains a JPanel (call it topGrid) with a grid layout in a JFrame at the top level. Within topGrid, I have placed another JPanel (midGrid) with grid layout. Inside midGrid, is another JPanel (bottomGrid) that has a JLabel that I populate with images depending on an array and what their instance is within that array.
The goal: I would like the topGrid to center its view on a specific object found in bottomGrid. (Picture a game that as the player icon moves, the game's grid moves to center on that icon and also when the game is started it is already centered for the user.)
I've considered getting the Point from bottomGrid and trying to pass it over to topGrid but doesn't seem to pull the correct information. The only way i know to find where the player is, is to iterate through all the components and check instances. this would have to be done once for the topGrid and again for midGrid to find the player at bottomGrid. then pass the Point data. Then use setLocation() on the appropriate JPanel minus the distance from the center.
Has anyone else tried this and have a more effective or elegant way to go about it? What other options could I explore?
Thanks for any feedback.
Creating the grid within topGrid's JPanel:
public void createTopGrid()
{
int rows = galaxy.getNumRows();
int columns = galaxy.getNumColumns();
pnlGrid.removeAll();
pnlGrid.setLayout(new GridLayout(rows, columns));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Position pos = new Position(galaxy, row, col);
Sector sector = galaxy.getSector(pos);
GalaxySector sectorUI = new GalaxySector(sector);
pnlGrid.add(sectorUI);
}
}
}
Creating the grid within midGrid's JPanel:
public void createOccupantIcons()
{
pnlGridOccupants.removeAll();
Occupant[] occs = sector.getOccupantsAsArray();
for ( Occupant occ : occs )
{
GalaxyOccupant occupant = new GalaxyOccupant(occ, sector);
pnlGridOccupants.add(occupant);
}
}
The Image icons for each occupant in the midGrid are pulled from an IconRep String in the model in the bottomGrid class' JPanel and added into a JLabel as needed in FlowLayout.
For visual reference:
Where green square is topGrid JPanel, red squares are midGrid JPanel, and the black square is the bottomGrid JPanel with the white circle for the player image inside a JLabel. The blue circle represents a viewport the user will see the game through and is where I want the player icon to be centered to. Currently the user can move the grid's using very inelegant buttons in the area around the viewport. That might be sufficient but at the start of the game the player has to move the grid around until they can locate their icon.
You might also look at JScrollNavigator, examined here. It would allow you to navigate on a thumbnail image of your entire world, seen at full size in an adjacent scroll pane.
Off the top of my head, I would store all the references you want to in some kind of model.
You could use this model to update the views based on selection requirements.
This allows the you to centralise the logic for finding and updating the elements without knowing or caring out the other UI elements

JTable refreshing

I use JTable with horizontal and vertical scrollbars. My JTable has empty space after rows with data.
When I open panel that is situated down of my table it hides a part of JTable and scrolling appears on JTable. This is normal behavior, but then I close that panel, empty space without data becomes grey instead of white color.
This only happens when I have horizontal scrollbar on my JTable. I suppose I must force JTable to repaint, I tried resizeAndRepaint() on TableHeader and JTable but it didn't work.
Please help! Thanks!
Here is resize() code invoked if any resize action was performed on table
for (int i = 0; i < columsNum; i++){
TableColumn column = this.getColumnModel().getColumn(i);
int preferedSize = //current size
int minimumSize = // min size
if (minimumSize != ColumnSizeCalculator.UNDEFINED_WIDTH)
column.setMinWidth(minimumSize);
column.setPreferredWidth(preferedSize);
}
this.revalidate();
this.repaint();
By default, a JTable does not fill the viewport of a scrollpane in the vertical direction. Try to call
table.setFillsViewportHeight(true);
on your table, then repainting the table should work.

SWT: Problem with sashform children's width

My application's got one horizontal SashForm with two children. The leftmost one should always be, at least, 200 pixels width. So I added a ControlListener to the left component. In its controlResized event I check the component's width. When it's smaller than 200, I set its bounds' width to 200. It apparently works as the component gets resized to that width, but the sashform stops working - the sash is no longer visible, it remains under the component.
Does anybody know what am I missing?
I've tried:
component.addControlListener(new ControlAdapter() {
#Override
public void controlResized(ControlEvent e) {
if (component.getBounds().width < 200) {
Rectangle bounds = component.getBounds();
bounds.width = 200;
component.setBounds(bounds);
}
}
});
here is an example
Just a guess, but maybe you need to call pack() or layout() on the SashForm after you programatically resize the inner component.

Checking if a row appears on screen before force scrolling to it?

I am using a Swing JTable, and i want to force scroll to a specific row inside it. That is simple using scrollRowToVisible(...), but i want first to check this row is not already visible on the screen before scrolling to it, as if it is already visible there is no need to force scroll.
How can i do that ?
The link below is to an article that determines if a cell is visible. You could use that - if the cell is visible, then the row is visible. (But of course, possibly not the entire row, if horizontal scrolling is also present.)
However, I think this will fail when the cell is wider than the viewport. To handle this case, you change the test to check if the top/bottom of the cell bounds is within the vertical extent of the viewport, but ignore the left/right part of the cell. It is simplest to set the left and width of the rectangle to 0. I've also changed the method to take just the row index (no need for column index) and it returns true if the table is not in a viewport, which seems to align better with your use-case.
public boolean isRowVisible(JTable table, int rowIndex)
{
if (!(table.getParent() instanceof JViewport)) {
return true;
}
JViewport viewport = (JViewport)table.getParent();
// This rectangle is relative to the table where the
// northwest corner of cell (0,0) is always (0,0)
Rectangle rect = table.getCellRect(rowIndex, 1, true);
// The location of the viewport relative to the table
Point pt = viewport.getViewPosition();
// Translate the cell location so that it is relative
// to the view, assuming the northwest corner of the
// view is (0,0)
rect.setLocation(rect.x-pt.x, rect.y-pt.y);
rect.setLeft(0);
rect.setWidth(1);
// Check if view completely contains the row
return new Rectangle(viewport.getExtentSize()).contains(rect);
}
Determining if a cell is visible in JTable

How to get the coordinate of Gridlayout

I set my JPanel to GridLayout (6,6), with dimension (600,600)
Each cell of the grid will display one pictures with different widths and heights.
The picture first add to a JLabel, and the JLabel then added to the cells.
How can retrieved the coordinate of the pictures in the cells and not the coordinate of cells? So far the out give these coordinate which equal height and width even on screen the pictures showed in different sizes.
e.g.
java.awt.Rectangle[x=100,y=100,width=100,height=100]
java.awt.Rectangle[x=200,y=100,width=100,height=100]
java.awt.Rectangle[x=300,y=100,width=100,height=100]
The reason why I used GridLayout instead of gridBagLayout is that, I want each pictures to have boundary. If I use GridBagLayout, the grid will expand according to the picture size.
I want grid size to be in fix size.
JPanel pDraw = new JPanel(new GridLayout(6,6));
pDraw.setPreferredSize(new Dimension(600,600));
for (int i =0; i<(6*6); i++)
{
//get random number for height and width of the image
int x = rand.nextInt(40)+(50);
int y = rand.nextInt(40)+(50);
ImageIcon icon = createImageIcon("bird.jpg");
//rescale the image according to the size selected
Image img = icon.getImage().getScaledInstance(x,y,img.SCALE_SMOOTH);
icon.setImage(img );
JLabel label = new JLabel(icon);
pDraw.add(label);
}
for(Component component:components)
{
//retrieve the coordinate
System.out.println(component.getBounds());
}
EDITED: I have tried this but not working :-(
for(Component component: pDraw.getComponents()){
System.out.println(((JLabel)component).getIcon());
}
How can I get output like these?
java.awt.Rectangle[x=300,y=100,width=50,height=40]
java.awt.Rectangle[x=400,y=400,width=60,height=50]
Do your images appear at the desired size ?
i think so.
Anyway, from what your code seems to do, I guess it gets the labels size, and not the icons size. JLabel, like any JComponent, are in fact Container instance. As such, their size depends upon constraints. As a consequence, in a GridLayout, a JLabel will have the size of a cell, whereas the contained Icon will have the size of the image.
As a consquence, to get image size, you have to call ((JLabel) component).getIcon() to be able to retrieve effective image dimension.

Categories