SWT Access gui components - java

I need to access gui components outside the class that defines them.
My gui class contain the following code for placing object on it:
/**
* Create contents of the window.
*/
protected void createContents() {
shlCertificatesmanager = new Shell(Display.getDefault());
shlCertificatesmanager.setSize(450, 300);
shlCertificatesmanager.setText("CertificatesManager");
shlCertificatesmanager.setLayout(new RowLayout(SWT.HORIZONTAL));
MenuItemListener menuListener = new MenuItemListener(shlCertificatesmanager);
Menu menu = new Menu(shlCertificatesmanager, SWT.BAR);
shlCertificatesmanager.setMenuBar(menu);
MenuItem mntmNewSubmenu = new MenuItem(menu, SWT.CASCADE);
mntmNewSubmenu.setText("File");
Menu menu_1 = new Menu(mntmNewSubmenu);
mntmNewSubmenu.setMenu(menu_1);
MenuItem mntmOpenCertificate = new MenuItem(menu_1, SWT.NONE);
mntmOpenCertificate.setText("Open Certificate");
mntmOpenCertificate.addSelectionListener(menuListener);
MenuItem mntmExit = new MenuItem(menu_1, SWT.NONE);
mntmExit.addSelectionListener(menuListener);
mntmExit.setText("Exit");
MenuItem mntmHelp = new MenuItem(menu, SWT.CASCADE);
mntmHelp.setText("Help");
Menu menu_2 = new Menu(mntmHelp);
mntmHelp.setMenu(menu_2);
MenuItem mntmAbout = new MenuItem(menu_2, SWT.NONE);
mntmAbout.setText("About");
mntmAbout.addSelectionListener(menuListener);
Label lblAliasName = new Label(shlCertificatesmanager, SWT.NONE);
lblAliasName.setText("Alias name: ");
Label label = new Label(shlCertificatesmanager, SWT.NONE);
label.setText("___________");
}
Now my need is to access some of these component from an external class, in that case i need to access the two labels (lblAliasName, label) from MenuItemListener class.
There is a way to access them? (maybe like Android with a findViewById method or similar?)
Or i need for example made them accessible from the other class in some way? (Creating a calss of gui components that will be used by both MenuItemListener class and GuiWindow class)

Two options come to my mind:
If there is only one instance of your class, declare the components as static fields and hand them over via getter methods.
If there is more than one instance, declare the components as fields (this time not static) and create getter methods. The other class would of course have to know the instance of your class to access the methods then.
Keep in mind:
If you try to change components from a thread that is not the gui-thread, you will get an SWTException with value ERROR_THREAD_INVALID_ACCESS.
You can solve this by using:
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// change/modify components here
}
});

No, there is no standard way to do this and you need to make them accessible as usual in Java.

Related

How to access variable from action listener/class constructor to use in main method in java

I have a frame with a combo box that displays different shapes and a button, for the button I added an action listener which will get the selected item from the combo box and store it as a string which i declared as a public class variable, in my main method i want to access this string to make a finch robot draw that shape but I can't seem to access it no matter what I try
public class DrawShape
{
private JFrame frame;
private String[] choices = {"circle", "square", "triangle", "rectangle", "quit"};
public String choice = "";
//class constructor
public DrawShape()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
JPanel p = new JPanel();
final JComboBox cb = new JComboBox(choices);
JButton button = new JButton("Done");
p.add(cb);
p.add(button);
frame.add(p);
//create an action listener that, when button is clicked, gets the selected choice and stores it to
//the string variable 'choice'
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
choice = (String)cb.getSelectedItem();
}
}) ;
frame.pack();
}
public static void main(String[] args)
{
new DrawShape();
System.out.println(choice);
}
}
I wouldn't recommend the use of non-private variables. However, you need to keep a reference to the object you created and then access the fields through that reference as if you were calling methods on an object.
DrawShape draw = new DrawShape();
System.out.println(draw.choice);
However, you should see null as this is called immediately after you construct the object rather than from the listener.
You probably want the code executed from the listener. So either put the print code in the listener, or have the listener call another method with that in.
GUI programming tends to be event driven. Don't expect to be able to sequence the user interaction - the user drives.
you should use getters/setters in this case. Your action listener would call the getter method which would in turn get what is in the combobox.
Here is an example of how that works: https://www.codejava.net/coding/java-getter-and-setter-tutorial-from-basics-to-best-practices
Hope this helps.

