Search code examples
javaswingjbuttonclickableinvisible

Working with JButtons (extra help)


I've recently been working on putting together a program that can track one's success during a basketball game. I have a court diagram set up, and my idea is that after clicking a "make" or "miss" button, you can click a spot on the court and it will chart your makes and misses while keeping tallies of both off to the side. I was thinking the easiest way to do this was to fill the court with a huge grid of buttons (20x20), and when you click one it would change the text to an "x" or an "o" depending on if it was a made shot. I have no problems for creating listeners for the various buttons, but the buttons show up over top of the graphics of the court lines. Making the buttons transparent (which I tried) makes it look a little better, but my ideal solution would be to make the buttons in the grid invisible, yet clickable and able to change its text after being clicked.

I am yet to find such a method or other way to make this happen, so if anyone has any experience or input in creating something that could make it function in this way would help. I guess my ultimate question would be is there a way to make buttons invisible, yet clickable? If there is no simple way to do this (which I fear), are there any other ideas that you have that could make this program function effectively that might not involve buttons?

Thank you very much and any ideas would help me out a lot.

I also think I might note that I have a separate driver from the code, even though it probably does not make a difference.


Solution

  • You could do something like this

    For the two buttons, just change the boolean make. You'll see why later

    boolean make = false;
    
    makeButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent){
            make = true;
        }
    });
    
    missButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent){
            make = false;
        }
    });
    

    Then you have your paintComponent

    protected void paintComponent(Graphics g){
        super.paintComponent(g);
    
        if (make){
            drawOval(whataver are your point requirements)
        } else {
            // draw an x at whatever points
        }
    }
    

    You can see from above that I made use of the made variable

    Now to get the location you can do something like this

    Point p;
    
    courtPanel.addMouseListener(new MouseAdapter(){
        public void mouseClicked(MouseEvent e){
            p = e.getLocationOnScreen();
            repaint();   
        }
    });
    

    You paint component will paint based off those point coordinates.

    SO basically, what all the thing I listed above does is:

    1) When the makeButton is pressed, it changes the setting to made so when the panel is painted, it gets painted with a circle and an X when the missButtton is pressed.

    2) I add a mouseListener to thecourtPanelbecuase everytime the panel is clicked somewhere, that's the point on the floor where is it either painted anxor acircle`

    If you want multiple X and circle painted you do something like this

    private boolean make = false;
    private HashMap<Boolean, Point> points = new HaspMap<>();
    
    makeButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent){
            make = true;
        }
    });
    
    missButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent){
            make = false;
        }
    });
    
    courtPanel.addMouseListener(new MouseAdapter(){
        public void mouseClicked(MouseEvent e){
            if (make) {
                points.put(true, e.getLocationOnScreen());
                repaint();   
            } else {
                points.put(false, e.getLocationOnScreen());
                repaint();
            }
    
    });
    
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
    
        for (Map.Entry<Boolean, Point> entry : points.entrySet()) {
            Boolean key = entry.getKey();
            Point point = entry.getValue();
    
            if (key) {
                g.grawOval(point.getX(), point.getY(), 10, 20);
            } esle {
                g.drawLine(.., .., .., ..);  //draws one half of `X`
                g.drawLine(.., .., .., ..);  //draws other half
            }
        }
    }