I'm trying to create a simple display using SWT. So far, I am successfully displaying information from my database and displaying it using a RowLayout, with each row containing a GridLayout. It looks like this:
What I really want is for the rows to extend to take up the full width of the window. How do I achieve this?
Thanks for your help!
The usual way to achieve this is to use GridData. This GridData tells the component how to behave within it's parent, e.g. how to spread across the parent.
By using:
component.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
you tell the component to occupy as much space as possible horizontally, but only the necessary space vertically.
Here is a small example that should behave in the way you expect it to:
public class StackOverflow
{
public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new Shell(display);
/* GridLayout for the Shell to make things easier */
shell.setLayout(new GridLayout(1, false));
for(int i = 0; i < 5; i++)
{
createRow(shell, i);
}
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static void createRow(Shell shell, int i)
{
/* GridLayout for the rows, two columns, equal column width */
Composite row = new Composite(shell, SWT.NONE);
row.setLayout(new GridLayout(2, true));
/* Make each row expand horizontally but not vertically */
row.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
/* Create the content of the row, expand horizontally as well */
Button first = new Button(row, SWT.PUSH);
first.setText("FIRST " + i);
first.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
Button second = new Button(row, SWT.PUSH);
second.setText("SECOND " + i);
second.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
}
}
This is what it looks like after startup:
and after resizing:
As a side note: I would suggest reading this tutorial from Eclipse about Layouts, if you haven't already read it. Every SWT developer should have read it.
Related
I have a window that must show a list of buttons all below each other.
All buttons must be square of a specific size (size can change while running).
This simple example works as in it shows all the buttons.
public class Main
{
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
val scrollPanel = new ScrolledComposite(shell, SWT.V_SCROLL);
scrollPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
scrollPanel.setLayout(new FillLayout());
val gridPanel = new Composite(scrollPanel, SWT.NONE);
val gridLayout = new GridLayout(1, false);
gridPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
gridPanel.setLayout(gridLayout);
scrollPanel.setContent(gridPanel);
val blue = display.getSystemColor(SWT.COLOR_BLUE);
val red = display.getSystemColor(SWT.COLOR_RED);
scrollPanel.setBackground(blue);
gridPanel.setBackground(red);
val exitButton = new Button(gridPanel, SWT.PUSH);
exitButton.setText("Exit");
exitButton.addListener(SWT.Selection, touchEvent -> shell.dispose());
for (int i = 1; i <= 10; i++)
{
val button = new Button(gridPanel, SWT.PUSH);
button.setText("Item: " + i);
button.setSize(60, 60);
gridPanel.setSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
shell.setSize(100, 700);
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
However, whenever I do the gridPanel.computeSize(), the buttons lose their size that is set by button.setSize().
When I remove the gridPanel.setSize() after adding a button, the size will be 0 and the gridPanel is never shown at all.
When I set the gridLayout on the scrollPanel and add the buttons to that, then only one button is shown.
(The last button if I use setContent() and the second (for whatever reason) if I do not use setContent() and just rely on the constructor of the buttons.)
At this moment, I am quite out of my options so if anyone can clear something up of this scenario, then please go ahead.
If you use a layout (which you should), you must not use setSize() or otherwise interfere with the layout.
Use widthHint and heightHint of GridData instead to control the size of the buttons.
For example:
GridData gridData = new GridData( SWT.BEGINNING, SWT.CENTER, false, false );
gridData.widthHint = 60;
gridData.heightHint = 60;
button.setLayoutData( gridData );
First of all, setSize is only going to work properly when you are not using layouts (absolute positioning).
If you are using a layout, it will automatically set the components size based on the layout itself and how you define the layout data of the components.
In general, it is highly recommended to use layouts over absolute positioning.
In case of GridLayout, you can specify a component size via widthHint and heightHint in its GridData, for example:
Button button = new Button(gridPanel, SWT.PUSH);
button.setText("Item: " + i);
GridData buttonLayoutData = new GridData();
buttonLayoutData.widthHint = 60;
buttonLayoutData.heightHint = 60;
button.setLayoutData(buttonLayoutData);
Other observations:
to make the ScrollComposite work properly you should add these lines:
scrollPanel.setExpandHorizontal(true);
scrollPanel.setExpandVertical(true);
scrollPanel.setMinSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
in particular, setMinSize will tell the ScrollComposite at what size it should make the scrollbar appear.
if the parent layout is a FillLayout you should not set layout data on its children. It won't do anything since it is not expected. So you should remove the setLayoutData from scrollPanel and gridPanel.
if you want to change the button size at a later moment, just get its layout data, modify the hints and ask the component to layout (also don't forget to notify the scrollbar of the change with setMinSize):
GridData buttonLayoutData = (GridData) button.getLayoutData();
buttonLayoutData.widthHint = 40;
buttonLayoutData.heightHint = 40;
button.requestLayout();
scrollPanel.setMinSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
I'm trying to add 7 Text widgets to a GridLayout row.
I want them all to be of the same width, but they come out funky:
//Columns
for(int i=0;i<7;i++) {
text = new Text(shell, SWT.BORDER);
text.setEditable(true);
data = new GridData(SWT.FILL, SWT.TOP,true,false,1,1);
text.setLayoutData(data);
cols.add(text);
}
Things I've tried:
Almost any combination of FILL/TOP and true/false to the GridData constructor (I was desperate).
Setting data.minimumWidth and data.widthHint to (window width)/7.
Yet the widgets are always in varying degrees of disarray.
You specify this on the GridLayout constructor, second parameter:
GridLayout layout = new GridLayout(7, true);
specifies 7 columns of equal width.
You can also use
layout.makeColumnsEqualWidth = true;
I have a list in a composite and is defined in the following way :
List list = new List(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
when the list is in disabled state (list.setEnabled(false);), and the values inside the list are more than the height of the list, is there any way to make the vertical scroll bar enabled?
The scroll bars are handled by the OS. Consequently, the OS will decide when to show/hide the scroll bars and when to let the user use them. You can't influence that.
There is a very similar question here.
However, you can wrap your List in a ScrolledComposite. This way, you can still scroll even if the List is disabled:
public static void main(String[] args)
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final ScrolledComposite composite = new ScrolledComposite(shell, SWT.V_SCROLL);
composite.setLayout(new FillLayout());
List list = new List(composite, SWT.NONE);
for (int i = 0; i < 20; i++)
{
list.add("Item: " + i);
}
composite.setContent(list);
composite.setExpandHorizontal(true);
composite.setExpandVertical(true);
composite.setMinSize(list.computeSize(SWT.DEFAULT, SWT.DEFAULT));
list.setEnabled(false);
shell.pack();
shell.setSize(100, 150);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Looks like this:
Context
I had encountred this issue last week i had to enable scrollbars in a disabled table view to prevent users from checking items checkboxes.
Solution
Since we can't enable vertical and horizontal scrollbars in disabled table view, i just prevent user from checking the checkboxes when he is not supposed to, and i also make item on gray foreground when the table is supposed to be disabled.
I'm trying to create a gui for chess game and could use some help.
I set up two panels: left panel, and right panel (both seats on a main panel). the left panel will contain the chess board itself, and the right panel will contain some more widgets.
The problem is, I just can get the right panel to be positioned at the right side of the window.
So to give you first some more background, here's how I want it to look:
and here's how it looks:
I tried to set the main panel (the one that holds both the left and the right panels) with FormLayout() object and then to set:
FormData form_data=new FormData();
form_data.left=new FormAttachment(left_panel);
right_panel.setLayoutData(form_data);
but that didn't do anything.
Here's the relevant code:
shell=new Shell(display,SWT.DIALOG_TRIM);
shell.setText("Chess");
/*********************
* setting main panel
*********************/
Composite main_panel=new Composite(shell, SWT.NONE);
main_panel.setBackgroundImage(background); //size of this image is 800x650, which means it should encompass the left and right panels exactly
main_panel.setBackgroundMode(SWT.INHERIT_DEFAULT);
main_panel.setBounds(background.getBounds());
main_panel.setLayout(new GridLayout(2,false);
/*********************
* setting left panel
*********************/
left_panel=new Composite(main_panel, SWT.NONE);
GridData data=new GridData(SWT.FILL, SWT.FILL, false, true);
data.widthHint = 650;
left_panel.setLayoutData(data);
board_panel=new Composite(left_panel,SWT.NONE);
board_panel.setBackgroundImage(game_board); //size of this image is 520x520
board_panel.setLocation(65, 65); //board size is 520x520, so this centralizes it in left panel
/*********************
* setting right panel
*********************/
right_panel=new Composite(main_panel, SWT.NONE);
right_panel.setBackgroundImage(panel); //size of this image is 150x650
right_panel.setLayoutData(new GridData(SWT.END, SWT.FILL, true, true));
shell.pack();
BTW, what style should I set the Composite to, if I don't anything special in it?
(as you can see I set it to SWT.NO_RADIO_GROUP because I didn't know what to put there...)
Any help would greatly appreciated.
**the code was edited
Never ever use setBounds unless absolutely necessary. Use a Layout instead.
Here is an excellent tutorial about layouts.
Here is some example code that should give you a starting point:
public static void main(String[] args)
{
final Display display = new Display();
Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new GridLayout(2, false));
Composite chessBoard = new Composite(shell, SWT.BORDER);
chessBoard.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite settings = new Composite(shell, SWT.BORDER);
GridData data = new GridData(SWT.END, SWT.FILL, false, true);
data.widthHint = 100;
settings.setLayoutData(data);
shell.pack();
shell.open();
shell.setSize(400, 200);
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
}
Looks like this:
SWT's RowLayout is fine for the purpose, however I'd like the vertical alignment on the font baseline for all widgets containing text.
Is there maybe a ready custom Layout that does this?
Snippet204.java probably has what it takes to implement it, but I just want to ask if it has been done before. Couldn't find it, but it seems like a typical requirement.
In the screenshot's top, there's the row layout, below is a fixed layout that I manually arranged to the baseline (WindowBuilder has snapping for that).
RowLayout has a field called center. Just set it to true and you're good.
center specifies whether the controls in a row should be centered vertically in each cell for horizontal layouts, or centered horizontally in each cell for vertical layouts. The default value is false.
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
RowLayout layout = new RowLayout();
layout.center = true;
shell.setLayout(layout);
shell.setText("StackOverflow");
new Label(shell, SWT.NONE).setText("Label");
new Button(shell, SWT.PUSH).setText("Button");
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
}