如何为图形创建JPanel

时间:2014-02-19 00:05:38

标签: java swing graphics jpanel

我正在创建一个函数grapher,它为Panel提供了4个参数和大小,但我不知道如何创建一个Panel类来从Grapher类中提取信息。有人可以帮忙吗?(参数不重要,我只是想学习如何制作一个Graph Panel供以后使用)

Panel Class

import java.awt.BorderLayout;

public class Panel extends JFrame {

    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {

    }

    /**
     * Create the frame.
     */
    public Panel(int w, int h) {
        setVisible(true);
        setSize(w,h);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, w, h);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setBackground(Color.WHITE);
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JPanel panel = new JPanel();
        panel.setBackground(Color.WHITE);
        panel.setBorder(new EmptyBorder(0, 0, 0, 0));
        panel.setBounds(0, 0, w, h);
        contentPane.add(panel);
    }


    public void paint(Graphics g) {
        super.paint(g);
        //g.drawLine(110, 112,129, 132);
    }

    public Graphics getGraphics(Graphics g){
        return g;
    }

}

Grapher类

import java.awt.EventQueue;


public class Grapher {

    private int panelWidth;
    private int panelHeight;
    int x1;
    int x2;
    int y1;
    int y2;
    int a;
    int b;
    int c;
    int d;
    private JFrame frmChinhsFunctionGrapher;
    private JTextField textFieldXMin;
    private JTextField textFieldXMax;
    private JTextField textFieldYMin;
    private JTextField textFieldYMax;
    private JTextField textFieldA;
    private JTextField textFieldB;
    private JTextField textFieldC;
    private JTextField textFieldD;
    private JLabel lblPeriod;
    private JLabel lblYIntercept;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Grapher window = new Grapher();
                    window.frmChinhsFunctionGrapher.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Grapher() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frmChinhsFunctionGrapher = new JFrame();
        frmChinhsFunctionGrapher.setTitle("Chinh's function grapher\r\n");
        frmChinhsFunctionGrapher.setBounds(100, 100, 450, 300);
        frmChinhsFunctionGrapher.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmChinhsFunctionGrapher.getContentPane().setLayout(null);

        textFieldXMin = new JTextField();
        textFieldXMin.setText("-200");
        textFieldXMin.setBounds(66, 8, 86, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldXMin);
        textFieldXMin.setColumns(10);

        JLabel lblXMin = new JLabel("X min");
        lblXMin.setBounds(10, 11, 46, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblXMin);

        JLabel lblXMax = new JLabel("X max");
        lblXMax.setBounds(10, 42, 46, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblXMax);

        textFieldXMax = new JTextField();
        textFieldXMax.setText("200");
        textFieldXMax.setBounds(66, 39, 86, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldXMax);
        textFieldXMax.setColumns(10);

        textFieldYMin = new JTextField();
        textFieldYMin.setText("-200");
        textFieldYMin.setBounds(66, 70, 86, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldYMin);
        textFieldYMin.setColumns(10);

        textFieldYMax = new JTextField();
        textFieldYMax.setText("200");
        textFieldYMax.setBounds(66, 101, 86, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldYMax);
        textFieldYMax.setColumns(10);

        JLabel lblYMin = new JLabel("Y min");
        lblYMin.setBounds(10, 73, 46, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblYMin);

        JLabel lblYMax = new JLabel("Y max");
        lblYMax.setBounds(10, 104, 46, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblYMax);

        JLabel lblParameters = new JLabel("Parameters");
        lblParameters.setBounds(320, 11, 93, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblParameters);

        textFieldA = new JTextField();
        textFieldA.setText("100");
        textFieldA.setBounds(360, 39, 64, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldA);
        textFieldA.setColumns(10);

        JLabel lblNewLabel = new JLabel("Graph's Height");
        lblNewLabel.setBounds(263, 42, 72, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblNewLabel);

