求助:开发读取文件坐标并绘制直线的Java GUI应用
Let's Get Your Line-Drawing GUI Working!
Hey there! I can see you've made a solid start with your Line JPanel, but there are a few key fixes and additions needed to get this app reading files and drawing lines correctly. Let's break this down step by step:
1. Fix the paintComponent Loop
Right now, your loop is trying to draw lines using the same index four times—this won't create actual lines between distinct points. Since each line needs four integers (x1, y1, x2, y2), you should iterate through your points list in steps of 4, grabbing a full set of coordinates each time:
@Override public void paintComponent(Graphics g) { super.paintComponent(g); // Always call this first to clear the panel properly Graphics2D g2d = (Graphics2D) g; // Iterate 4 elements at a time (one complete line per group) for (int i = 0; i < points.size(); i += 4) { // Make sure we don't go out of bounds if the list has an odd number of elements if (i + 3 < points.size()) { int x1 = points.get(i); int y1 = points.get(i + 1); int x2 = points.get(i + 2); int y2 = points.get(i + 3); g2d.drawLine(x1, y1, x2, y2); } } }
Note: Calling super.paintComponent(g) is non-negotiable—it ensures the panel clears old lines before redrawing, preventing messy overlaps.
2. Add File Reading Functionality
Next, we need to let users select a file, parse each line of coordinates, and populate the points list. We'll use JFileChooser for file selection and BufferedReader to handle parsing safely:
Add this method to a main class (or a controller) to handle loading files:
private void loadCoordinatesFromFile(Line linePanel) { JFileChooser fileChooser = new JFileChooser(); int result = fileChooser.showOpenDialog(null); if (result == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooser.getSelectedFile(); ArrayList<Integer> newPoints = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(selectedFile))) { String line; while ((line = br.readLine()) != null) { // Split lines by commas and trim any extra whitespace String[] coords = line.trim().split(","); if (coords.length == 4) { // Ensure we have exactly 4 values per line try { int x1 = Integer.parseInt(coords[0].trim()); int y1 = Integer.parseInt(coords[1].trim()); int x2 = Integer.parseInt(coords[2].trim()); int y2 = Integer.parseInt(coords[3].trim()); newPoints.add(x1); newPoints.add(y1); newPoints.add(x2); newPoints.add(y2); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Skipping invalid number in line: " + line); } } else { JOptionPane.showMessageDialog(null, "Skipping invalid line format: " + line + "\nExpected format: x1,y1,x2,y2"); } } } catch (IOException e) { JOptionPane.showMessageDialog(null, "Error reading file: " + e.getMessage()); } // Update the panel's points and trigger a repaint to show new lines linePanel.points = newPoints; linePanel.repaint(); } }
3. Full Working Code
Here's the complete app that combines the Line panel, file loading, and a user-friendly main window with a button to trigger file selection:
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; public class LineDrawingApp extends JFrame { private Line linePanel; public LineDrawingApp() { setTitle("Line Drawing from File"); setSize(800, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); // Create the panel where lines will be drawn linePanel = new Line(); add(linePanel, BorderLayout.CENTER); // Add a button to load coordinate files JButton loadButton = new JButton("Load Coordinates File"); loadButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loadCoordinatesFromFile(linePanel); } }); add(loadButton, BorderLayout.NORTH); } private void loadCoordinatesFromFile(Line linePanel) { JFileChooser fileChooser = new JFileChooser(); int result = fileChooser.showOpenDialog(null); if (result == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooser.getSelectedFile(); ArrayList<Integer> newPoints = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(selectedFile))) { String line; while ((line = br.readLine()) != null) { String[] coords = line.trim().split(","); if (coords.length == 4) { try { int x1 = Integer.parseInt(coords[0].trim()); int y1 = Integer.parseInt(coords[1].trim()); int x2 = Integer.parseInt(coords[2].trim()); int y2 = Integer.parseInt(coords[3].trim()); newPoints.add(x1); newPoints.add(y1); newPoints.add(x2); newPoints.add(y2); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, "Skipping invalid number in line: " + line); } } else { JOptionPane.showMessageDialog(null, "Skipping invalid line format: " + line); } } } catch (IOException ex) { JOptionPane.showMessageDialog(null, "Failed to read file: " + ex.getMessage()); } linePanel.points = newPoints; linePanel.repaint(); } } public static void main(String[] args) { // Launch the GUI safely on Swing's Event Dispatch Thread SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new LineDrawingApp().setVisible(true); } }); } // Modified Line panel class static class Line extends JPanel { ArrayList<Integer> points = new ArrayList<>(); public Line() { // Optional sample line for testing points.add(20); points.add(40); points.add(250); points.add(40); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; for (int i = 0; i < points.size(); i += 4) { if (i + 3 < points.size()) { int x1 = points.get(i); int y1 = points.get(i + 1); int x2 = points.get(i + 2); int y2 = points.get(i + 3); g2d.drawLine(x1, y1, x2, y2); } } } } }
Quick Tips
- Swing Thread Safety: We use
SwingUtilities.invokeLaterto launch the GUI—this is the correct way to avoid bugs with Swing components. - Error Handling: The code skips invalid lines/numbers instead of crashing, making it more robust for real-world files.
- Testing: The
Lineconstructor includes a sample line so you can see it working immediately before loading a file.
Just compile and run this code, click the "Load Coordinates File" button, select your coordinate file, and it will draw all your lines!
内容的提问来源于stack exchange,提问作者user9139039

