2

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();
    }
}
vmck
  • 21
  • 3
  • 2
    I don't see any functional difference between them. BTW, what are `img1`, `img2`,.. – Rohit Jain Mar 24 '14 at 18:53
  • There is no functional difference, but it changes the display in a way that is less attractive (if I create the objects outside of the constructor). Sorry, img1, img2, and img3 are images that represent the buttons in the GUI (they are created in the JFrame class as well). – vmck Mar 24 '14 at 18:53
  • 1
    Post compilable code, and explain how it's less attrractive. We can't see your screen. – JB Nizet Mar 24 '14 at 18:55

1 Answers1

3

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...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Why does this change the appearance of the GUI though, with respect to the buttons on the toolbar? – vmck Mar 24 '14 at 18:55
  • @vmck: As I say in my edited answer, given that you don't do anything with the `bar` variable, I'm surprised that a toolbar is created at all. It would really help if you'd post complete code so that we can reproduce the issue. – Jon Skeet Mar 24 '14 at 18:56
  • I have posted the complete correct code (the difference is small, it's what I stated in the original question). However, I think you'd need three images saved to be able to run it the way I did... or do you want me to change that so that the buttons are represented by text in the GUI and not images? – vmck Mar 24 '14 at 19:00
  • @vmck Could you post screenshots of a comparison of the GUI differences you are seeing? – jrowe08 Mar 24 '14 at 19:01
  • I just tried... apparently I don't have enough reputation. If the object is created outside of the constructor, there is a thin white border around it, compared to the other buttons that ARE created within the constructor. – vmck Mar 24 '14 at 19:07
  • @JonSkeet I have edited my question to include new text with buttons with text. – vmck Mar 24 '14 at 19:13
  • @JonSkeet Does it have something to do with the size and look and feel? – vmck Mar 24 '14 at 19:14
  • @JonSkeet Sorry, I don't understand. You want me to create a new Tool object in the main and then use that object instance to call the setLookAndFeel() method? – vmck Mar 24 '14 at 19:21
  • @vmck: No, I said to make the `setLookAndFeel` method `static` (it doesn't use `this` at all) and then call it from `main`. Once it's `static`, you don't need to create an instance of the class in order to call the method. (I wouldn't just swallow the exception, mind you...) – Jon Skeet Mar 24 '14 at 19:22
  • @JonSkeet Wow thank you so so much. But if I may ask, why exactly DID that work? – vmck Mar 24 '14 at 19:24
  • @vmck: Because when you create a UI component, presumably it looks at the current look and feel to find out various aspects of how it should look. Changing look and feel when you've already created some of the UI therefore ends up with some components using one L&F, and others using a different one... – Jon Skeet Mar 24 '14 at 19:25
  • @JonSkeet so what does static mean? (Sorry I'm really new at this) – vmck Mar 24 '14 at 19:27
  • @vmck: At this point you should look in a good Java book. This is a fundamental part of understanding Java, and can't be adequately dealt with in comments on a question which is about something entirely different... – Jon Skeet Mar 24 '14 at 19:28
  • @JonSkeet okay. I'm currently trying to teach myself this language. Are there any good Java books that you recommend? – vmck Mar 24 '14 at 19:31
  • @vmck: It's been a long time since I've looked at any beginner books, so I wouldn't know what to recommend, but this is now *way* off topic for your question. You might want to ask in the Java chat room. You should also read the Java Tutorial: http://docs.oracle.com/javase/tutorial/ – Jon Skeet Mar 24 '14 at 19:32