如何创建用于绘图的JPanel [英] How to create a JPanel for graphing

查看:134
本文介绍了如何创建用于绘图的JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个带有4个参数和大小的Panel的函数绘图器,但是我不知道如何创建一个Panel类,该类将从Grapher类中提取信息.可以帮忙吗?(参数并不重要,我只想学习如何制作图形面板以备后用)

I'm making a function grapher that take 4 parameters and size for the Panel, but I don't know how to create a Panel class that will draw the information from the Grapher class. Can some one help please?(The parameters are not important, I just want to learn how to make a Graph Panel for later use)

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

}

绘图仪类

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

推荐答案

您的代码存在很多问题

您不应使用null布局.您不应该扩展JFrame,即使这样做,也不应覆盖JFrame的paint方法.您应该在事件调度线程上创建GUI.您应该对如何定义函数的哪个区域到面板的哪个区域有所了解. (绘制sin(x)之类的函数将得到一条水平的直线,因为这些值将在-1和1之间交替,因此跨度仅为3个像素...)

You should not use the null layout. You should not extent JFrame and even if you do it, you should not override the paint method of JFrame. You should create the GUI on the Event Dispatch Thread. You should have an idea of how you are going to define which area of the function is plotted into which area of the panel. (Plotting a function like sin(x) will result in a straight, horizontal line, because the values will alternate between -1 and 1, and thus, span a range of only 3 pixels...)

但是,一旦我创建了 https://stackoverflow.com/help/mcve 并显示了非常 em>简单绘图仪,可用于绘制任意函数.也许您会发现其中的一部分鼓舞人心".

However, once I created a https://stackoverflow.com/help/mcve showing a very simple plotter that can be used to plot arbitrary functions. Maybe you find parts of it "inspiring".

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


}

这篇关于如何创建用于绘图的JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