It's my first question here but I'm really stuck. Maybe it's just my extreme fatigue for last few days, but I looked up google for few hours now and couldn't find any close to good answer.
I know SWT is event driven like all GUI's I can think of and when creating widgets I should keep in mind that they need to be able to reach the ones they are supposed to modify/interact with. But what I need to know is if my thinking is right and if not what should I improve.
Let's say I start with eclipse+windowbuilder+swt/jface java project. Then I add button and clabel +click listener for button(SelectionListener), so the generated code looks more or less like(only main method, above there is only Main class and imports)
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setSize(450, 300);
shell.setText("SWT Application");
Button btnNewButton = new Button(shell, SWT.NONE);
btnNewButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
}
});
btnNewButton.setBounds(51, 31, 75, 25);
btnNewButton.setText("New Button");
CLabel lblOneTwo = new CLabel(shell, SWT.NONE);
lblOneTwo.setBounds(180, 119, 61, 21);
lblOneTwo.setText("one two");
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
As I know and it's probably obvious to most of you I can't just go and add to
btnNewButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
}
});
code like lblOneTwo.setText("three") and from what I know and use sometimes I just declare all stuff beforehand, as static widget widgetName and then I can access them from basically everywhere, so code like
static Button btnNewButton;
static CLabel lblOneTwo;
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setSize(450, 300);
shell.setText("SWT Application");
btnNewButton = new Button(shell, SWT.NONE);
btnNewButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
lblOneTwo.setText("three");
}
});
(...)
works just fine. But I guess and think it's not the best practice and way of doing it, isn't it? So please, help me, point me in the right direction so I can stop coding in a sin. Thanks in advance! indirect answers with links to articles/tutorials would be great, but I like examples people are putting here because of their clear way of showing things.
There are multiple ways to do this.
Make the widgets field of your class. Don't make them static unless necessary.
private Label l;
private Button b;
public static void main(String[] args)
{
...
b.addListener(...);
Define all your widgets first (have to be final if you want to use them in the Listener), after that add your Listeners.
final Label l = ...;
final Button b = ....;
b.addListener(...);
If you want to change the widget itself in the Listener you can use Event#widget to get the source of the event.
b.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
Button button = (Button) e.widget;
}
});
Related
I would like to create a dialog window that shows a user's profile (such as name, avatar, sex, etc.) in a visually pleasing way by using labels that contain the relevant information. At the same time, I would like to show an edit button that transforms the labels into textboxes or buttons allowing the name or avatar to be changed.
How can I realize this with SWT? What would be the best strategy to approach this?
You can use a Text and then set setEditable(boolean) to enable/disable editing of the text box from the SWT.Selection Listener of the Button:
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new GridLayout(1, false));
// Create a read-only text field
final Text text = new Text(shell, SWT.BORDER);
text.setEditable(false);
text.setText("Some text here");
Button button = new Button(shell, SWT.PUSH);
button.setText("Change");
button.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
text.setEditable(!text.getEditable());
}
});
shell.open();
shell.pack();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
}
Alternatively, you can use a StackLayout and have two versions of the same UI (or just parts of it) and switch between them when the button is pressed.
About a year ago, I wrote a small Checkers game as part of some study assignment. The code files was laying around on a flash drive ever since, and recently I decided to revive it and make it better, just to fill up my spare time.
I wrote it using SWT, and I remember that back then it worked perfectly.
Oddly enough, after setting all the environment again (This is a new computer, so I had to install Eclipse, import SWT jar files, etc...), and running it, I was surprised to find out that the some Group objects - that were holding buttons - were not properly displayed.
Let me first post the code, and I'll explain exactly what I'm talking about (it's quite long, so I omitted irrelevant parts)...
public class MainMenu {
public static void main(String[] args) {
MainMenu menu=new MainMenu();
menu.run();
}
/*private class StartGameListener extends MouseAdapter {
// omitted because it is not relevant, unless it is, and then I wouldn't mind posting it too...
}*/
final static String images_path="./images";
final private Display display;
final private Shell shell;
private Button start_game;
private Button quit_game;
private Button[] mode_options;
private Button[] board_options;
private Text player_one_name;
private Text player_two_name;
private BoardPanel board;
private CustomBoard custom_board_menu;
private IController game_controller;
//constructor
public MainMenu() {
/******************
* main shell setup
******************/
display=new Display();
shell=new Shell(display, SWT.DIALOG_TRIM);
shell.setText("Checkers Game");
Image menu_background=new Image(display, images_path+"/backgrounds/menu.jpg");
shell.setBackgroundImage(menu_background);
shell.setBounds(menu_background.getBounds());
shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
/******************************************
* Start Game and Quit game button
******************************************/
start_game=new Button(shell, SWT.PUSH);
start_game.setText("Start Game");
start_game.setLocation(650, 135);
start_game.pack();
start_game.addMouseListener(new StartGameListener());
quit_game=new Button(shell, SWT.PUSH);
quit_game.setText("Quit Game");
quit_game.setLocation(650, 170);
quit_game.addMouseListener(new MouseAdapter() {
#Override
public void mouseUp(MouseEvent e) {
shell.dispose();
display.dispose();
}
});
quit_game.pack();
/******************
* game modes Group
******************/
Group game_modes=new Group(shell,SWT.SHADOW_ETCHED_OUT);
game_modes.setText("Game Mode");
game_modes.setLocation(65, 120);
game_modes.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options=new Button[5];
mode_options[0]=new Button(game_modes, SWT.RADIO);
mode_options[1]=new Button(game_modes, SWT.RADIO);
mode_options[2]=new Button(game_modes, SWT.RADIO);
mode_options[3]=new Button(game_modes, SWT.CHECK);
mode_options[4]=new Button(game_modes, SWT.CHECK);
mode_options[0].setText("Versus Mode");
mode_options[0].setLocation(5, 20);
mode_options[0].setSelection(true);
mode_options[0].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options[0].pack();
mode_options[1].setText("PC Mode");
mode_options[1].setLocation(5, 45);
mode_options[1].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options[1].pack();
mode_options[2].setText("Demo Game");
mode_options[2].setLocation(5, 70);
mode_options[2].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options[2].pack();
mode_options[3].setText("Creatures");
mode_options[3].setLocation(130, 70);
mode_options[3].setEnabled(false);
mode_options[3].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options[3].pack();
mode_options[4].setText("Custom Game");
mode_options[4].setLocation(130, 20);
mode_options[4].setSelection(false);
mode_options[4].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
mode_options[4].pack();
/*********************************************
* the following anonymous class will listen to any
* change in the game modes selection and will
* react accordingly
*********************************************/
MouseAdapter modes_listener=new MouseAdapter() {
#Override
public void mouseUp(MouseEvent e) {
String selection=((Button)e.getSource()).getText();
switch (selection) {
case "Versus Mode":
player_one_name.setEnabled(true);
player_two_name.setEnabled(true);
mode_options[3].setEnabled(false);
mode_options[4].setEnabled(true);
break;
case "PC Mode":
player_one_name.setEnabled(true);
player_two_name.setEnabled(false);
mode_options[3].setEnabled(false);
mode_options[4].setEnabled(false);
break;
case "Demo Game":
player_one_name.setEnabled(false);
player_two_name.setEnabled(false);
mode_options[3].setEnabled(true);
mode_options[4].setEnabled(false);
break;
}
}
};
for (int i=0; i<3; i++) {
mode_options[i].addMouseListener(modes_listener);
}
/******************
* board size Group
******************/
Group board_size=new Group(shell, SWT.SHADOW_ETCHED_OUT);
board_size.setText("Board Size");
board_size.setLocation(65, 230);
board_size.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
board_options=new Button[2];
board_options[0]=new Button(board_size, SWT.RADIO);
board_options[1]=new Button(board_size, SWT.RADIO);
board_options[0].setText("Normal");
board_options[0].setLocation(5, 20);
board_options[0].setSelection(true);
board_options[0].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
board_options[0].pack();
board_options[1].setText("Large");
board_options[1].setLocation(5, 45);
board_options[1].setForeground(display.getSystemColor(SWT.COLOR_WHITE));
board_options[1].pack();
/********************
* players names Group
********************/
Group players_names=new Group(shell, SWT.NONE);
players_names.setLayout(new GridLayout(2,true));
players_names.setLocation(335, 130);
players_names.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
Label player_one=new Label(players_names, SWT.LEFT);
player_one.setText("Player 1 Name: ");
player_one.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
player_one_name=new Text(players_names, SWT.BORDER);
player_one_name.setText("Player 1");
player_one_name.setLayoutData(new GridData(128, SWT.DEFAULT));
Label player_two=new Label(players_names, SWT.LEFT);
player_two.setText("Player 2 Name: ");
player_two.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
player_two_name=new Text(players_names, SWT.BORDER);
player_two_name.setText("Player 2");
player_two_name.setLayoutData(new GridData(128, SWT.DEFAULT));
game_modes.pack();
board_size.pack();
players_names.pack();
}//end of MainMenu constructor
//render the main menu
public void run() {
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
}
The above code produces this:
As you can see, the Group widgets (and also both the Start Game and Quit Game buttons) have no transparent background (which is what I'd expect, had they inherit their background from their parent - the shell).
Again, this is strange, because I remember that a year ago this wasn't a problem, but nevertheless, I tried to change:
shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
To:
shell.setBackgroundMode(SWT.INHERIT_FORCE);
But this didn't help much:
The ones with the keen eye must have noticed that now the Start Game and Quit Game buttons are more neatly displayed, but still - the three Group objects would not agree to inherit their background from their parent (although the widgets inside them [radio buttons, text labels, etc...] do).
Does anyone know what can be the problem? Am I missing something here?
I have little problem with StyledText. When I use setText() Method and text is long, I must wait few seconds for render that text. Is there any method what can I use to speed up showing this text?
The only optimisation you can implement is putting your setText() in a Job or in a Runnable to not block the UI.
Other than that, it's an API limitation from SWT.
Other suggestions:
File a bug/feature request
Search for a StyledText, although apparently none exist
Rethink your program. Don't you have a backup plan? Is the performance critical?
Edit:
#greg-449
/**
*
* #author ggrec
*
*/
public class Test
{
public static void main(final String[] args)
{
new Test();
}
private Test()
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
final Button button = new Button(shell, SWT.PUSH);
button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
button.setText("Press me");
final StyledText text = new StyledText(shell, SWT.NONE);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
button.addSelectionListener(new SelectionAdapter()
{
#Override public void widgetSelected(final SelectionEvent e)
{
Display.getDefault().asyncExec(new Runnable()
{
#Override public void run()
{
text.setText("*put very long text here*");
}
});
}
});
shell.setSize(1000, 1000);
shell.open();
while (!shell.isDisposed())
{
if ( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
}
I want to use a text field which will expand when the user enters some data and when the user is done editing and move out of text field than it should collapse. After that when ever user focus on the text field it should expand like a tooltip. Any pointer regarding this will help me.
This code should give you an idea of how to do it:
public static void main(String[] args)
{
Display display = Display.getDefault();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
final Text text = new Text(shell, SWT.BORDER | SWT.MULTI);
text.setText("edasdasdas\n\nasdasda\n\nasdasd");
final GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
data.heightHint = 100;
text.setLayoutData(data);
text.addListener(SWT.FocusIn, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
data.heightHint = 100;
shell.layout(true);
}
});
text.addListener(SWT.FocusOut, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
data.heightHint = 50;
shell.layout(true);
}
});
Button button = new Button(shell, SWT.PUSH);
button.setText("Button");
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It basically changes the heightHint of the GridData when focus is lost/gained. Afterwards you need to re-layout the parent.
You will have to make some adjustments for the "focused height" and "unfocused height" values yourself.
Here are some screenshots:
With focus:
Without focus:
Just press the Button to lose focus.
Just add a FocusListener to your text field:
text.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
text.setSize(); // put in the size you want
}
#Override
public void focusLost(FocusEvent e) {
text.setSize(); // put in the size you want
}
});
Note that for setSize to work properly, parent of text can't have a layout.
i am using eclipse rcp and swt for developing application.i have a list and i need to set its visibility false on a movement of title bar or when user click a titleBar. i am unable to find any event of titleBar. Is there any event of titleBar so that i can solve my problem? Or any thing that could probably solve my problem? i searched but could find for flex only as
function panelClick ( event:MouseEvent ) : void
{
trace( event.localX + '/' + event.localY );
}
is there same thing for swt using eclispe.
thanks in advance.
The following code will output "Move" and "Minimize" when the corresponding events happen:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Button dummy = new Button(shell, SWT.PUSH);
dummy.setText("Dummy");
shell.addListener(SWT.Move, new Listener() {
#Override
public void handleEvent(Event arg0) {
System.out.println("Move");
}
});
shell.addListener(SWT.Iconify, new Listener() {
#Override
public void handleEvent(Event arg0) {
System.out.println("Minimize");
}
});
shell.pack();
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
However, the SWT.MOVE event is only fired after the shell has been moved, i.e. when the "move" is over.