简体   繁体   中英

Painting on a JFrame

I have a class that extends JFrame with ten radio buttons on it, and I've used a variety of JPanels and GridLayouts to help me place them correctly. I'm attempting to make it so that when you select a combination of radio buttons, the program will draw a line between each of the radio buttons in the order you've selected them. However, I can't get anything to appear. I'm not sure if I'm not overridding the right method, if I should be using Graphics2D, if the panels are hiding whatever I'm drawing...preferably, I'd like a solution that doesn't have me overriding a JPanel or something like that.

    public void paintComponent(Graphics g)
{
    super.update(g);
    if(buttonsSelected>1)
    {
        g.setColor(new Color(0xE3, 0xC9, 0x39));
        for(int k=0;k>4&&lastButton[k+1]!=-1;k++)
        {
            g.drawLine(buttonTest[lastButton[k]].getX(), buttonTest[lastButton[k]].getY(), buttonTest[lastButton[k+1]].getX(), buttonTest[lastButton[k]].getY());
            System.out.println("Ole!");
        }
    }
}

Additionally, here is part of the code I'm using to draw the panes

    int j=0;
    for(int k=0;k<10;k++)
    {
        buttonTest[k]=new JRadioButton();
        buttonTest[k].setActionCommand(Integer.toString(k));
        buttonTest[k].setToolTipText(powersDin[k]);
        buttonTest[k].addActionListener(new GoddessListener());
        buttonTest[k].setEnabled(false);
    }
    buttonTest[0].setEnabled(true);
    buttonTest[6].setEnabled(true);
    buttonTest[9].setEnabled(true);

    paneGrids[0]=new JPanel();
    paneGrids[0].setLayout(new GridLayout(1,7));
    paneGrids[0].add(new JLabel()); //adding a blank JLabel lets me pad out the empty cells I don't want to fill
    paneGrids[0].add(new JLabel());
    paneGrids[0].add(new JLabel());
    paneGrids[0].add(buttonTest[j++]);
    paneGrids[0].add(new JLabel());
    paneGrids[0].add(new JLabel());
    paneGrids[0].add(new JLabel());

You should use the @Override annotation on your paintComponent method. You will see that you are not overriding any method on your JFrame. It is because paintComponent is defined on JComponent which JFrame does not inherit from. Therefore your paintComponent method is never called.

Instead of trying to paint on a top-level container ( which should generally not be done ), use a JPanel for the custom painting.

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

    // your custom painting
}

Using a JPanel is no more complicated, just call yourFrame.setContentPane(yourCustomPanel); .

If you want to draw on top of the children you can override paint judiciously . paintComponent will necessarily draw behind the children because it is for drawing the component. paint will draw on everything . The other option for drawing on top of children is to using something like a glass pane or JLayeredPane which are more difficult to work with.

Here is an MCVE that demonstrates how to do something like I think you are wanting to do simply.

连接网格

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JCheckBox;
import javax.swing.SwingUtilities;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.RenderingHints;

import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Iterator;

class ConnectiveGrid implements Runnable {
    static final int GRID_H = 5;
    static final int GRID_W = 10;

    Map<JCheckBox, Point> path;
    GridPanel grid;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ConnectiveGrid());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Connective Grid");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // (LinkedHashMap will maintain insertion order)
        path = new LinkedHashMap<JCheckBox, Point>();

        grid = new GridPanel();
        ActionListener listener = new Listener();

        for(int i = 0; i < GRID_H * GRID_W; i++) {
            JCheckBox check = new JCheckBox();
            check.addActionListener(listener);
            grid.add(check);
        }

        frame.setContentPane(grid);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class Listener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent ae) {
            Object sc = ae.getSource();
            if(!(sc instanceof JCheckBox)) {
                return;
            }

            JCheckBox check = (JCheckBox)sc;
            if(check.isSelected()) {

                Dimension sz = check.getSize();
                Point pt = check.getLocation();

                pt.x += sz.width / 2;
                pt.y += sz.height / 2;

                // if the check box is selected
                // put it and its associated point in the path
                path.put(check, pt);

            } else {

                // else remove the check box and point
                path.remove(check);
            }

            // prompt a clean repaint
            grid.repaint();
        }
    }

    class GridPanel extends JPanel {
        GridPanel() {
            super(new GridLayout(GRID_H, GRID_W));
        }

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

            // verify there are enough points to draw at least one line
            if(path.size() < 2) {
                return;
            }

            Graphics2D copy = (Graphics2D)g.create();
            copy.setPaint(Color.BLUE);
            copy.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON
            );

            // iterate the path and paint line-by-line
            Iterator<Point> it = path.values().iterator();
            Point prev = it.next();
            do {
                Point next = it.next();

                copy.drawLine(
                    prev.x, prev.y,
                    next.x, next.y
                );

                prev = next;
            } while(it.hasNext());

            copy.dispose();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM