I am trying to create an application that contains a StyledText box displayed within a ScrolledComposite. I am having difficulties displaying a large number of lines in my StyledText box (over 2,550 seems to cause issues).
The StyledText box must not itself have a scroll bar but must be scrollable via the ScrolledComposite. As there are other items below and above the StyledText that need to be scrollable to and I do not want multiple scroll bars.
Hence with large amounts of data I have a very large (as in height) StyledText box that seems to stop after a certain height.
The issue is that the StyledText should be as tall is its contents and it is not. The reason for the gap underneath is that the containing composite is resizing what StyledText reports to be its height but this is not in fact its height.
Here is a piece of simplified example code to illustrate my issue:
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class ExpandBox2
{
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Example");
shell.setLayout(new FillLayout());
ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL);
scrolledComposite.setLayout(new FillLayout(SWT.VERTICAL));
Composite mainComp = new Composite(scrolledComposite, SWT.NONE);
mainComp.setLayout(new FillLayout(SWT.VERTICAL));
StyledText styledText = new StyledText(mainComp, SWT.NONE);
styledText.getContent().setText(bigString());
mainComp.setSize(mainComp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
scrolledComposite.setContent(mainComp);
scrolledComposite.setMinSize(mainComp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setExpandVertical(true);
scrolledComposite.getVerticalBar().setIncrement(10);
shell.setSize(400, 350);
shell.open();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) {
display.sleep ();
}
}
display.dispose();
}
private static String bigString()
{
String big = "";
for(int i=0;i<10000;i++)
{
big = big + "hello\r\n";
}
return big;
}
}
Update: Interestingly this problem occurs with SWT Label and SWT Text
This is actually a Windows limitation. Composites may only be of a certain size in windows, no more than 32767 (pixels, I assume).
This is find for the scrolledComposite because it isn't actually > 32767, it just appears to be. Whereas with the mainComp the actual size is > 32767 and this is where we got cut off.
Initially I thought this was an Eclipse bug and filed a report where I was informed that this was a Windows issue/feature: https://bugs.eclipse.org/bugs/show_bug.cgi?id=333111
Perhaps you could solve this problem by going the other way around and place your "other things" inside the StyledText? And then consequently make the StyledText scroll instead of the ScrolledComposite. StyledText has support for embedding both images and controls, and you are able to implement listeners (for instance VerifyListener) to keep the user from deleting the embedded object - if that is what you want.
Here's some sample code:
http://www.java2s.com/Tutorial/Java/0280__SWT/StyledTextembedimages.htm
http://www.java2s.com/Tutorial/Java/0280__SWT/StyledTextembedcontrols.htm
If you want your controls to look better than in the second example, you can make your controls take up the whole width of the text area (and listen to events for when the area is resized - use styledText.addListener(SWT.Resize, new Listener() ...).
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 have a StyledText widget (SWT) inside a ScrolledComposite that should display the content of a log file. Unfortunately the log file has thousands of lines in it so that I came to the point where the widget cuts off the text after ~ 2200 lines.
I found this post that refers to this report that states that there is a height limitation for widgets in windows and my theory is that I have reached that limit.
My question is how I can deal with this. What is the workaround for displaying text with that many lines in it?
EDIT:
I found out that this does only happen, if I use the StyledText inside a ScrolledComposite. If I use the plain StyledText there is no problem.
Here's the code to reproduce:
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class StyledTextLimit {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
ScrolledComposite scrollComp = new ScrolledComposite(shell,
SWT.H_SCROLL | SWT.V_SCROLL);
StyledText text = new StyledText(scrollComp, SWT.NONE);
text.setSize(100, 500);
scrollComp.setContent(text);
scrollComp.setExpandHorizontal(true);
scrollComp.setExpandVertical(true);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 5000; i++) {
builder.append(i);
builder.append(" ");
for (int j = 'a'; j < 'a' + 200; j++) {
builder.append((char) j);
}
builder.append("\n");
}
text.setText(builder.toString().trim());
scrollComp.setMinSize(text.computeSize(SWT.DEFAULT, SWT.DEFAULT));
// shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
I don't see a need to wrap the StyledText into a ScrolledComposite. The StyledText shows scrollbars on its own when necessary.
I suggest using the StyledText without a ScrolledComposite.
The StyledText certainly also has a limit on what text it is capable to hold. This limit, however, should be much higher than 2200 lines. If StyledText still overflows, then you'll have to truncate the log to be shown.
Although #RĂ¼diger Herrmann helped me fixing my problem I still feel that I should help those who might come to the same problem as I did without the possibility of getting rid of the ScrolledComposite.
Therefore I want to link this post that deals with the ScrolledComposite problem.
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.
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();
}
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.