-2

I'm attempting to add a button to my JPanel and set the location. I have

buttonOptions.setLocation(1150, 700);

but it adds it to the middle of my JPanel, around 600, 20. I tried adding

buttonOptions.setLocation(1150, 700);

after the adding of the button to the panel but that didn't fix it either. I also set the action to set the location and that works.

public class StartScreen extends JPanel implements ActionListener{
    ImageIcon imageButtonOptions = new ImageIcon(imageButtonOptionsPath);
    ImageIcon imageButtonOptionsHovered = new ImageIcon(imageButtonOptionsHoveredPath);

    JButton buttonOptions = new JButton(imageButtonOptions);

    public StartScreen() {  
        buttonOptions.setBorderPainted(false);  
        buttonOptions.setFocusPainted(false);  
        buttonOptions.setContentAreaFilled(false);
        buttonOptions.addActionListener(this);
        buttonOptions.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                buttonOptions.setIcon(imageButtonOptionsHovered);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                buttonOptions.setIcon(imageButtonOptions);
            }
        });
        buttonOptions.setLocation(1150, 700);
        add(buttonOptions);
    }
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
MillerTime
  • 55
  • 1
  • 6

2 Answers2

5

JPanel, by default, uses a FlowLayout by default. This will layout the components (generally) in a horizontal flow, one next to each other, by default, starting in the top centre.

