-2

I want to create a simple game menue for the game pong. In the background there is a ball that bounces of the edges just to look nice. Now I want to add Buttons to this menue screen. But then the Background isn't painted anymore. So i want to draw a live Background but the buttons should still stay in the front. This live Background is implemented with a loop. In the following are the GUI class and the DrawStartMenueClass.

I heard about Layers but everybody uses them with some kind of tool in NetBeans and I got eclipse so I don't have that opportunity. I guess you can put the buttons and the background in different containers but then again I am not sure how that would. Every help is welcome.


public class GUI {



    public GUI() {

        //Frame erzeugen
        Var.frame = new JFrame("Pong");
        Var.frame.setSize(Var.dimension);
        Var.frame.setVisible(true);
        Var.frame.setResizable(true);
        Var.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Var.frame.setLocationRelativeTo(null);

        //Komponenten erzeugen
        Var.start = new JButton("Start");
        Var.optionen = new JButton("Optionen");
        Var.modus = new JButton("Modus");
        Var.skins = new JButton("Skins");
        Var.beenden = new JButton("Beenden");

        //Komponenten anpassen
        Var.start.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 400, Var.buttonWidth, 50);
        Var.optionen.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 500, Var.buttonWidth, 50);
        Var.modus.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 600, Var.buttonWidth, 50);
        Var.skins.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 700, Var.buttonWidth, 50);
        Var.beenden.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 800, Var.buttonWidth, 50);

        //Komponenten hinzufügen
        Var.frame.getContentPane().add(new DrawStartMenue());
        Var.frame.add(Var.start);
        Var.frame.add(Var.optionen);
        Var.frame.add(Var.modus);
        Var.frame.add(Var.skins);
        Var.frame.add(Var.beenden);

    }

}

package main;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import javax.swing.JPanel;


public class DrawStartMenue extends JPanel{

    private static final long serialVersionUID = 1L;
    private GridLayout experimentLayout = new GridLayout(6,1);


    public Graphics2D g2d;

    public void paint(Graphics g) {

        //Objekt g zum Zeichnen erzeugen
        super.paintComponent(g);
        g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        //Hintergrund
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0,  0,  Var.screenWidth,  Var.screenHeight);
        g2d.setColor(Color.WHITE);
        g2d.setStroke(new BasicStroke(8));
        g2d.drawRect(Var.whiteRectX1, Var.whiteRectY1 , Var.whiteRectWidth, Var.whiteRectHeight);

        //Ball im Hintergrund
        for(int i = 0; i < Var.ballList.size(); i++) {
            g2d.fillOval(Var.ballList.get(i).ballX, Var.ballList.get(i).ballY,
                         Var.ballList.get(i).ballWidth, Var.ballList.get(i).ballHeight);
        }

        //Schriftzug
        drawCenteredString(g, "PONG", Var.rect, new Font("NO CONTINUE", Font.PLAIN, 230));
        repaint();


    }

George Z.
  • 6,643
  • 4
  • 27
  • 47