        textFieldB = new JTextField();
        textFieldB.setText("10");
        textFieldB.setBounds(360, 70, 64, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldB);
        textFieldB.setColumns(10);

        textFieldC = new JTextField();
        textFieldC.setText("100");
        textFieldC.setBounds(360, 101, 64, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldC);
        textFieldC.setColumns(10);

        textFieldD = new JTextField();
        textFieldD.setText("1");
        textFieldD.setBounds(360, 132, 64, 20);
        frmChinhsFunctionGrapher.getContentPane().add(textFieldD);
        textFieldD.setColumns(10);

        JButton btnGraph = new JButton("Graph");
        btnGraph.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {


                getInput();

                Panel pn = new Panel(panelWidth, panelHeight);

                Graphics gs = pn.getGraphics();
                gs.drawLine(100, 100, 200, 200);



            }
        });
        btnGraph.setBounds(10, 228, 89, 23);
        frmChinhsFunctionGrapher.getContentPane().add(btnGraph);

        lblPeriod = new JLabel("Period");
        lblPeriod.setBounds(263, 73, 46, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblPeriod);

        lblYIntercept = new JLabel("Vertical shift");
        lblYIntercept.setBounds(263, 104, 72, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblYIntercept);

        JLabel lblHorizontalShift = new JLabel("Horizontal shift");
        lblHorizontalShift.setBounds(263, 135, 86, 14);
        frmChinhsFunctionGrapher.getContentPane().add(lblHorizontalShift);
    }


    public void getInput(){
        x1 = Integer.parseInt(textFieldXMin.getText());
        x2 = Integer.parseInt(textFieldXMax.getText());
        y1 = Integer.parseInt(textFieldYMin.getText());
        y2 = Integer.parseInt(textFieldYMax.getText());
        a = Integer.parseInt(textFieldA.getText());
        b = Integer.parseInt(textFieldB.getText());
        c = Integer.parseInt(textFieldC.getText());
        d = Integer.parseInt(textFieldD.getText());

        panelWidth = Math.abs(x2 - x1);
        panelHeight = Math.abs(y2 - y1);
    }
}

2 个答案:

答案 0 :(得分:4)

您的代码存在一些问题

您不应使用null布局。您不应该扩展JFrame,即使您这样做,也不应该覆盖JFrame的paint方法。您应该在Event Dispatch Thread上创建GUI。您应该知道如何定义函数的哪个区域绘制到面板的哪个区域。 (绘制像sin(x)这样的函数将产生一条直的水平线,因为这些值将在-1和1之间交替,因此,跨越的范围只有3个像素......)

然而,一旦我创建了https://stackoverflow.com/help/mcve,显示了一个非常简单的绘图仪,可以用来绘制任意函数。也许你发现它的一部分“鼓舞人心”。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Main class of the simple function plotter. Contains the
 * main method and creates the GUI
 */
public class SimplePlotMain
{
    /**
     * Entry point
     *
     * @param args not used
     */
    public static void main(String[] args)
    {
        // Create the GUI on the Event-Dispatch-Thread
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    /**
     * Creates the frame containing the simple plotter
     */
    private static void createAndShowGUI()
    {
        // Create the main frame
        JFrame frame = new JFrame("SimplePlot");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout());
        frame.setSize(800,600);

        // Create the SimplePlotPanel and add it to the frame
        SimplePlotPanel plotPanel = new SimplePlotPanel();
        frame.getContentPane().add(plotPanel, BorderLayout.CENTER);

        // Create the Function that should be plotted, and assign
        // it to the SimplePlotPanel
        Function function = new Function()
        {
            @Override
            public double compute(double argument)
            {
                return Math.sin(argument)*argument;
            }
        };
        plotPanel.setFunction(function);

        // Create a simple control panel and add it to the frame
        JComponent controlPanel = createControlPanel(plotPanel);
        frame.getContentPane().add(controlPanel, BorderLayout.EAST);

        // As the last action: Make the frame visible
        frame.setVisible(true);
    }

