I have been tasked with making an application that the user uses to search for three pictures of theirQuery . It could be written in any language, and Python was suggested. However, my GUI skills with Python suck, I am most familiar with Java, and I have downloaded the Eclipse SWT package, which I intend on using.
OK, what have you done so far
I pimped their example code that makes a simple web browser. I have it display Google Images as the home page, and intend on using JavaScript/jQuery to automate the filling in of theirQuery, and returning the first three pictures. (I also plan on somehow using JavaScript/jQuery to return the three pictures.)
According to the documentation for Eclipse SWT, evaluate(),execute() are used to evaluate,execute JavaScript: http://help.eclipse.org/indigo/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/browser/Browser.html
Here is the code that I have used:
import org.eclipse.swt.*;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.browser.StatusTextEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
public class BrowserCodeDemo {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
shell.setLayout(gridLayout);
ToolBar toolbar = new ToolBar(shell, SWT.NONE);
ToolItem itemBack = new ToolItem(toolbar, SWT.PUSH);
itemBack.setText("Back");
ToolItem itemForward = new ToolItem(toolbar, SWT.PUSH);
itemForward.setText("Forward");
ToolItem itemStop = new ToolItem(toolbar, SWT.PUSH);
itemStop.setText("Stop");
ToolItem itemRefresh = new ToolItem(toolbar, SWT.PUSH);
itemRefresh.setText("Refresh");
ToolItem itemGo = new ToolItem(toolbar, SWT.PUSH);
itemGo.setText("Go");
GridData data = new GridData();
data.horizontalSpan = 3;
toolbar.setLayoutData(data);
Label labelAddress = new Label(shell, SWT.NONE);
labelAddress.setText("Address");
final Text location = new Text(shell, SWT.BORDER);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
data.grabExcessHorizontalSpace = true;
location.setLayoutData(data);
final Browser browser;
try {
browser = new Browser(shell, SWT.NONE);
} catch (SWTError e) {
System.out.println("Could not instantiate Browser: " + e.getMessage());
display.dispose();
return;
}
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.horizontalSpan = 3;
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
browser.setLayoutData(data);
final Label status = new Label(shell, SWT.NONE);
data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
status.setLayoutData(data);
final ProgressBar progressBar = new ProgressBar(shell, SWT.NONE);
data = new GridData();
data.horizontalAlignment = GridData.END;
progressBar.setLayoutData(data);
/* event handling */
Listener listener = new Listener() {
#Override
public void handleEvent(Event event) {
ToolItem item = (ToolItem)event.widget;
String string = item.getText();
if (string.equals("Back")) browser.back();
else if (string.equals("Forward")) browser.forward();
else if (string.equals("Stop")) browser.stop();
else if (string.equals("Refresh")) browser.refresh();
else if (string.equals("Go")) browser.setUrl(location.getText());
}
};
browser.addProgressListener(new ProgressListener() {
#Override
public void changed(ProgressEvent event) {
if (event.total == 0) return;
int ratio = event.current * 100 / event.total;
progressBar.setSelection(ratio);
}
#Override
public void completed(ProgressEvent event) {
progressBar.setSelection(0);
}
});
browser.addLocationListener(new LocationListener() {
#Override
public void changed(LocationEvent event) {
if (event.top) location.setText(event.location);
}
#Override
public void changing(LocationEvent event)
{
//System.out.println("Something is happening.");
}
});
itemBack.addListener(SWT.Selection, listener);
itemForward.addListener(SWT.Selection, listener);
itemStop.addListener(SWT.Selection, listener);
itemRefresh.addListener(SWT.Selection, listener);
itemGo.addListener(SWT.Selection, listener);
location.addListener(SWT.DefaultSelection, new Listener() {
#Override
public void handleEvent(Event e)
{
browser.setUrl(location.getText());
System.out.println("New URL loaded");
}
});
shell.open();
browser.setUrl(
"https://www.google.com/imghp?hl=en&tab=wi&ei=m8g4VLndMaz4igKlvoDADg&ved=0CAMQqi4oAQ");
//browser.setVisible(false);
boolean jQueryExecuted = browser.execute("$(\'#lst-ib\').val(\'snopes\')");
if (!jQueryExecuted)
{
System.out.println("Your jQuery didn't execute.");
}
jQueryExecuted = browser.execute("$(\'[name=btnG]\').click()");
if (!jQueryExecuted)
{
System.out.println("Your jQuery didn't execute.");
}
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
I don't think the issue is the code itself, as I have tried to set the text field automatically and it failed, both in Java and in my browser; /* the name of the text field is "lst-ib" */
What are you trying to web-scrape?
I am trying to web scrape Google images: https://www.google.com/imghp?hl=en&tab=wi&ei=m8g4VLndMaz4igKlvoDADg&ved=0CAMQqi4oAQ .
The text field is an input with name "lst-ib". The button is an input with name "btnG". The text field is within a div with id of "gs_lc0". (I see multiple other input elements in there, too, of the exact same size).
Oh, wow. It has been 10 hours and nobody has so much as commented on here but me. It turns out that the problem is much bigger than I thought: Browser from Eclipse SWT cannot execute jQuery.
Luckily, I found the Google Image API, which is written in JavaScript, and is deprecated, but still works. Also, I found some simple source code on the page: https://developers.google.com/image-search/v1/devguide#hiworld
I changed the newImg.src = "/image-search/v1/result.tbUrl;" to newImg.src = result.tbUrl; so that the images would load. This changes everything.
What is your new plan?
I now plan on using this code from Java. I plan on changing the src to the src that is the Google Image API that the JavaScript code uses, and then invoking the code to get the first three images. This is how, apparently, you run JavaScript from Java: How to run javascript in java programming . If only I can figure out how to change the src of the JavaScript engine that Java uses to this: https://www.google.com/jsapi
Related
I am looking for a widget or component (SWT), that allows me to notify the user whenever a background job has finished. I am aware of things like MyLyn, that provide ways of creating system notifications. However, I would prefer a widget that displays the notifications within my window. Is there any existing widget out there that I was unable to find?
Thanks.
[EDIT]
I have seen a component do more or less what I want. It is used in the eclipse error reporting as described here: https://eclipsesource.com/blogs/2015/06/23/error-reporting-top-eclipse-mars-feature-2/ However I can't seem to find the underlying widget being used here.
You can use ToolTip as notification which will appear in taskbar tray item. I provide below the code snippet you can try. In windows, it popups like small black popup window in the right lower corner. I have provided button just to simulate. You can implement in your own way once the background long running task is over.
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
public class ToolTipBalloon {
public static void showNotificationPopup(Shell shell) {
ToolTip tip = new ToolTip(shell, SWT.BALLOON | SWT.ICON_INFORMATION);
tip.setMessage("Your Notification Message");
Display display = shell.getDisplay();
Tray tray = display.getSystemTray();
if (tray != null) {
TrayItem item = new TrayItem(tray, SWT.NONE);
// Image image = new Image(display, "yourFile.gif");
// item.setImage(image);
tip.setText("Notification from a Windows Tray");
item.setToolTip(tip);
} else {
tip.setText("Notification from anywhere");
tip.setLocation(400, 400);
}
tip.setVisible(true);
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
// To simulate notification
Button notifyBtn = new Button(shell, SWT.PUSH);
notifyBtn.setText("Press for Notification");
notifyBtn.addListener(
SWT.Selection,
new Listener() {
public void handleEvent(Event event) {
showNotificationPopup(shell);
}
});
notifyBtn.pack();
shell.setBounds(50, 50, 200, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}
I will suggest you can explore Nebula Notifier . You may have to customize it for notification inside your application
Took below code snippet
public class NotifierSnippet {
/**
* #param args
*/
public static void main(final String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("Notifier Snippet");
shell.setSize(200, 200);
shell.setLayout(new FillLayout(SWT.VERTICAL));
final int[] counter = new int[1];
counter[0] = 0;
// Yellow theme (default)
final Button testerYellow = new Button(shell, SWT.PUSH);
testerYellow.setText("Push me [Yellow theme]!");
testerYellow.addListener(SWT.Selection, event -> {
Notifier.notify("New Mail message", "Laurent CARON (lcaron#...)<br/><br/>Test message #" + counter[0] + "...");
counter[0]++;
});
// Blue theme
final Button testerBlue = new Button(shell, SWT.PUSH);
testerBlue.setText("Push me [Blue theme]!");
testerBlue.addListener(SWT.Selection, event -> {
Notifier.notify("New Mail message", "Laurent CARON (lcaron#...)<br/><br/>Test message #" + counter[0] + "...", NotifierTheme.BLUE_THEME);
counter[0]++;
});
// Grey theme
final Button testerGrey = new Button(shell, SWT.PUSH);
testerGrey.setText("Push me [Gray theme]!");
testerGrey.addListener(SWT.Selection, event -> {
Notifier.notify("New Mail message", "Laurent CARON (lcaron#...)<br/><br/>Test message #" + counter[0] + "...", NotifierTheme.GRAY_THEME);
counter[0]++;
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Is it possible to get the list of all the applications that can open a certain file type from the OS in Java?
For eg, list of all the applications that can open a .txt or .pdf file.
You should check the example of the JFace Eclipse plugin that is here: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/Showstheextensionsonthesystemandtheirassociatedprograms.htm
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.*;
/**
* This class shows the extensions on the system and their associated programs.
*/
public class ShowPrograms {
/**
* Runs the application
*/
public void run() {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Show Programs");
createContents(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
/**
* Creates the main window's contents
*
* #param shell the main window
*/
private void createContents(Shell shell) {
shell.setLayout(new GridLayout(2, false));
// Create the label and combo for the extensions
new Label(shell, SWT.NONE).setText("Extension:");
Combo extensionsCombo = new Combo(shell, SWT.BORDER | SWT.READ_ONLY);
extensionsCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Create the label and the
new Label(shell, SWT.NONE).setText("Program:");
final Label programName = new Label(shell, SWT.NONE);
programName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Fill the combo with the extensions on the system
String[] extensions = Program.getExtensions();
for (int i = 0, n = extensions.length; i < n; i++) {
extensionsCombo.add(extensions[i]);
}
// Add a handler to get the selected extension, look up the associated
// program, and display the program's name
extensionsCombo.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
Combo combo = (Combo) event.widget;
// Get the program for the extension
Program program = Program.findProgram(combo.getText());
// Display the program's name
programName.setText(program == null ? "(None)" : program.getName());
}
});
// Create a list box to show all the programs on the system
List allPrograms = new List(shell, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL);
GridData data = new GridData(GridData.FILL_BOTH);
data.horizontalSpan = 2;
allPrograms.setLayoutData(data);
// Put all the known programs into the list box
Program[] programs = Program.getPrograms();
for (int i = 0, n = programs.length; i < n; i++) {
String name = programs[i].getName();
allPrograms.add(name);
allPrograms.setData(name, programs[i]);
}
// Add a field for a data file
new Label(shell, SWT.NONE).setText("Data File:");
final Text dataFile = new Text(shell, SWT.BORDER);
dataFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Double-clicking a program in the list launches the program
allPrograms.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent event) {
List list = (List) event.widget;
if (list.getSelectionCount() > 0) {
String programName = list.getSelection()[0];
Program program = (Program) list.getData(programName);
program.execute(dataFile.getText());
}
}
});
// Let them use launch instead of execute
Button launch = new Button(shell, SWT.PUSH);
data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
launch.setLayoutData(data);
launch.setText("Use Program.launch() instead of Program.execute()");
launch.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
// Use launch
Program.launch(dataFile.getText());
}
});
}
/**
* The application entry point
*
* #param args the command line arguments
*/
public static void main(String[] args) {
new ShowPrograms().run();
}
}
I wanted to have a Text widget that could display a message in it when the user has not entered a value into the field yet. I extended composite and essentially wrapped a text field in it. Added a focus listener to remove the message on focus, and to replace the message when the focus is lost if the field is empty. That all works as expected.
The issue I am having is I wanted the prompt to be styled differently when it is placed in the text field. The font does not seem to be being used initially. Once the field has had focus and loses focus it looks correct.
For example this is how it looks when it initially loads:
And this is how it should look on initial load and how it looks after having and lost focus:
It gets a little stranger, as when I run this inside a simple shell, it works how it should. When I run it as an Eclipse application is when it does not get styled correctly.
Here is the code for my composite:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
/**
* The <code>PromptingTextInput</code> component is a small enhancement to
* standard <code>Text</code>. It adds the ability to specify a prompt value
* that displays when the text is empty and the field does not have focus.
*/
public class PromptingTextInput extends Composite {
private String prompt;
private Text input;
private boolean textEmpty;
Font emptyFont;
Font inputFont;
public PromptingTextInput(String prompt, Composite parent, int style, boolean passwordField) {
super(parent, style);
this.prompt = prompt;
setLayout(new FillLayout());
this.textEmpty = true;
this.input = new Text(this, (passwordField ? SWT.PASSWORD : SWT.NONE));
setEmptyInputStyle();
this.input.setText(this.prompt);
this.input.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
PromptingTextInput.this.focusGained();
}
public void focusLost(FocusEvent e) {
PromptingTextInput.this.focusLost();
}
});
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
disposeFonts();
}
});
}
protected void focusGained() {
if (this.textEmpty) {
this.input.setText("");
setInputStyle();
}
}
protected void focusLost() {
if (input.getText() == null || input.getText().trim().length() == 0) {
this.input.setText(this.prompt);
setEmptyInputStyle();
this.textEmpty = true;
} else {
this.textEmpty = false;
}
}
protected void setInputStyle() {
if (this.inputFont == null){
this.inputFont = new Font(Display.getCurrent(), "Verdana", 8, SWT.DEFAULT);
}
this.input.setFont(this.inputFont);
this.input.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
}
protected void setEmptyInputStyle() {
if (this.emptyFont == null){
this.emptyFont = new Font(Display.getCurrent(), "Verdana", 6, SWT.ITALIC);
}
this.input.setFont(this.emptyFont);
this.input.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
}
public String getPrompt() {
return prompt;
}
public void setPrompt(String prompt) {
this.prompt = prompt;
if(!this.input.isFocusControl()){
this.input.setText(this.prompt);
setEmptyInputStyle();
}
}
public Text getInput() {
return input;
}
public boolean isTextEmpty() {
return textEmpty;
}
public String getText() {
return this.input.getText();
}
public void addModifyListener (ModifyListener listener) {
this.input.addModifyListener(listener);
}
public void disposeFonts(){
if (this.inputFont != null){
this.inputFont.dispose();
}
if (this.emptyFont != null){
this.emptyFont.dispose();
}
}
}
UPDATE: As Baz has shown this is not an issue in Indigo and only seems to be an issue with an E4 app in Juno.
Building upon sambi's answer, I got the following working. Maybe this works in Juno:
private static Font italic;
public static void main(String[] args) {
final Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1,false));
italic = new Font(Display.getCurrent(), "Verdana", 6, SWT.ITALIC);
final Text text = new Text(shell, SWT.BORDER);
text.addListener(SWT.Paint, new Listener() {
#Override
public void handleEvent(Event event) {
if(text.getText().length() < 1 && !text.isFocusControl())
{
GC gc = event.gc;
gc.setFont(italic);
gc.setForeground(display.getSystemColor(SWT.COLOR_GRAY));
Point size = text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
/* Strangely the y positioning doesn't work correctly */
//gc.drawText("Please enter text", 1, (size.y / 2) - (italic.getFontData()[0].getHeight() / 2));
gc.drawText("Please enter text", 1, 4);
}
}
});
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
Button button = new Button(shell, SWT.PUSH);
button.setText("Dummy");
button.forceFocus();
shell.setSize(200, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
italic.dispose();
display.dispose();
}
Without focus and empty text:
With focus or text:
You could use Text.setMessage (String message). The problem with this is you will not be able to customize much with font size and fore ground...etc.
To customize it, you can actually draw message with in the bounds of Text.
I've been banging away at this for a while now and I can't seem to get anywhere. I've tried all of the examples I can find online and nothing seems to work! I haven't been able to find much on this problem which leads me to think I'm missing something basic. . .
In my Eclipse RCP program I want to display a dialog that will show a list of errors that occurred while loading a data file. I have overridden TitleAreaDialog and simply want to display a scrollable Text containing the list of errors and an OK button.
The problem is that the Text vertical scroll bars don't become active - the Text just grows taller to fit the text. This makes the dialog window height increases until it either fits the Text box or until it reaches the height of the screen - and then it just cuts off the bottom of the Text box.
How do I prevent the Dialog/Text box from growing too large? What am I missing?
Thanks for your help!!
-Christine
...
Here is a simple program showing my Dialog:
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.*;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class ScrollableDialogRunner {
public static void main(String[] args) {
System.out.println("starting");
Display display = new Display ();
Shell shell = new Shell (display);
String errors = "one\ntwo\nthree\nfour\nfive\n";
for(int i = 0; i < 5; i++){
errors += errors;
}
ScrollableDialog dialog = new ScrollableDialog(shell, "Errors occurred during load", "The following errors occurred while loaded file 'x.data'", errors);
dialog.open();
}
}
class ScrollableDialog extends TitleAreaDialog {
private String title;
private String text;
private String scrollableText;
public ScrollableDialog(Shell parentShell, String title, String text, String scrollableText) {
super(parentShell);
this.title = title;
this.text = text;
this.scrollableText = scrollableText;
}
#Override
protected Control createDialogArea(Composite parent) {
GridLayout layout = new GridLayout();
layout.numColumns = 1;
parent.setLayout(layout);
GridData gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.horizontalAlignment = GridData.FILL;
Text scrollable = new Text(parent, SWT.BORDER | SWT.V_SCROLL);
scrollable.setLayoutData(gridData);
scrollable.setText(scrollableText);
return parent;
}
#Override
public void create() {
super.create();
setTitle(title);
setMessage(text, IMessageProvider.ERROR);
}
#Override
protected void createButtonsForButtonBar(Composite parent) {
Button okButton = createButton(parent, OK, "OK", true);
okButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
close();
}
});
}
#Override
protected boolean isResizable() {
return false;
}
}
Assign a size to the dialog; otherwise, the dialog will layout the children asking them for their "preferred" size (which is infinite for the text widget) and will resize itself accordingly.
[EDIT] This version works. See my comments for details.
class ScrollableDialog extends TitleAreaDialog {
private String title;
private String text;
private String scrollableText;
public ScrollableDialog(Shell parentShell, String title, String text, String scrollableText) {
super(parentShell);
this.title = title;
this.text = text;
this.scrollableText = scrollableText;
}
#Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea (parent); // Let the dialog create the parent composite
GridData gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessVerticalSpace = true; // Layout vertically, too!
gridData.verticalAlignment = GridData.FILL;
Text scrollable = new Text(composite, SWT.BORDER | SWT.V_SCROLL);
scrollable.setLayoutData(gridData);
scrollable.setText(scrollableText);
return composite;
}
#Override
public void create() {
super.create();
// This is not necessary; the dialog will become bigger as the text grows but at the same time,
// the user will be able to see all (or at least more) of the error message at once
//getShell ().setSize (300, 300);
setTitle(title);
setMessage(text, IMessageProvider.ERROR);
}
#Override
protected void createButtonsForButtonBar(Composite parent) {
Button okButton = createButton(parent, OK, "OK", true);
okButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
close();
}
});
}
#Override
protected boolean isResizable() {
return true; // Allow the user to change the dialog size!
}
}
A bug has been filed and fixed (super quickly) in SWT:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=305294
Just to preface this, my goal here is to print the two images into a canvas so that I can animate the canvas sliding across the screen (think iPhone), sliding the controls themselves was too CPU intensive, so this was a good alternative until I tested it on Win7. I'm open to anything that will help me solve my original problem, it doesn't have to be fixing the problem below.
Does anyone know how to get "Control.print(GC)" to work with Windows 7 Aero? I have code that works just fine in Windows XP and in Windows 7, when Aero is disabled, but the command:
control.print(GC) causes a non-top control to be effectively erased from the screen.
GC gc = new GC(image);
try {
// As soon as this code is called, calling "layout" on the controls
// causes them to disappear.
control.print(gc);
} finally {
gc.dispose();
}
I have stacked controls and would like to print the images from the current and next controls such that I can "slide" them off the screen. However, upon printing the non-top control, it is never redrawn again.
Here is some example code. (Interesting code bits are at the top and it will require pointing at SWT in order to work.)
Thanks for any and all help. As a work around, I'm thinking about swapping controls between prints to see if that helps, but I'd rather not.
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class SWTImagePrintTest {
private Composite stack;
private StackLayout layout;
private Label lblFlip;
private Label lblFlop;
private boolean flip = true;
private Button buttonFlop;
private Button buttonPrint;
/**
* Prints the control into an image
*
* #param control
*/
protected void print(Control control) {
Image image = new Image(control.getDisplay(), control.getBounds());
GC gc = new GC(image);
try {
// As soon as this code is called, calling "layout" on the controls
// causes them to disappear.
control.print(gc);
} finally {
gc.dispose();
}
}
/**
* Swaps the controls in the stack
*/
private void flipFlop() {
if (flip) {
flip = false;
layout.topControl = lblFlop;
buttonFlop.setText("flop");
stack.layout();
} else {
flip = true;
layout.topControl = lblFlip;
buttonFlop.setText("flip");
stack.layout();
}
}
private void createContents(Shell shell) {
shell.setLayout(new GridLayout(2, true));
stack = new Composite(shell, SWT.NONE);
GridData gdStack = new GridData(GridData.FILL_BOTH);
gdStack.horizontalSpan = 2;
stack.setLayoutData(gdStack);
layout = new StackLayout();
stack.setLayout(layout);
lblFlip = new Label(stack, SWT.BOLD);
lblFlip.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_CYAN));
lblFlip.setText("FlIp");
lblFlop = new Label(stack, SWT.NONE);
lblFlop.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_BLUE));
lblFlop.setText("fLoP");
layout.topControl = lblFlip;
stack.layout();
buttonFlop = new Button(shell, SWT.FLAT);
buttonFlop.setText("Flip");
GridData gdFlip = new GridData();
gdFlip.horizontalAlignment = SWT.RIGHT;
buttonFlop.setLayoutData(gdFlip);
buttonFlop.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
flipFlop();
}
});
buttonPrint = new Button(shell, SWT.FLAT);
buttonPrint.setText("Print");
GridData gdPrint = new GridData();
gdPrint.horizontalAlignment = SWT.LEFT;
buttonPrint.setLayoutData(gdPrint);
buttonPrint.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
print(lblFlip);
print(lblFlop);
}
});
}
/**
* #param args
*/
public static void main(String[] args) {
Shell shell = new Shell();
shell.setText("Slider Test");
shell.setSize(new Point(800, 600));
shell.setLayout(new GridLayout());
SWTImagePrintTest tt = new SWTImagePrintTest();
tt.createContents(shell);
shell.open();
Display display = Display.getDefault();
while (shell.isDisposed() == false) {
if (display.readAndDispatch() == false) {
display.sleep();
}
}
display.dispose();
}
}
This was the result of a bug:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=305294
It's since been fixed. Hopefully a new packaged version of SWT will come out soon so we can officially use it.