Search code examples
javaswingjpanelpaintcomponent

JButtons hidden by paintComponent


I have two screens that both extend GameScreen, which in turn extends a JPanel. My NavigationFrame class executes properly, but my InternalSensorsFrame is drawing the gray background rectangle over my buttons so that the buttons are hidden and only briefly flicker to visible when you mouse over them. Here is my code. Can anyone tell me why the one example is working and the other is not, and how I can fix it?

public class NavigationFrame extends GameScreen {

...
    public NavigationFrame() {
        //super(parent);
        addKeyListener(new TAdapter());
        //background
        img = new ImageIcon(Home.resources.getClass().getResource(imageName));
        bg = new BufferedImage(
        img.getIconWidth(),
        img.getIconHeight(),
        BufferedImage.TYPE_4BYTE_ABGR);
        Graphics gg = bg.createGraphics();
        img.paintIcon(null, gg, 0,0);
        gg.dispose();
        RenderingHints rh =
                new RenderingHints(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);

    gameFont = new Font("Helvetica", Font.BOLD, 14);

    //Set Viewscreen to blockmapview
    if (viewScreen == null){
        setViewScreen(new ScrollShipScreen(this, 0));
    }
    viewScreen.setBounds(150, 50, 500, 500);
    add(viewScreen);

    //Buttons
    btnMainComputer = new JButton("Main Computer");
    btnMainComputer.setBounds(140, 560, 120, 23);
    btnMainComputer.addActionListener(this);
    add(btnMainComputer);

    btnInternalSensors = new JButton("Internal Sensors");
    btnInternalSensors.setBounds(330, 560, 130, 23);
    btnInternalSensors.addActionListener(this);
    add(btnInternalSensors);

    btnNavigation = new JButton("Navigation");
    btnNavigation.setBounds(550, 560, 110, 23);
    btnNavigation.addActionListener(this);
    add(btnNavigation);


    }

    @Override
    public void paintComponent(Graphics g) {
        //background
        g.setColor(Color.decode("#666665"));
        Graphics2D g2d = (Graphics2D) g;
        g2d.fillRect(0, 0, 800, 600);
        g2d.drawImage(bg, 0, 0,img.getIconWidth(), img.getIconHeight(), this);

        //text setup
        g.setColor(Color.white);
        g.setFont(gameFont);


        //Write the strings
        //left bar
        g.drawString(location, 10,60);
....

    }



    //Button Presses
    public void actionPerformed(ActionEvent ae) {   
        JButton o = (JButton) ae.getSource();
....
        else if(o == btnMainComputer){
            Container parent  = getParent();
            parent.remove(Home.getCurrentScreen());
            Home.setCurrentScreen(new MainComputerFrame());
            parent.add(Home.getCurrentScreen());
            //System.out.println("Main Comp");
        }
        else if(o == btnInternalSensors){
            Container parent  = getParent();
            parent.remove(Home.getCurrentScreen());
            Home.setCurrentScreen(new InternalSensorsFrame());
            parent.add(Home.getCurrentScreen());
            //System.out.println("Sensors");

        }
        else if(o == btnNavigation){
            //Does nothing on a navigation Frame
//          remove(Home.getCurrentScreen());
//          Home.setCurrentScreen(new NavigationFrame());
//          Home.frame.add(Home.getCurrentScreen());
        }

        this.requestFocus();
    }

}

and here is the non-working class:

public class InternalSensorsFrame extends GameScreen {
private String imageName = "textures/interface/View Screen Frame Overlay.png";



public InternalSensorsFrame(){
    //super(parent);
    addKeyListener(new TAdapter());

    //background
    img = new ImageIcon(Home.resources.getClass().getResource(imageName));
    bg = new BufferedImage(
    img.getIconWidth(),
    img.getIconHeight(),
    BufferedImage.TYPE_4BYTE_ABGR);
    Graphics gg = bg.createGraphics();
    img.paintIcon(null, gg, 0,0);
    gg.dispose();
    RenderingHints rh =
            new RenderingHints(RenderingHints.KEY_ANTIALIASING,
           RenderingHints.VALUE_ANTIALIAS_ON);
    rh.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);