Difference between creating an object within the constructor vs outside of the constructor?

Within my program, I am trying to create a toolbar within a frame. Within the toolbar, I have three buttons that are represented with a picture instead of text.
The problem is that I have found that there is a difference in how the buttons are displayed if I create the JButton objects within the constructor, compared to if I did this outside of the constructor (but still within the JFrame class).
My code when I create the buttons within the constructor :
public class Tool extends JFrame
{
public Tool()
{
JToolbar bar = new JToolBar();
JButton button1 = new JButton(img1);
JButton button2 = new JButton(img2);
JButton button3 = new JButton(img3);
bar.add(button1);
bar.add(button2);
bar.add(button3);
}
}
Then the buttons are added nicely and neatly to the toolbar.
However, if I do this:
public class Tool extends JFrame
{
JButton button1 = new JButton(img1);
JButton button2 = new JButton(img2);
JButton button3 = new JButton(img3);
public Tool()
{
JToolbar bar = new JToolBar();
bar.add(button1);
bar.add(button2);
bar.add(button3);
}
}
Then, the buttons are still added to the toolbar. BUT instead of being formatted nicely, they seem to have a border around them (similar to if you just copied an image off of google and paste it onto a powerpoint presentation, for example, and you get a square border around the image).
Why is this the case? Why does it matter where I create the JButton objects?
Thank you in advance.
Edit (complete CORRECT code):
In the code below, button1 and button2 are created within the constructor, whereas button3 is created outside of the constructor. As you can see, there is a faint white border around the button with the text "Java", compared to the two other buttons.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Tool extends JFrame
{
JButton button3 = new JButton("Java");
public Tool()
{
super("Tool");
setLookAndFeel();
setSize(370, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button1 = new JButton("Help");
JButton button2 = new JButton("SOS");
//build toolbar
JToolBar bar = new JToolBar();
bar.add(button1);
bar.add(button2);
bar.add(button3);
// build text area
JTextArea edit = new JTextArea(8, 40);
JScrollPane scroll = new JScrollPane(edit);
// create frame
BorderLayout border = new BorderLayout();
setLayout(border);
add("North", bar);
add("Center", scroll);
setVisible(true);
}
private void setLookAndFeel()
{
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
}
catch(Exception e)
{
}
}
public static void main(String[] arguments)
{
Tool loot = new Tool();
}
}
In the first case, you just have three local variables declared in the constructor.
In the second case, your Tool class has three fields. You can then refer to those fields in other methods, and they are part of the state of the object.
That's a significant difference in itself, but shouldn't affect the behaviour in itself. However, it also affects the timing of when the JButton instances are created - when they're fields, the initializer is being executed before you call setLookAndFeel and before you call setSize.
After experimenting a bit, it seems that it's the look and feel which is important here. I suggest you change your code to make setLookAndFeel a static method, and then call that from main before you create any GUI components. You'll then get a consistent experience. (I would suggest only catching UnsupportedLookAndFeelException and ReflectiveOperationException, and at least logging any exception, instead of just continuing without any trace of what's wrong, too...)

Adding and Removing Panels GWT Dynamically

I'm trying to add/remove panels in GWT. First I declare panels and some Labels (which act as buttons).
DockPanel dockPanel = new DockPanel();
RootLayoutPanel rootLayout = RootLayoutPanel.get();
Label one = new Label("First Button");
Label two = new Label("Second Button");
Then I have this which initialises various panels
public void initPanels() {
dockPanel.add(one, DockPanel.EAST);
rootLayout.add(dockPanel);
I add some click handlers which then sends requests to this class, which would then remove a panel and replace it with another, only I can't work out how to do it:
public void getActivePanel(String activePanelName){
if (activePanelName==null){
dockPanel.add(one, DockPanel.EAST);
}
else if (activePanelName == "two"){
//can't figure this bit out
//dockPanel.remove(AnotherLabel);
//dockPanel.remove((IsWidget) DockPanel.EAST);
//dockPanel.add(two, DockPanel.EAST);
}
}
You can do:
dockPanel.remove(one);
dockPanel.add(two, DockPanel.EAST);

How to create a custom JMenuBar?

I want to create a custom menu bar class that i can add close and minimize buttons to. I want to extend the JMenuBar class but I don't know which methods to override or how to override them. I tried checking the java docs but that only tells you what a method does, not how it works. Can someone please help?
Yes, you can extend JMenuBar to create your own one. In order to have some custom menu buttons, you should ensure
Create a constructor with an ActionListener parameter
public MyMenuBarClass(ActionListener p_objAl) {
super();
this.objal = p_objAl;
initComponents();
}
When you initial the menu buttons, you should add the ActionListener object into the added JMenuItem such as
JMenu menu1 = new JMenu("menu 1");
this.add(menu1);
JMenuItem menuitem1_1 = new JMenuItem("menu item 1.1");
menuitem1_1.setMnemonic(KeyEvent.VK_F10);
menuitem1_1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0));
menuitem1_1.setActionCommand("command1_1");
menuitem1_1.addActionListener(this.objal);
menu1.add(menuitem1_1);
Implement the ActionListener object to handle the command such as command1_1 in the above example.
This is how i modified the JMenuBar class to except all JComponents instead of just menu's.
public class CustomMenuBar extends JMenuBar{
public JComponent addComponent(JComponent c) {
super.add(c);
return c;
}
}