Nicky
  • 121
  • 1
  • 7
  • 1
    Consider creating a [mre]. – George Z. Aug 13 '19 at 15:40
  • I am sorry. But that really is reduced already. I didnt even show the loop in order to make the code shorter. – Nicky Aug 13 '19 at 16:44
  • *"that really is reduced already."* There is more to an MRE than 'minimal'. Please read that document again, as well as the document on the [Short, Self Contained, Correct Example](http://www.sscce.org/). – Andrew Thompson Aug 14 '19 at 02:56

2 Answers2

2
    Var.frame.getContentPane().add(new DrawStartMenue());
    Var.frame.add(Var.start);
    Var.frame.add(Var.optionen);
    Var.frame.add(Var.modus);
    Var.frame.add(Var.skins);
    Var.frame.add(Var.beenden);

The default layout for a JFrame is the BorderLayout. When you add a component to the frame without specifying a constraint the component is added to the CENTER. Only one component can be added to the CENTER. So only the last one added is visible.

If you want the button on the background then you need to add the buttons to background panel, not the frame:

    JPanel background = new DrawStartMenue();
    Var.frame.add(background, BorderLayout.CENTER);
    background.add(Var.start);
    background.add(Var.optionen);
    background.add(Var.modus);
    background.add(Var.skins);
    background .add(Var.beenden);

Other problems with the code:

  1. custom painting is done by overriding paintComopnent(...) not paint(...).
  2. Never invoke repaint() in a painting method. Swing will determine when the component should be repainted.
  3. components should be added to the frame BEFORE the frame is made visible.
  4. don't attempt to setBounds(...) components. Swing was designed to be used with layout managers. Use the appropriate layout manager for your desired layout.

Edit:

So you know how to:

  1. add components to a panel
  2. do custom painting on a panel.

So to combine both concepts you modify the SwingPaintDemo2 code as follow:

//f.add(new MyPanel());
JPanel panel = new MyPanel();
panel.add( new JButton("Testing") );
f.add(panel);

So know that you know the basics, you use the knowledge on your real code.

And don't forget, you should NEVER invoke repaint in a painting method. I already showed you how to use a Swing Timer for the animation.

Next if you don't like the location of the buttons, then you use a different layout manager on the MyPanel class. If you need help with layout manager, then the Swing tutorial also has a section on layout manager with working example for you to download and test.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • So I tried using the border Layout and the buttons won't appear. Then I tried it without using the border Layout and then the buttons appeared. They were in the wrong place but at least they appeared. I changed the paint Method to painComponent. Also if I don't repaint() i don't see the balls animation on the screen. I tried adding the buttons to a different panel than the background panel and added that to the content pane of the JFrame. Didn't work either. I also tried setting the frame visible at the very end. Didn't work either. Also setComponentZOrder does not work. Happy to hear anwers. – Nicky Aug 20 '19 at 12:29
  • *So I tried using the border Layout and the buttons won't appear.* - I never suggested you change anything to use the BorderLayout. I said the default layout of the frame is a BorderLayout. The default layout of a JPanel is the FlowLayout. You just add the background panel to the frame and the buttons to the background panel. If you don't like the FlowLayout of your panel then change the layout manager. *Also if I don't repaint() i don't see the balls animation* - animation is done by using a `Swing Timer`. See: https://stackoverflow.com/a/54028681/131872 for a complete example. – camickr Aug 20 '19 at 15:56
  • I guess I am just to stupid to create GUIs. None of the research I do helps with the problem I got. But thanks for trying your best. – Nicky Aug 20 '19 at 16:34
  • The problem is that you still haven't posted an [mre]. You are trying to run before you learn to walk. All you need to do is create a JPanel and set its background color to RED. Then you create a JButton and add the button to the panel. Then you add the panel to the frame. The entire code will be 10-15 lines. Then you have something to post in the forum. There is no need to worry about all those variables you have. Get the basics working. Then you replace the JPanel with your custom JPanel. One step at a time. – camickr Aug 20 '19 at 19:42
  • So I created an MRE. But that doesn't help at all. Now the I have set the Backgroundcolor to black ( or red doesn't matter). The buttons appear in front of the background, in the wrong place (thats not the problem) but at least they appear. However that of course doesn't help with the problem I have because I want to draw a "live" background that changes permanently. And of course the argument for the setBackground method is a color and not a panel or component. So now I have a static background all in one color. – Nicky Aug 21 '19 at 06:05
  • *But that doesn't help at all.* of course it does. You proved you know how to add buttons to a JPanel. Your class is also a JPanel so you add buttons to it the same way. But first lets learn to do custom painting properly. Read the section from the Swing tutorial on [Custom Painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html) and download the `SwingPaintDemo2` code and test it. This shows the proper way to do custom painting by overriding `paintComponent(...)` and `getPreferredSize()`. Once that is done see "my edited answer" for code to demonstrate both concepts. – camickr Aug 21 '19 at 14:31
  • I override the method painComponent(). And I already tried adding the buttons to my CustomPanel. They don't appear which is why I posted this question in the first place. – Nicky Aug 21 '19 at 17:07
