Java如何绘制/绘制图形?
该程序读取数据文件并在文件中绘制数据点的图形。该图形绘制在具有三个部分的窗口中。第一部分包含三个按钮,用于启动程序的操作。动作也可以通过控制键启动。
第二部分显示要绘制图形的数据,并允许用户编辑图形数据。最后一部分显示图形。
package org.nhooo.example.geom; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.*; public class Plot { public static void main(String[] args) { JFrame frame = new JFrame("Plot"); frame.getContentPane().setLayout(new BorderLayout()); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); String className = UIManager.getSystemLookAndFeelClassName(); UIManager.setLookAndFeel(className); JPanel commandPanel = new JPanel(new FlowLayout()); JButton openButton = new JButton("Open Ctrl-O"); JButton plotButton = new JButton("Plot Ctrl-P"); JButton quitButton = new JButton("Quit Ctrl-Q"); quitButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); commandPanel.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }, KeyStroke.getKeyStroke("control Q"), JComponent.WHEN_IN_FOCUSED_WINDOW); commandPanel.add(openButton); commandPanel.add(plotButton); commandPanel.add(quitButton); frame.getContentPane().add(commandPanel, "North"); GraphPanel graphpanel = new GraphPanel(frame); plotButton.addActionListener(graphpanel); commandPanel.registerKeyboardAction(graphpanel, KeyStroke.getKeyStroke("control P"), JComponent.WHEN_IN_FOCUSED_WINDOW); openButton.addActionListener(graphpanel.getDataPanel()); commandPanel.registerKeyboardAction(graphpanel.getDataPanel(), KeyStroke.getKeyStroke("control O"), JComponent.WHEN_IN_FOCUSED_WINDOW); frame.setVisible(true); frame.pack(); } } class GraphPanel implements ActionListener { private DataPanel datapanel; private JFrame frame; private GraphicPanel panel; GraphPanel(JFrame newFrame) { frame = newFrame; panel = new GraphicPanel(); panel.setDisplayPlot(false); datapanel = new DataPanel(frame); panel.setDataPanel(datapanel); frame.getContentPane().add(panel, "Center"); } public void actionPerformed(ActionEvent e) { if (!datapanel.isInitialized()) { return; } datapanel.refreshData(); panel.setDisplayPlot(true); panel.update(panel.getGraphics()); frame.setSize(700, 600); frame.setVisible(true); frame.pack(); } ActionListener getDataPanel() { return datapanel; } } class GraphicPanel extends JPanel { private boolean display_plot; private DataPanel d; public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setPaint(Color.black); g2d.setStroke(new BasicStroke()); g2d.setFont(new Font("Century Schoolbook", Font.PLAIN, 12)); if (d.isInitialized() && display_plot) { d.refreshData(); Float xLower = d.getXLower(); Float xUpper = d.getXUpper(); Float xInterval = d.getXInterval(); Float yLower = d.getYLower(); Float yUpper = d.getYUpper(); Float yInterval = d.getYInterval(); Float dx = xUpper - xLower; Float dy = yUpper - yLower; drawCenteredString(g2d, d.getTitle(), 250, 25, (float) 0.); drawCenteredString(g2d, d.getXTitle(), 250, 475, (float) 0.); drawCenteredString(g2d, d.getYTitle(), 25, 250, (float) -Math.PI / 2); drawCenteredString(g2d, xLower.toString(), 50, 475, (float) 0); drawCenteredString(g2d, xUpper.toString(), 450, 475, (float) 0); drawCenteredString(g2d, yLower.toString(), 25, 450, (float) 0); drawCenteredString(g2d, yUpper.toString(), 25, 50, (float) 0); g2d.setPaint(Color.gray); for (Float x = 50f; x <= 450; x += 400 * xInterval / dx) g2d.draw(new Line2D.Float(x, 450, x, 50)); for (Float y = 50f; y <= 450; y += 400 * yInterval / dy) g2d.draw(new Line2D.Float(45, y, 450, y)); g2d.setPaint(Color.red); Float diam = 8f; int num_points = d.getNumberOfPoints(); for (int i = 0; i < num_points; i++) { Float ex = 400 * (d.getPoint(i).x - xLower) / dx + 50; ex -= diam / 2; Float ey = -400 * (d.getPoint(i).y - yLower) / dy + 450; ey -= diam / 2; g2d.fill(new Ellipse2D.Float(ex, ey, diam, diam)); } } } void setDataPanel(DataPanel new_d) { d = new_d; } void setDisplayPlot(boolean new_display) { display_plot = new_display; } private void drawCenteredString(Graphics2D g2d, String string, int x0, int y0, float angle) { FontRenderContext frc = g2d.getFontRenderContext(); Rectangle2D bounds = g2d.getFont().getStringBounds(string, frc); LineMetrics metrics = g2d.getFont().getLineMetrics(string, frc); if (angle == 0) { g2d.drawString(string, x0 - (float) bounds.getWidth() / 2, y0 + metrics.getHeight() / 2); } else { g2d.rotate(angle, x0, y0); g2d.drawString(string, x0 - (float) bounds.getWidth() / 2, y0 + metrics.getHeight() / 2); g2d.rotate(-angle, x0, y0); } } } class DataPanel implements ActionListener { private boolean initialized; private int titleIndex, xTitleIndex, yTitleIndex; private int xLowerIndex, xUpperIndex, xIntervalIndex; private int yLowerIndex, yUpperIndex, yIntervalIndex; private JFrame frame; private JPanel panel; private String title; private String xTitle; private String yTitle; private float xLower, xUpper, xInterval; private float yLower, yUpper, yInterval; private Point2D.Float[] points; private JLabel[] paramLabels; private JTextField[] paramFields; private JTextField[] dataFields; DataPanel(JFrame newFrame) { initialized = false; titleIndex = 0; xTitleIndex = 1; xLowerIndex = 2; xUpperIndex = 3; xIntervalIndex = 4; yTitleIndex = 5; yLowerIndex = 6; yUpperIndex = 7; yIntervalIndex = 8; paramLabels = new JLabel[9]; paramLabels[titleIndex] = new JLabel("Title"); paramLabels[xTitleIndex] = new JLabel("X Axis Title"); paramLabels[yTitleIndex] = new JLabel("Y Axis Title"); paramLabels[xLowerIndex] = new JLabel("X lower bound"); paramLabels[xUpperIndex] = new JLabel("X upper bound"); paramLabels[xIntervalIndex] = new JLabel("X tick interval"); paramLabels[yLowerIndex] = new JLabel("Y lower bound"); paramLabels[yUpperIndex] = new JLabel("Y upper bound"); paramLabels[yIntervalIndex] = new JLabel("Y tick interval"); paramFields = new JTextField[9]; paramFields[titleIndex] = new JTextField("Test Title"); paramFields[xTitleIndex] = new JTextField("X"); paramFields[yTitleIndex] = new JTextField("Y"); paramFields[xLowerIndex] = new JTextField("0"); paramFields[xUpperIndex] = new JTextField("10"); paramFields[xIntervalIndex] = new JTextField("1"); paramFields[yLowerIndex] = new JTextField("0"); paramFields[yUpperIndex] = new JTextField("10"); paramFields[yIntervalIndex] = new JTextField("1"); frame = newFrame; panel = new JPanel(new FlowLayout()); frame.getContentPane().add(panel, "West"); } public void actionPerformed(ActionEvent e) { JFrame fileFrame = new JFrame(); JPanel filePanel = new JPanel(); JFileChooser fileChooser = new JFileChooser(); fileFrame.getContentPane().add(filePanel); filePanel.add(fileChooser); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); int result = fileChooser.showOpenDialog(filePanel); if (result != JFileChooser.APPROVE_OPTION) { JLabel msg = new JLabel("No file selected"); panel.add(msg); return; } File datafile = fileChooser.getSelectedFile(); initialized = readFile(datafile); panel.update(panel.getGraphics()); frame.pack(); frame.setVisible(true); } //数据文件包含两个部分。 //第一部分包含用于配置图形的参数。 //每行以单个单词标识符开头,后跟一个空格。 //该行的其余部分是值。 //它由包含单词“Data”的行终止。"Data". //第二部分包含将要绘制图形的数据对。 private boolean readFile(File datafile) { int numAllocated = 10; int numRead = 0; int numDataPoints = 0; String[] dataStrings = new String[numAllocated]; BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(datafile)); String text; while ((text = reader.readLine()) != null) { if (numRead >= numAllocated) { numAllocated = 2 * numAllocated; String[] temp = dataStrings; dataStrings = new String[numAllocated]; System.arraycopy(temp, 0, dataStrings, 0, numRead); } dataStrings[numRead] = text; numRead = numRead + 1; } } catch (FileNotFoundException e) { System.out.println("File not found"); } catch (IOException e) { System.out.println("IO Exception"); } try { if (reader != null) reader.close(); } catch (IOException e) { System.out.println("IO Exception on close"); } int thisCase = -2; int thisDataPoint = 0; for (int i = 0; i < numRead; i++) { String[] segments = dataStrings[i].split(" "); if (segments[0].equals("Title")) { thisCase = titleIndex; } else if (segments[0].equals("xTitle")) { thisCase = xTitleIndex; } else if (segments[0].equals("yTitle")) { thisCase = yTitleIndex; } else if (segments[0].equals("xLower")) { thisCase = xLowerIndex; } else if (segments[0].equals("xUpper")) { thisCase = xUpperIndex; } else if (segments[0].equals("xInterval")) { thisCase = xIntervalIndex; } else if (segments[0].equals("yLower")) { thisCase = yLowerIndex; } else if (segments[0].equals("yUpper")) { thisCase = yUpperIndex; } else if (segments[0].equals("yInterval")) { thisCase = yIntervalIndex; } else if (segments[0].equals("Data")) { thisCase = -1; numDataPoints = numRead - i - 1; dataFields = new JTextField[2 * numDataPoints]; points = new Point2D.Float[numDataPoints]; } else if (thisCase != -1) { thisCase = -2; } if (thisCase >= 0 && segments.length > 1) { StringBuilder temp = new StringBuilder(segments[1]); for (int j = 2; j < segments.length; j++) temp.append(" ").append(segments[j]); paramFields[thisCase].setText(temp.toString()); thisCase = -2; } else if (thisCase == -1 && !segments[0].equals("Data") && thisDataPoint < numDataPoints) { dataFields[2 * thisDataPoint] = new JTextField(segments[0]); dataFields[2 * thisDataPoint + 1] = new JTextField(segments[1]); thisDataPoint++; } } frame.getContentPane().remove(panel); panel = new JPanel(new GridLayout(9 + numDataPoints, 2)); for (int i = 0; i < 9; i++) { panel.add(paramLabels[i]); panel.add(paramFields[i]); } for (int i = 0; i < numDataPoints; i++) { panel.add(dataFields[2 * i]); panel.add(dataFields[2 * i + 1]); } frame.getContentPane().add(panel, "West"); return true; } //从面板读取数据,以防用户进行任何更改 void refreshData() { if (!initialized) { return; } title = paramFields[titleIndex].getText(); xTitle = paramFields[xTitleIndex].getText(); yTitle = paramFields[yTitleIndex].getText(); xLower = Float.parseFloat(paramFields[xLowerIndex].getText()); xUpper = Float.parseFloat(paramFields[xUpperIndex].getText()); xInterval = Float.parseFloat(paramFields[xIntervalIndex].getText()); yLower = Float.parseFloat(paramFields[yLowerIndex].getText()); yUpper = Float.parseFloat(paramFields[yUpperIndex].getText()); yInterval = Float.parseFloat(paramFields[yIntervalIndex].getText()); for (int i = 0; i < points.length; i++) { Float x = Float.parseFloat(dataFields[2 * i].getText()); Float y = Float.parseFloat(dataFields[2 * i + 1].getText()); points[i] = new Point2D.Float(x, y); } } boolean isInitialized() { return initialized; } String getTitle() { return title; } String getXTitle() { return xTitle; } String getYTitle() { return yTitle; } float getXLower() { return xLower; } float getXUpper() { return xUpper; } float getXInterval() { return xInterval; } float getYLower() { return yLower; } float getYUpper() { return yUpper; } float getYInterval() { return yInterval; } int getNumberOfPoints() { return points.length; } Point2D.Float getPoint(int i) { if (i < 0) { i = 0; } else if (i >= points.length) { i = points.length - 1; } return points[i]; } }
这是数据文件示例,您可以将其另存为test.txt。
Title Test String Xtitle X axis Ytitle Y axis Xlower 0 Xupper 10 Xinterval 1.0 Ylower 0 Yupper 10 Yinterval 1 Data 0 0 0.25 0.0625 0.5 0.25 0.75 0.5625 1 1 1.25 1.5625 1.5 2.25 1.75 3.0625 2 4 2.25 5.0625 2.5 6.25 2.75 7.5625 3 9 3.25 7.5625 3.5 6.25 3.75 5.0625 4.0 4 4.25 3.0625 4.5 2.25 4.75 1.5625 5.0 1 5.25 0.5625 5.5 0.25 5.75 0.0625 6 0
运行程序显示结果。