Domanda

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.

È stato utile?

Soluzione

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
        }
    }
}

Altri suggerimenti

The problem with transparent components is, basically, it's next to near impossible to actually click them ;)

Another solution might be to use a MouseListener on the component rendering the map and simple make the translation from click point to "virtual grid", which you can then renderer over the top, for example...

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BaseBallMap {

    public static void main(String[] args) {
        new BaseBallMap();
    }

    public BaseBallMap() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        public static final int GRID_COUNT = 20;

        private BufferedImage map;
        private List<Point> cells;

        public TestPane() {
            cells = new ArrayList<>(400);
            try {
                map = ImageIO.read(new File("Map.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    Point p = e.getPoint();
                    if (getMapBounds().contains(p)) {
                        p.x -= getXOffset();
                        p.y -= getYOffset();
                        int col = p.x / getColumnWidth();
                        int row = p.y / getRowHeight();
                        System.out.println(col + "x" + row);
                        Point cell = new Point(col, row);
                        if (cells.contains(cell)) {
                            cells.remove(cell);
                        } else {
                            cells.add(cell);
                        }
                        repaint();
                    }
                }

            });

        }

        @Override
        public Dimension getPreferredSize() {
            return map == null ? new Dimension(200, 200) : new Dimension(map.getWidth(), map.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (map != null) {
                Graphics2D g2d = (Graphics2D) g.create();

                int xOffset = getXOffset();
                int yOffset = getYOffset();

                int x = xOffset;
                int y = yOffset;
                g2d.drawImage(map, x, y, this);

                int colWidth = getColumnWidth();
                int rowHeight = map.getHeight() / GRID_COUNT;

                g2d.setColor(new Color(255, 0, 0, 128));
                for (Point p : cells) {

                    x = xOffset + (p.x * colWidth);
                    y = yOffset + (p.y * rowHeight);

                    g2d.fillRect(x, y, colWidth, rowHeight);

                }

                g2d.setColor(new Color(128, 128, 128, 64));
                for (int col = 0; col < GRID_COUNT; col++) {
                    x = xOffset + (col * colWidth);
                    g2d.drawLine(x, yOffset, x, yOffset + map.getHeight());
                }
                for (int row = 0; row < GRID_COUNT; row++) {
                    y = yOffset + (row * rowHeight);
                    g2d.drawLine(xOffset, y, xOffset + map.getWidth(), y);
                }

                g2d.drawRect(xOffset, yOffset, map.getWidth(), map.getHeight());

                g2d.dispose();
            }
        }

        protected int getColumnWidth() {
            return map == null ? 0 : map.getWidth() / GRID_COUNT;
        }

        protected int getRowHeight() {
            return map == null ? 0 : map.getHeight() / GRID_COUNT;
        }

        protected int getXOffset() {
            return map == null ? 0 : (getWidth() - map.getWidth()) / 2;
        }

        protected int getYOffset() {
            return map == null ? 0 : (getHeight() - map.getHeight()) / 2;
        }

        protected Rectangle getMapBounds() {

            return map == null ? new Rectangle(0, 0, 0, 0) : new Rectangle(getXOffset(), getYOffset(), map.getWidth(), map.getHeight());

        }
    }

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top