The question is, why do you need absolute positioning

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I don't technically need absolution positioning, but it'll be much nicer. And I forgot panels used flowlayout by default so I'd need to set it to null. Unfortunately, setting the layout to null make the button not draw at all. – MillerTime Mar 10 '13 at 05:17
  • 3
    Setting the layout manager to null, not only requires you to position the components, but also to provide the size. Absolute positioning is generally not encouraged in Swing with out very good reason (sorry, I have a 10 month sleeping in my lap, so I can't cut an example at the mo) – MadProgrammer Mar 10 '13 at 05:18
  • 1
    @HovercraftFullOfEels she is a beautiful little girl who, thank god, looks like her mother :P – MadProgrammer Mar 10 '13 at 05:39
4

Your current problem is that your code above does not respect the layout managers that are in use by default.

The best solution is to use layout managers to do the laying out of components for you including nesting JPanels, each using its own layout. Some may suggest that you use a null layout, and in most cases that is the wrong thing to do as it makes your program very hard to maintain and close to impossible to upgrade.

By the way, where are you trying to place the button? In the lower right hand corner of your GUI?

Also, rather than using a MouseListener with your JButton, which is usually a bad idea, butter to add a ChangeListener to the JButton's model. Then you can see if the mouse is over the button easily.

Edit
You state:

Yes, the lower right hand corner.

Then one way is to use a GridBagLayout and place the button in the right lower corner by using appropriate constants in your GridBagConstraints parameter.

Edit 1
For example:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class StartScreen extends JPanel implements ActionListener {
   private static final int PREF_W = 1200;
   private static final int PREF_H = 720;
   JButton buttonOptions = new JButton("Options");

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public StartScreen() {
      setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
            GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(
                  5, 5, 5, 5), 0, 0);
      add(buttonOptions, gbc);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // TODO Auto-generated method stub

   }

   private static void createAndShowGui() {
      StartScreen mainPanel = new StartScreen();

      JFrame frame = new JFrame("StartScreen");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Edit 2
Now with Icons that change on hover or "roll-over". And I was wrong -- there's no need to listen to the ButtonModel's state. Simply set the button's Icon and its rollover Icon, and the Button swaps them for you:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

@SuppressWarnings("serial")
public class StartScreen extends JPanel {
   private static final int PREF_W = 1200;
   private static final int PREF_H = 720;
   private static final int BI_WIDTH = 100;
   private static final int BI_HEIGHT = 30;

   private JButton buttonOptions = new JButton();
   private Icon nonHoveredIcon;
   private Icon hoveredIcon;

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public StartScreen() {
      hoveredIcon = createIcon("Hovered");
      nonHoveredIcon = createIcon("Non-Hovered");

      buttonOptions.setIcon(nonHoveredIcon);
      buttonOptions.setRolloverIcon(hoveredIcon);

      setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
            GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(
                  5, 5, 5, 5), 0, 0);
      add(buttonOptions, gbc);
   }

   private ImageIcon createIcon(String text) {
      BufferedImage img = new BufferedImage(BI_WIDTH, BI_HEIGHT, 
            BufferedImage.TYPE_INT_ARGB);
      Graphics g = img.getGraphics();
      g.setColor(Color.black);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      g.drawString(text, 10, 20);
      g.dispose();
      return new ImageIcon(img);
   }

   private static void createAndShowGui() {
      StartScreen mainPanel = new StartScreen();

      JFrame frame = new JFrame("StartScreen");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    I do not agree that calling null layout evil is beneficial. A simple tool is much simpler and more effective to implement using null layout than resorting to a layout manager. Layout managers are the reason why many java programmers, especially beginners hate java. There's more than one way to do it, there is no "right way" to do something, and saying that "in most cases is wrong thing to do" is purely subjective. In most cases it IS the right thing to do, because it is simpler to implement, test, and turn into a layout manager. Good luck maintaining a gridbaglayout as a beginner. – Dmytro Mar 10 '13 at 05:13
  • 5
    @Dmitry You'd have better luck maintaining a GridBagLayout over a null layout - IMHO – MadProgrammer Mar 10 '13 at 05:15
  • 4
    @MillerTime : Simply add a new JPanel to the `PAGE_END` of your contentPane, and let this `Jbutton` be added to this `JPanel` with layout set to `panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5))` (something like this will work) – nIcE cOw Mar 10 '13 at 05:15
  • 2
    @Dmitry: I didn't call them "evil", but I will stand by what I said, that in most instances, you are better off not using null layout. I've seen complex GUI's posted here with many `setBounds(...)` and then the user wants to add one more JRadioButton to a set of JRadioButtons in the middle of the GUI. They'll find that they must re-set all components affected by this change. If they used layout managers and nested JPanels, they instead would only need one line of code. You tell me what is easier, coding right the first time or trying to debug a complex program? – Hovercraft Full Of Eels Mar 10 '13 at 05:15
  • @Hovercraft again, you have to do something until you get it right, before you can do it until you can't get it wrong. Layout managers make this terrible because many people cannot get layout managers to work as they want to begin with. Layout managers force people to think "hey, it is evil to do null layout, and I do not want to do relative and impossible to set up layout, so I will instead make a JPanel and invent my own positioning in it, and set it's preferred size to be say, 800 by 500, and do fixed positioning there, and just make rectangles handle events" – Dmytro Mar 10 '13 at 05:20
  • @Hovercraft My point is, many jobs absolutely have no alternative to null layout, because they require a minimal window size to begin with, and necessary font size, etc. This should mean it would be relatively reliable. Many jobs such as tables, and formal interfaces work well with gridbag layout. For hacky games, and quick projects, layout managers are discouraging, and have killed off far too many projects, just because the alternative is evil. – Dmytro Mar 10 '13 at 05:21
  • 6
    @Dmitry, you are fighting a losing battle with the people that have responded to this posting. We've answwered questions on the forum long enough to know the a null layout causes more problems than it solves. – camickr Mar 10 '13 at 05:24
  • 2
    @Dmitry And the next question they ask is " Why doesn't this work on my friends computer or different OS?". Absolute layouts have there place, I don't believe this is one of them – MadProgrammer Mar 10 '13 at 05:25
  • Again, I have no wish to argue this `yet`, I have simply stated my opinions, and experiences from using them compared to not using them. For now, I will leave my point to a simple `from my experience, using layout managers leads SIMPLE project into a really sticky situations when faced with debugging layouts and adding new functionality`. In most cases which require null layouts (usually games) a new alternative appears to be required though. – Dmytro Mar 10 '13 at 05:30
  • 3
    @Dmitry Look at the [tag:null-layout-manager] questions with accepted answers to see that the most common accepted solution involves using a layout (I was trying to find one that didn't, but failed). – Andrew Thompson Mar 10 '13 at 05:32
  • @Dmitry, yes if you need random, dynamically changing position of components (like in a game) you would use a null layout. This question is NOT about a game! – camickr Mar 10 '13 at 05:37
  • @camickr: Indeed, the OP stated that he wants the button in the lower right corner, something that is very easy to achieve *and maintain* with layout managers. A null layout is asking for a rigid OS and graphics setting inflexible program. – Hovercraft Full Of Eels Mar 10 '13 at 05:38
  • He just needs to position the button on the panel by setting the location. It means that he needs null layout manager, nothing more. I always failed when I was trying to make advanced GUI design by using layout managers – Arsen Alexanyan Mar 10 '13 at 05:39
  • 1
    @camickr But if you have the logic to position components randomly while accounting for visibility/layering when the components overlap, why not encapsulate that in a (custom) `RandomLayout`? Personally I would use a custom layout for 'put it wherever I drop it' - which seems well suited to a `null` layout`. – Andrew Thompson Mar 10 '13 at 05:39
  • 5
    @ArsenAlexanyan: just because you aren't yet able to use them with ease doesn't mean that they are the wrong tool to use! That's like saying because you are not able to cut out an appendix, a patient suffering from acute appendicitis should be treated by a faith healer. The solution for the OP, *and for you* is to learn how to use layouts. – Hovercraft Full Of Eels Mar 10 '13 at 05:41
  • 3
    @ArsenAlexanyan *"It means that he needs null layout manager, nothing more. I always failed.."* Not all programmers lack the competence to use layouts, and your inability to use them is irrelevant. – Andrew Thompson Mar 10 '13 at 05:41
  • 5
    @ArsenAlexanyan With respect, I work on a very complex application, with well over million lines of code, 6+ years in development and 7+ developers and senior managers who like to say "Can't we just add/move/change this?" Layout managers are my saviour. Having programmed in DOS, C/C++ (in Windows, Delphi and (I'm ashamed to say) VB and I can tell you, layout managers are one of most significant timing saving tools there is in Swing. With all due respect, failure to understand/use layout managers isn't the fault of the layout managers – MadProgrammer Mar 10 '13 at 05:47
  • 1
    weird that developers (@Dmitry, @ArsenAlexanyan) without any/much documented experience in Swing/AWT feel obliged to propagate worst practice ... – kleopatra Mar 10 '13 at 14:47