singleton create new window

It's good practice to use singleton to create new window?
I have main window and i want create another one. This window will be used only to change properties in main window.
My code:
Main Window
public class MainWindow {
private StackPane root = new StackPane();
private Stage primaryStage = new Stage();
public void run(){
primaryStage.setTitle("v0.2-alpha");
Scene scene = new Scene(root, 600, 400);
scene.getStylesheets().addAll("css/style.css");
MainMenu mmb = new MainMenu();
VBox vBox = new VBox();
vBox.getChildren().add(mmb.createMenuBar());
ISplitPane lsp = new SplitPaneLeftImpl();
ISplitPane csp = new SplitPaneCenterImpl();
ISplitPane rsp = new SplitPaneRightImpl();
HBox hboxpane = new HBox();
hboxpane.getChildren().addAll(spl.createSplitPane(), spc.createSplitPane(), spr.createSplitPane());
root.getChildren().addAll(vBox,hboxpane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Create new window class
public interface IStage {
public void createStage();
}
class StageOptionsImpl implements IStage{
private OptionsStage(){}
private Stage stageOptions = new Stage();
private static StageOptionsImpl os = null;
public static StageOptionsImpl getInstance(){
if(os == null){
synchronized(StageOptionsImpl.class){
if(os == null){
os = new StageOptionsImpl();
}
}
}
return os;
}
#Override
public void createStage(){
GridPane gp = new GridPane();
TabPane tabPane = new TabPane();
tabPane.setSide(Side.LEFT);
Tab tabSecurity = new Tab("Security");
tabSecurity.setContent(new SecurityTab().tabCreate());
Tab tab2 = new Tab("System Data");
tab2.setContent(new DataTab().tabCreate());
Tab tab3 = new Tab("tab 3");
tab3.setContent(new SecurityTab().tabCreate());
tabPane.getTabs().addAll(tabSecurity, tab2, tab3);
Scene sceneOptions = new Scene(tabPane, 400, 300, Color.AQUA);
stageOptions.setScene(sceneOptions);
stageOptions.show();
}
}
If it's only used from there, why would you want a singleton. Whole point of a Singleton is so you can use the same intance of it from anywhere.
It's good practice to use singleton to create new window?
Well, that comes down to a design question.
If you only ever want to have a single, shared instance of a Component in you're application, then I would say a singlton is not a bad approach. It will force this choice.
If, however, you want to display multiple instances of the same Component but want, say, a simpler way to construct it, or want to expose a non-concrete interface through the API, then a Factory pattern would be of a better choice.
The best approach to manage these windows is usually by creating a class that manages all of the windows/panels in the program.
If you wanted to open the panel called 'ClientForm' it should have a method like this:
public void OpenClientForm(){
// Set the other forms to their default form(when != null) and set their visibility as false (when != null).
RestorePanels();
// In case it hasn't been created yet
if (ClientForm == null){
// calls a factory that creates the form.
}
else{
// Set the form as visible
}
}
When 'disposing' of panels/forms inside of the program you should have a method that clears the panels, forcing them back to their original state and setting their visible as false.
Swing is pretty buggy, disposing of the forms and recreating them could mess up a lot of things in your interface. So, back to your question... implemeting a singleton or a factory to manage ur forms should be the best approach.
Hope this helps.

Categories