    //Add buttons
    btnMainComputer = new JButton("Main Computer");
    btnMainComputer.setBounds(140, 560, 120, 23);
    btnMainComputer.addActionListener(this);
    add(btnMainComputer);

    btnInternalSensors = new JButton("Internal Sensors");
    btnInternalSensors.setBounds(330, 560, 130, 23);
    btnInternalSensors.addActionListener(this);
    add(btnInternalSensors);

    btnNavigation = new JButton("Navigation");
    btnNavigation.setBounds(550, 560, 110, 23);
    btnNavigation.addActionListener(this);
    add(btnNavigation);

}
@Override
public void paintComponent(Graphics g) {
    //super.paint(g);
    g.setColor(Color.decode("#666665"));
    Graphics2D g2d = (Graphics2D) g;
    g2d.fillRect(0, 0, 800, 600);
    g2d.drawImage(bg, 0, 0,img.getIconWidth(), img.getIconHeight(), this);
    g2d.translate(150, 50);
    Home.ship.shipLayout.paintComponent(g2d);
//        ArrayList<CrewMan> crew = Home.ship.crew;
//        for (int i=0; i<crew.size(); i++){
//          crew.get(i).paint(g2d);
//        }
        g.setColor(Color.white);
        g.drawString("teststring", 10,60);
        //super.paint(g);

        //Toolkit.getDefaultToolkit().sync();
      //  g.dispose();
}

        //Button Presses
        public void actionPerformed(ActionEvent ae) {   

            JButton o = (JButton) ae.getSource();

            if(o == btnMainComputer){
                Container parent  = getParent();
                parent.remove(Home.getCurrentScreen());
                Home.setCurrentScreen(new MainComputerFrame());
                parent.add(Home.getCurrentScreen());
                //System.out.println("Main Comp");
            }
            else if(o == btnInternalSensors){
                Container parent  = getParent();
                parent.remove(Home.getCurrentScreen());
                Home.setCurrentScreen(new InternalSensorsFrame());
                parent.add(Home.getCurrentScreen());
                //System.out.println("Sensors");

            }
            else if(o == btnNavigation){
                Container parent  = getParent();
                parent.remove(Home.getCurrentScreen());
                Home.setCurrentScreen(new NavigationFrame());
                parent.add(Home.getCurrentScreen());
            }

            this.requestFocus();
        }
}

Solution

  • Perhaps this advices don't solve your issue but may be help.

    1)

    Call super.paintComponent(g) when you override this method.

    @Override
        public void paintComponent(Graphics g) {
            //background
            super.paintComponent(g);
            g.setColor(Color.decode("#666665"));
            Graphics2D g2d = (Graphics2D) g;
            g2d.fillRect(0, 0, 800, 600);
            g2d.drawImage(bg, 0, ...
    

    2) requestFocus()

    Note that the use of this method is discouraged because its behavior is platform dependent. Instead we recommend the use of requestFocusInWindow().

    3) Use proper name for your classes you are saying that your class is a Frame when in fact is a JPanel.

    4) As a personal suggestion don't use too much concrete inheritance cause it's dangereous and hard to mantain, and your inheritance tree level is too high, instead you can use something like this.

    Example:

    public class NavigationComponent {
    
    private GameScreen gameScreen;
    
    public NavigationComponent(){
          gameScreen = new GameScreen(){
               @override
              public paintComponent(Graphics g){
                  // code here
              }
    
          };
    }
    
    }
    

    5) You are adding keyListener to a JPanel. To get this work you have to make your object focusable and to be in focus.Instead of keyListener the swing way is to use KeyBinding. Swing was designed to use with keyBindings.How to use keybindings