    /**
     * Creates a panel containing some Spinners that allow defining
     * the area in which the function should be shown
     *
     * @param plotPanel The SimplePlotPanel, to which the settings
     * will be transferred
     * @return The control-panel
     */
    private static JComponent createControlPanel(
        final SimplePlotPanel plotPanel)
    {
        JPanel controlPanel = new JPanel(new BorderLayout());
        JPanel panel = new JPanel(new GridLayout(0,2));
        controlPanel.add(panel, BorderLayout.NORTH);

        // Create spinners for the minimum and maximum
        // X- and Y-values
        final JSpinner minXSpinner = new JSpinner(
            new SpinnerNumberModel(-1.0, -1000.0, 1000.0, 0.1));
        final JSpinner maxXSpinner = new JSpinner(
            new SpinnerNumberModel( 1.0, -1000.0, 1000.0, 0.1));
        final JSpinner minYSpinner = new JSpinner(
            new SpinnerNumberModel(-1.0, -1000.0, 1000.0, 0.1));
        final JSpinner maxYSpinner = new JSpinner(
            new SpinnerNumberModel( 1.0, -1000.0, 1000.0, 0.1));

        // Add the spinners and some labels to the panel
        panel.add(new JLabel("minX"));
        panel.add(minXSpinner);
        panel.add(new JLabel("maxX"));
        panel.add(maxXSpinner);
        panel.add(new JLabel("minY"));
        panel.add(minYSpinner);
        panel.add(new JLabel("maxY"));
        panel.add(maxYSpinner);

        // Create a ChangeListener that will be added to all spinners,
        // and which transfers the settings to the SimplePlotPanel
        ChangeListener changeListener = new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent event)
            {
                double minX = ((Double)minXSpinner.getValue()).doubleValue();
                double maxX = ((Double)maxXSpinner.getValue()).doubleValue();
                double minY = ((Double)minYSpinner.getValue()).doubleValue();
                double maxY = ((Double)maxYSpinner.getValue()).doubleValue();
                plotPanel.setRangeX(minX, maxX);
                plotPanel.setRangeY(minY, maxY);
            }
        };
        minXSpinner.addChangeListener(changeListener);
        maxXSpinner.addChangeListener(changeListener);
        minYSpinner.addChangeListener(changeListener);
        maxYSpinner.addChangeListener(changeListener);

        // Set some default values for the Spinners
        minXSpinner.setValue(-10.0);
        maxXSpinner.setValue( 10.0);
        minYSpinner.setValue(-10.0);
        maxYSpinner.setValue( 10.0);

        return controlPanel;
    }
}


/**
 * Interface for a general function that may be plotted with
 * the SimplePlotPanel
 */
interface Function
{
    /**
     * Compute the value of the function for the given argument
     *
     * @param argument The function argument
     * @return The function value
     */
    double compute(double argument);
}



/**
 * The panel in which the function will be plotted
 */
class SimplePlotPanel extends JPanel
{
    private static final long serialVersionUID = -6588061082489436970L;

    /**
     * The function that will be plotted
     */
    private Function function;

    /**
     * The minimal x value that is shown
     */
    private double minX = -1.0f;

    /**
     * The maximal x value that is shown
     */
    private double maxX = 1.0f;

    /**
     * The minimal y value that is shown
     */
    private double minY = -1.0f;

    /**
     * The maximal y value that is shown
     */
    private double maxY = 1.0f;

    /**
     * Set the Function that should be plotted
     *
     * @param function The Function that should be plotted
     */
    public void setFunction(Function function)
    {
        this.function = function;
        repaint();
    }

    /**
     * Set the x-range that should be plotted
     *
     * @param minX The minimum x-value
     * @param maxX The maximum y-value
     */
    public void setRangeX(double minX, double maxX)
    {
        this.minX = minX;
        this.maxX = maxX;
        repaint();
    }