-1

Here is the MRE. I finally got it to work. However it doesn't work in my project.

package main;

import java.awt.Color;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GUI {

    static JFrame frame;
    static JPanel buttons;
    static JPanel background;
    static JButton test1;
    static JButton test2;

    public static void main(String[] args) {

        frame = new JFrame();
        frame.setResizable(false);
        frame.setSize(600,  400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        //Initzialize Components
        buttons = new JPanel();
        buttons.setBackground(Color.BLACK);

        background = new JPanel();
        background.setBackground(Color.BLACK);

        test1 = new JButton("Test1");
        test2 = new JButton("Test2");


        //Adding the Buttons
        buttons.add(test1);
        buttons.add(test2);

        //Adding panels to JFrame
        frame.add(background);
        //frame.add(buttons);

        background.add(buttons);

        frame.setVisible(true);




    }

}
Nicky
  • 121
  • 1
  • 7
  • The solution works for me. And as it seems no one here is able to provide a different one. Maybe I dont understand the basics of swing. That may be because no one teaches me except for myself which is not particularly easy. And it seems nobody really understands my problem. I know you can add buttons when you custom paint. But I repaint 120 times a times and no matter what I tried nothing worked except for adding the buttons to the glass pane. If you have a better solution which I assume you have and enlighten me. But just stating it is possible without a solution doesnt help. – Nicky Sep 01 '19 at 15:13
  • *That may be because no one teaches me* - I gave you a tutorial link that demonstrates the basics. You learn by reading and looking at working code. *If you have a better solution* I did provide you a solution. Of course this assumes you actually took the time to read the tutorial. Then you download the code from the tutorial and change/add the 4 lines of code I gave you. I also provided you will a solution for animation hundreds of balls. – camickr Sep 01 '19 at 17:30
  • Another possibility is to just add the buttons to a panel and add the panel to the PAGE_START of the frame and you custom panel to the CENTER of the frame. Now the buttons will appear above (not on top) of the custom painted panel. Again read the Swing tutorial on [How to Use the BorderLayout](https://docs.oracle.com/javase/tutorial/uiswing/layout/border.html) for working examples. All the Swing basics are in the tutorial. You have no one to blame but yourself if you don't take the time to read the tutorial . – camickr Sep 01 '19 at 17:33
  • I am sorry. I know I come across pretty stupid at this point. But if I use your suggested method adding the panel with the Buttons to PAGE_START and adding the custom panel to CENTER I only get a grey Rectangle on top of the frame which of course is the panel where the buttons should. Not only are the buttons above the custom panel that should stay in the background. They are not visible at all. I really did read the tutorial on custom painting and on the BorderLayout. But as far as I can see they don't help with the problem. – Nicky Sep 01 '19 at 19:44
  • *I only get a grey Rectangle on top of the frame* - prove it! Where is your [mre]. We can't see what you are really doing if you never post your [mre]. If you add buttons to the panel and you add the panel to the frame, then the buttons will display. I already stated they will be "above", not "on top" of your custom panel. – camickr Sep 01 '19 at 20:06
  • It was a suggestion to try to show you how the parent/child design of Swing works. You can add multiple panels directly to the frame (by specify the BorderLayout constraints), or you can add one panel to the frame and then a second component (or panel) to the child panel you just added to the frame. Which approach you use depends on your requirement. But you first need to understand that you have options. – camickr Sep 01 '19 at 20:07
  • So I have added the MRE as you can see. But it doesn't really help with my problem. Because a static is background is not what I want. – Nicky Sep 22 '19 at 12:49