I am builing an expanding Window/layout that shall expand/shrink on supplied data, possibly expanding to fill the browser window.
Edit: The scroll bars shall be on the work-area, not the window.
So far i have only managed to get it working vertically with a simple list of labels (see simple_list.png).
Vertical scrollbar appear when browser window filled vertically Horizontal scrollbar always present and width of window/layout seems directed by length of panel title and window icons at top-right.
Edit: Scroll bars OK on Panel. No horizontal expansion.
It fails completeley for a GridLayout (see gridlayout.png).
Edit: I.E no scrollbars on work-area (Panel)
The final layout is supposed to have a central work area and header, footer, left/right areas. The work area to expand according to data.
Barked up the wrong tree? CSSLayout? Not for Vaadin?
Any help/guidance appreciated.
A simplified test case below (Vaadin 7, subclassing Window).
public TestWindow() {
super.setSizeUndefined();
VerticalLayout vL = new VerticalLayout();
vL.setSizeFull();
super.setContent(vL);
//vL.addComponent(buildHeader());
Panel workArea = new Panel();
workArea.setSizeFull();
workArea.setCaption("View");
vL.addComponent(workArea);
vL.setExpandRatio(workArea, 1f);
//vL.addComponent(buildFooter());
//-----------------------------
VerticalLayout view = new VerticalLayout();
view.setSizeUndefined();
workArea.setContent(view);
for (int i=0; i < 100; i++) {
String s = "view line "+i;
for (int j=0; j < 10; j++) {
s += "____________________"+j;
}
Label line = new Label(s);
line.setSizeUndefined();
view.addComponent(line);
}
//=============================
/*
VerticalLayout view = new VerticalLayout();
view.setSizeUndefined();
workArea.setContent(view);
GridLayout gl = new GridLayout();
gl.setSizeUndefined();
view.addComponent(gl);
view.setExpandRatio(gl, 1);
gl.setColumns(2);
for (int i=0; i < 100; i++) {
Label line = new Label("view line "+i);
line.setSizeUndefined();
gl.addComponent(line);
}
*/
//------------------------------
center();
setModal(true);
setDraggable(true);
UI.getCurrent().addWindow(this);
}
simple_list.png
gridlayout.png
Vaadin documentation says:
If a sub-window has a fixed or percentual size and its content becomes too big to fit in the content area, a scroll bar will appear for the particular direction. On the other hand, if the sub-window has undefined size in the direction, it will fit the size of the content and never get a scroll bar.
Source: https://vaadin.com/docs/v7/framework/layout/layout-sub-window.html
Related
In my GUI, I have a JSplitPane containing two JTextArea controls enclosed in a JScrollPane, all enclosed in a JFrame.
I am having problems with the scrollbar updating when the window is maximized. The scrollbar updates correctly when the window is minimized, but fails to appear when I try to create a new line in one of the text areas. It updates when I minimize the window, but I am trying to get the scroll bar to update when the window is maximized.
this.text = new JTextArea(15, 70);
this.text.getDocument().addDocumentListener(this);
this.text.setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.text.setLineWrap(true);
//Create lines
JTextArea lines = new JTextArea(15, 2);
lines.setBorder(BorderFactory.createLineBorder(Color.BLACK));
int lineHeight = lines.getRows();
int i = 1;
while (i <= lineHeight + 1) {
lines.append(Integer.toString(i) + "\n");
i++;
}
lines.setEditable(false);
//Pack it all
JSplitPane combo = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, lines,
this.text);
combo.setResizeWeight(0d / 10d);
//Create scrolling area
JScrollPane scroller = new JScrollPane(combo);
scroller.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
I have some more code regarding a menu and putting everything into a frame if that is important. I believe I am using the default layout manager.
I have a JScrollPane with a number of JLabel objects in a panel using a GridBagLayout. Each of the labels is displaying HTML text with rich elements which varies at run time.
I would like all labels to have the same width (driven by the width of the scroll pane) but vary in height depending on their content with the text wrapping (as is handled automatically by JLabel). If the labels exceed the scroll pane's height then a vertical scroll bar should appear.
Here is some sample code to demonstrate the problem:
public class ScrollLabels extends JFrame {
private final JPanel labelPanel = new JPanel(new GridBagLayout());
private final GridBagConstraints c = new GridBagConstraints();
public ScrollLabels() throws HeadlessException {
super("Scroll Labels");
}
public void createUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scroller = new JScrollPane(labelPanel);
add(scroller);
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
c.fill = GridBagConstraints.HORIZONTAL;
addLabel("Here is <em>Rich Text</em>");
addLabel("Here is <ul><li>A</li><li>List</li></ul>");
addLabel("Here is <table><tr><th>A</th><th>Table></th></tr></table");
addLabel("Here is more <em>Rich Text</em>");
addLabel("Here is even more <b>Rich Text</b>");
addLabel("Here is a long sentence that should wrap when the panel "
+ "is too small for the text.");
pack();
}
private void addLabel(String text) {
JLabel label = new JLabel("<html>" + text + "</html>");
label.setBorder(BorderFactory.createEtchedBorder());
labelPanel.add(label, c);
}
public static void main(String[] args) {
ScrollLabels frame = new ScrollLabels();
frame.createUI();
frame.setVisible(true);
}
}
It correctly resizes the labels horizontally and shows scroll bars where appropriate. What it doesn't do is resize labels vertically to fit them within the scroll pane.
Here are the various things I have tried:
Changing the GridBagConstraint values. There are good controls for how to expand and contract components but I can't see any way to set a min or max width.
Setting the JScrollPane scroll bar policy to never show horizontal scroll bars. This just cuts off the label text rather than wrapping the text.
Manually setting the label size - i.e. setting the width from the scroll pane and the height depending on the text. I can't see an easy way to get the correct height of rich HTML text given a fixed width. In any case I'd prefer to have a layout manager that can do the job rather than manually coding preferred sizes.
The one thing I haven't tried yet is creating a custom layout manager. I suspect this might be the right answer but would like to see if any of you have an easier solution that I'm not seeing.
I would like all labels to have the same width (driven by the width of the scroll pane) but vary in height depending on their content
You need to implement the Scrollable interface on your panel and override the getScrollableTracksViewportWidth() method to return true. You will also need to provide default implementations for the other methods of the interface.
Or you can use the Scrollable Panel which provides method that allow you to set the scrolling properties.
JPanel grid = new JPanel();
GridLayout layout = new GridLayout (6,7,0,0);
grid.setLayout (layout);
slot = new ImageIcon ("");
for (int x = 0; x < 42; ++x)
{
slotbtn = new JButton(slot);
slotbtn.setContentAreaFilled (false);
//slotbtn.setBorderPainted (false);
slotbtn.setBorder (BorderFactory.createEmptyBorder (0,0,0,0));
slotbtn.setFocusPainted (false);
grid.add(slotbtn);
}
This is the output I get:
I am creating a 6x7 grid. The output I need is for there to be no space in between the rows and columns, everything should be compressed together. I tried pack and it didn't work. What am I doing wrong?
-- I tried FlowLayout but I had to resize the frame and I have other buttons on the frame so I don't think I'd prefer resizing it to make the buttons fit in their proper places.
-- I placed this JPanel inside another jpanel(which uses borderlayout and contains two other panels) and I placed it at the center, the two other panels North and South.
this issue because you divide the grid (the whole size of grid) to 7*6 so if you re-size the window you will see this gaps changed so if you wan't to remove this gab
calculate the size of the window (ex: width = 7* width of your image , hight = 6*hight of your mage)
or re-size your image
JButton employs a margin property to provide additional padding to the content area of the button, you could try using...
slotbtn.setMargin(new Insets(0, 0, 0, 0));
I would also try using something like slotbtn.setBorder(new LineBorder(Color.RED)); to determine if the spacing is from the button, icon or layout
GridLayout will also provide each cell with equal amount of space, based on the available space to the container, this means that the cell may increase beyond the size of the icon.
While a little more work, GridBagLayout would (if configured properly) honour the preferred size of each component.
Have a look at How to use GridBagLayout for more ideas.
I get no margins using your code, with any image I use. Check your image. And maybe post a runnable example replicating the problem. Maybe there's something going on you're not showing us. I'd start by checking the image for margins. Check it against this. If it still has margins, than its your image. Also, Don't set the size to anything! You may be stretching the panel unnecessarily, which will cause the gaps. Also if there an of your other panels are larger than the grip panel, it will also cause it to stretch. But take all your set(Xxx)sizes out and see what happens. Just pack()
import java.awt.GridLayout;
import javax.swing.*;
public class TestButtonGrid {
public TestButtonGrid() {
ImageIcon icon = new ImageIcon(getClass().getResource("/resources/stackoverflow3.png"));
JPanel panel = new JPanel(new GridLayout(6, 7));
for (int i = 0; i < 42; i++) {
JButton slotbtn = new JButton(icon);
slotbtn.setContentAreaFilled(false);
//slotbtn.setBorderPainted (false);
slotbtn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
slotbtn.setFocusPainted(false);
panel.add(slotbtn);
}
JFrame frame = new JFrame();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new TestButtonGrid();
}
}
I'm trying to create a grid for my snakes and ladders game in java, but I have a small problem where there is an unwanted space in the grids I've created
Does anyone know how I can get rid of that?
This is the code I have for the client side (Client.java):
//Initialize Grid Cells
private Cell[][] cell = new Cell[10][10];
//Create Grid Layout
GridLayout GameBoard = new GridLayout(10, 10, 1, 1); //Create GridLayout
GameArea.setLayout(GameBoard); //Add GridLayout
GameArea.setPreferredSize(new Dimension(590,560));
GameArea.setOpaque(false);
//Add Cells to Grid
for (int v = 0; v < 10; v++)
for (int h = 0; h < 10; h++)
GameArea.add(cell[v][h] = new Cell(v, h, this));
//Individual Image on Each Cell
cell[1][0].add(new JLabel(GreenGrid));
This is the code I have for the cells(Cells.java), it also extends JPanel:
//Indicate the row and column of this cell in the board
private int GridRow;
private int GridColumn;
private Client parent;
public Cell(int GridRow, int GridColumn, Client GUI) {
this.GridRow = GridRow;
this.GridColumn = GridColumn;
this.parent = GUI;
setBorder(new LineBorder(Color.orange, 1)); // Set cell's border
setBackground(Color.gray);
}
I can't see your image, but I suspect that you have a layout issue. Does your Cell extend JPanel by the way? Do you set its layout manager or do you use the default FlowLayout?
Consider:
You should not call setPreferredSize(...) on the GameBoard as that will then dictate your grid cell size, which is too big.
Rather, the Cells themselves should be dictating the size of themselves and the entire grid.
Consider having Cell override getPreferredSize() and returning the dimension of the JLabel's image (if one is present) or else returning the super's result.
Be sure to call pack() on your top-level window after adding all components and before setting it visible.
Consider having Cell use a BorderLayout and adding your JLabel to the BorderLayout.CENTER position so that it fills the cell (if that's what you want it to do).
For more help and better help, consider creating and posting an sscce.
Your first problem is here...
GridLayout GameBoard = new GridLayout(10, 10, 1, 1); //Create GridLayout
As described in the JavaDocs...
public GridLayout(int rows,
int cols,
int hgap,
int vgap)
Creates a grid layout with the specified number of rows and columns.
All components in the layout are given equal size.
In addition, the horizontal and vertical gaps are set to the specified
values. Horizontal gaps are placed between each of the columns.
Vertical gaps are placed between each of the rows.
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
What this means is, you are supplying the gap by supplying non-zero values to the hgap and vgap parameters.
If you used something like...
GridLayout GameBoard = new GridLayout(10, 10); //Create GridLayout
You would end up with something like...
As has already been mentioned, I would avoid using GameArea.setPreferredSize(new Dimension(590,560)); and instead, override the getPreferredSize method the Cell class. Because of the way that GridLayout works, this won't stop the cells from been resized, but this might be desirable anyway...
I've been trying to get a GridPane's content to behave regarding auto-size but I'm relatively new to JavaFX, so I've not had any success. Basically, each column is what appears to me to be a completely random size, and I have no idea how to make them grow correctly. If I try to set column constraints, the content sometimes disappears completely, sometimes it's just sized completely arbitrarily. Trying to bind preferred width to anything else also fails to work. I'm sure the error is mine, though. Here's my code (the contentHolder is a ScrollPane with vGrow set to ALWAYS):
int row = 1;
GridPane gridPane = new GridPane();
for (List<IndexObject> stepList : search) {
Label itemLabel = new Label();
itemLabel.setText(String.valueOf(row));
TreeItem<String> treeRoot = new TreeItem<>(stepList.get(0).getPath());
for (int line = 1; line < stepList.size(); line++) {
treeRoot.getChildren().add(new TreeItem<>(stepList.get(line).getPath()));
}
TreeView treeView = new TreeView();
treeView.setShowRoot(true);
treeView.setRoot(treeRoot);
treeRoot.setExpanded(true);
IndexObject lastObject = stepList.get(stepList.size() - 1);
TextArea output = new TextArea();
output.setText(lastObject.prettyPrint());
gridPane.addRow(row, itemLabel, treeView, output);
row++;
}
contentHolder.setContent(gridPane);
Everything up to the contentHolder is defined in fxml. Here's what it looks like. No entry has anywhere near the height that is automatically assigned, but all the widths are too small. What am I missing?
The answer is that the scroll pane does not automatically resize until you make it:
<ScrollPane VBox.vgrow="ALWAYS" fitToWidth="true">
at which point everything works as expected.