    /**
     * Set the y-range that should be plotted
     *
     * @param minY The minimum y-value
     * @param maxY The maximum y-value
     */
    public void setRangeY(double minY, double maxY)
    {
        this.minY = minY;
        this.maxY = maxY;
        repaint();
    }

    /**
     * Overridden method from JComponent: Paints this panel - that
     * is, paints the function into the given graphics object
     */
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        paintAxes(g);
        paintFunction(g);
    }

    /**
     * Converts an x-coordinate of the function into an x-value of this panel
     *
     * @param x The x-coordinate of the function
     * @return The x-coordinate on this panel
     */
    private int toScreenX(double x)
    {
        double relativeX = (x-minX)/(maxX-minX);
        int screenX = (int)(getWidth() * relativeX);
        return screenX;
    }

    /**
     * Converts an y-coordinate of the function into an y-value of this panel
     *
     * @param y The y-coordinate of the function
     * @return The y-coordinate on this panel
     */
    private int toScreenY(double y)
    {
        double relativeY = (y-minY)/(maxY-minY);
        int screenY = getHeight() - 1 - (int)(getHeight() * relativeY);
        return screenY;
    }

    /**
     * Converts an x-coordinate on this panel into an x-coordinate
     * for the function
     *
     * @param x The x-coordinate on the panel
     * @return The x-coordinate for the function
     */
    private double toFunctionX(int x)
    {
        double relativeX = (double)x/getWidth();
        double functionX = minX + relativeX * (maxX - minX);
        return functionX;
    }


    /**
     * Paints some coordinate axes into the given Graphics
     *
     * @param g The graphics
     */
    private void paintAxes(Graphics2D g)
    {
        int x0 = toScreenX(0);
        int y0 = toScreenY(0);
        g.setColor(Color.BLACK);
        g.drawLine(0,y0,getWidth(),y0);
        g.drawLine(x0,0,x0,getHeight());
    }

    /**
     * Paints the function into the given Graphics
     *
     * @param g The graphics
     */
    private void paintFunction(Graphics2D g)
    {
        g.setColor(Color.BLUE);

        int previousScreenX = 0;
        double previousFunctionX = toFunctionX(previousScreenX);
        double previousFunctionY = function.compute(previousFunctionX);
        int previousScreenY = toScreenY(previousFunctionY);

        for (int screenX=1; screenX<getWidth(); screenX++)
        {
            double functionX = toFunctionX(screenX);
            double functionY = function.compute(functionX);
            int screenY = toScreenY(functionY);

            g.drawLine(previousScreenX, previousScreenY, screenX, screenY);
            previousScreenX = screenX;
            previousScreenY = screenY;
        }
    }


}

答案 1 :(得分:0)

首先,我想说删除面板类中的main()方法。它与回答你的问题毫无关系,但我认为这会引起问题和/或混乱。

你需要做的是 1)在面板类中向Grapher类添加一个引用,以便面板绘制方法可以调用Grapher类 2)将引用设置为指向Grapher类的实例 3)使用Panel paint方法调用Grapher类中的方法来绘制图形。

1)添加参考

public class Panel extends JFrame {

    private Grapher myGrapher = null;        //add this line
    private JPanel contentPane;

2)设置参考

public Panel(Grapher graph, int w, int h) {   //change this line
    myGrapher = graph;                        //add this line
    setVisible(true);

public void actionPerformed(ActionEvent arg0) {


            getInput();

            Panel pn = new Panel(this, panelWidth, panelHeight);  //change this line

            //Graphics gs = pn.getGraphics();                     //remove this line
            //gs.drawLine(100, 100, 200, 200);                    //remove this line

        }

3)调用方法

  public void paint(Graphics g) {
        super.paint(g);
        //g.drawLine(110, 112,129, 132);
        if(myGrapher != null)                     //add this line
        {
            myGrapher.drawGraph(g);               //add this line
        }
    }

并在Grapher类中添加方法

void drawGraph(Graphics g) {
    g.drawLine(100, 100, 200, 200);
    //whatever else you need to draw the graph
}
祝你好运!