0

I have googled this and read a lot but did not find an answer that suits my needs, so I'll ask here:

I would like to have a gradient background in my JFrame. Currently the background is a single colour. My code looks something like this:

//imports

public class Game {

   //some other irrelevant instance variables

   JFrame frame = new JFrame("Game");

   public Game() {

       frame.getContentPane().setBackground(new Color(200,220,200));
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setLayout(null);
       frame.setPreferredSize(new Dimension(frameX,frameY)); //frameX and frameY are instance variables

       getMenu(); //method that adds a few JLabels to the JFrame and so on

   }
}

The methods that I have read about apply to classes that extend JPanel or JFrame (and then use GradientPaint or something like that), but as you can see I use JFrame as an instance variable. Can someone help me out?

Edit: Picture:

enter image description here

Sid
  • 563
  • 1
  • 10
  • 28
  • @Reimeus I think it was very unhelpful of you to delete your answer. There was a person who commented there who was willing to help me, even though you decided to ignore my follow-up question. – Sid Jan 16 '14 at 17:28
  • @Reimeus Yes and I had seen it before I posted my question, but that person is working with a JPanel. – Sid Jan 16 '14 at 17:32

1 Answers1

5

Now, obviously, your example image above does not specify buttons and does not add a label for the message at the bottom. But since it was obvious you intended the user to select those options, I used buttons. The label at the bottom is just to show proof they are buttons (with an action listener attached, to show the message).

The advantage of using actual buttons is that they are also keyboard accessible (press Enter to see the first message, press Tab to navigate to the next one...

If the game does not need to be keyboard accessible, you can swap those out for labels and add a mouse listener. I'll leave that to you.

The code has a lot of comments containing the word 'adjust'. Look at them closely, check the JavaDocs, adjust them as needed..

enter image description here enter image description here

enter image description here enter image description here

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

public class GradientPaintBackground {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                // the GUI as seen by the user (without frame)
                JPanel gui = new JPanel(new BorderLayout(15, 15)) {

                    @Override
                    public void paintComponent(Graphics g) {
                        super.paintComponent(g);

                        Point point1 = new Point(10, 10);
                        Point point2 = new Point(
                                getWidth() - 10, 
                                getHeight() - 10);
                        final GradientPaint gp = new GradientPaint(
                                point1, Color.YELLOW,
                                point2, new Color(255, 225, 100),
                                true);

                        // we need a Graphics2D to use GradientPaint.
                        // If this is Swing, it should be one..
                        final Graphics2D g2 = (Graphics2D) g;
                        g2.setPaint(gp);
                        g.fillRect(0, 0, getWidth(), getHeight());
                    }
                };
                // adjust size to need.
                gui.setBorder(new EmptyBorder(20, 20, 20, 20));

                // Start:  Add components
                // adjust size to size of logo
                BufferedImage logo = new BufferedImage(
                        100, 40, BufferedImage.TYPE_INT_RGB);
                JLabel logoLabel = new JLabel(new ImageIcon(logo));
                gui.add(logoLabel, BorderLayout.NORTH);

                // adjust spacing to need
                JPanel menuPanel = new JPanel(new GridLayout(0, 1, 20, 20));
                menuPanel.setBorder(new EmptyBorder(5, 55, 5, 5));
                // allow the BG to show through..
                menuPanel.setOpaque(false);
                gui.add(menuPanel);
                String[] actionTexts = new String[]{
                    "Play Game", "Tutorial", "Other"
                };
                final JLabel messages = new JLabel("Ready to play?  "
                        + "Select an option");
                gui.add( messages, BorderLayout.PAGE_END );
                ActionListener al = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (e.getSource() instanceof JButton) {
                            JButton b = (JButton)e.getSource();
                            messages.setText(b.getText() + " selected!");
                        }
                    }
                };
                for (int ii = 0; ii < actionTexts.length; ii++) {
                    JButton b = new JButton(actionTexts[ii]);
                    b.setContentAreaFilled(false);
                    b.setHorizontalAlignment(SwingConstants.LEADING);
                    b.setBorder(null);
                    b.addActionListener(al);
                    menuPanel.add(b);
                }
                // End:  Add components

                JFrame f = new JFrame("Gradient Background in JFrame");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See https://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                f.setMinimumSize(f.getSize());
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

General Tip

Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. This is why you are continually seeing the types of problems you see. Toss layouts out the window, and all hell breaks loose.

To organize the components for a robust GUI, instead use layout managers, or combinations of them1, along with layout padding & borders for white space2.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • The reason I don't like to use JButtons is because I have stylish images that I want to use in place of the custom Java buttons. I feel like the layout managers don't offer me much flexibility. – Sid Jan 17 '14 at 01:31
  • *"I have stylish images"* No problem. See [this answer](http://stackoverflow.com/a/10862262/418556). *"I feel like the layout managers don't offer me much flexibility."* The thing is, it is not just layout managers, but also borders, margins within components, size hints to components (columns and rows).. Thw "White Space" GUI above goes into some of that. It is complex, but once you understand the principles, it is possible to create just about any robust layout of components (and by 'robust' I mean, won't break on another OS or machine) -- The alternative, results in a fragile GUI. – Andrew Thompson Jan 17 '14 at 05:20