我正在撰寫一個用于資料處理的 Java Swing 應用程式。我需要添加的功能之一是以圖形方式可視化資料。為此,我想使用 Graphics2D 類。
我創建了一個 GUI,集成了我的程式以及一個使用 Graphics2D 類繪制圖形的面板。
但我的問題是我不知道如何在從 GUI 選擇和加載檔案后呼叫 drawLine 方法
下面是簡短的代碼示例,顯示了我的問題。它只包含一個帶有 2 個面板的基本 GUI 和一個帶有加載選項的選單來解釋我的問題:
在 de MyFrame.java 檔案中,我在第 87 行添加了一條注釋,以準確顯示卡住的位置。
該應用程式基于 3 個檔案: main:在這里它創建 GUI 的 MyFrame 的實體 Myframe:創建 GUI 和資料的進一步處理 MyPanel:使用基本的藍色矩形框架作為開始視圖制作 Graphics2D 的 Jpanel。
如果有人能給我一個關于如何從 MyFrame() 建構式外部呼叫這個 drawLine 方法的提示......
我仍然不完全理解如何在類之間進行互動的全部要點......
這是 GUI 外觀的圖片:

謝謝你在這方面幫助我
public class main {
public static void main(String[] args) {
new MyFrame();
}
}
- MyFrame.java:
public class MyFrame extends JFrame {
JTextComponent tc;
String fileName;
MyFrame() {
this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
this.setLayout(null);
this.setBounds(0,0,464,312);
tc = new JTextPane();
tc.setBounds(0,520,450,50);
tc.setPreferredSize(new Dimension(450,50));
JScrollPane sp = new JScrollPane(tc);
JMenuBar mb = new JMenuBar();
JMenu fm = new JMenu("File");
JMenuItem loadItem = new JMenuItem("Load file");
loadItem.addActionListener(e -> {tc.setText("loading" "\n");
SDprocess();});
fm.add(loadItem);
mb.add(fm);
MyPanel p1 = new MyPanel();
p1.setBounds(0,0,450,200);
p1.setPreferredSize(new Dimension(450,200));
JPanel p2 = new JPanel();
p2.setBounds(0,200,450,50);
p2.setPreferredSize(new Dimension(450,50));
p2.add(sp);
this.setJMenuBar(mb);
this.add(p1);
this.add(p2);
this.setResizable(false);
this.setVisible(true);
}
public void SDprocess() {
File fr = null;
JFileChooser fc = new JFileChooser();
int result = fc.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
fr = fc.getSelectedFile();
fileName=fr.getName();
System.out.println(fileName);
}
try {
Scanner sc = new Scanner(fr);
tc.setText(fileName " loading\n");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// ...
// rest of code to get the x and y data for drawing
// lines using drawLine(x1,y1,x2,y2) method.
//
// at this point I need to call this drawLine method but how ???
// i just don't know how to call this method from this point and how to
// and update the graphics panel p1 after adding the data....
}
sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 我的面板.java:
public class MyPanel extends JPanel {
Graphics2D g2D;
MyPanel() {
this.setPreferredSize(new Dimension (450,200));
}
public void paint (Graphics g) {
g2D = (Graphics2D) g;
g2D.setStroke(new BasicStroke(1));
g2D.setPaint(Color.blue);
g2D.drawLine(5, 5, 445,5);
g2D.drawLine(445, 5, 445,195);
g2D.drawLine(445, 195, 5,195);
g2D.drawLine(5, 195, 5,5);
}
}
uj5u.com熱心網友回復:
Oracle 有一個有用的教程,
這是“讀取檔案”后修改后的 GUI。

我創建了一個應用程式模型來保存線段。將此模型傳遞給繪圖,JPanel以便可以在繪圖的paintComponent方法中繪制線段JPanel。
我清理了你的 GUI。我使用Swing 布局管理器來創建 GUI。我將 the 的創建與 theJPanels的創建分開,JFrame因此代碼更易于人們閱讀和理解。
這是完整的可運行代碼。我創建了額外的類內部類,所以我可以將此代碼作為一個塊發布。
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
public class ExampleDrawingGUI {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new ExampleDrawingGUI().new MyFrame());
}
public class MyFrame extends JFrame {
private static final long serialVersionUID = 1L;
private ExampleDrawingModel model;
JTextComponent tc;
MyPanel p1;
public MyFrame() {
super("My Frame");
this.model = new ExampleDrawingModel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setJMenuBar(createMenuBar());
p1 = new MyPanel(model);
this.add(p1, BorderLayout.CENTER);
this.add(createTextPanel(), BorderLayout.SOUTH);
this.pack();
this.setLocationByPlatform(true);
// this.setResizable(false);
this.setVisible(true);
}
private JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenu fm = new JMenu("File");
JMenuItem loadItem = new JMenuItem("Load file");
loadItem.addActionListener(e -> {
tc.setText("loading" "\n");
model.readFile();
p1.repaint();
});
fm.add(loadItem);
mb.add(fm);
return mb;
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
tc = new JTextPane();
tc.setPreferredSize(new Dimension(450, 50));
JScrollPane sp = new JScrollPane(tc);
panel.add(sp, BorderLayout.CENTER);
return panel;
}
public void repaint() {
p1.repaint();
}
}
public class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ExampleDrawingModel model;
public MyPanel(ExampleDrawingModel model) {
this.model = model;
this.setPreferredSize(new Dimension(450, 200));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
paintBorder(g2D);
for (LineSegment line : model.getLines()) {
Point startPoint = line.getStartPoint();
Point endPoint = line.getEndPoint();
g2D.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
}
}
private void paintBorder(Graphics2D g2D) {
int margin = 5;
int x1 = margin;
int x2 = getWidth() - margin;
int y1 = margin;
int y2 = getHeight() - margin;
g2D.setStroke(new BasicStroke(3f));
g2D.setPaint(Color.blue);
g2D.drawLine(x1, y1, x1, y2);
g2D.drawLine(x1, y1, x2, y1);
g2D.drawLine(x2, y1, x2, y2);
g2D.drawLine(x1, y2, x2, y2);
}
}
public class ExampleDrawingModel {
private List<LineSegment> lines;
public ExampleDrawingModel() {
this.lines = new ArrayList<>();
}
public void readFile() {
this.lines.clear();
// Here's where you'd read a file and create a list of lines.
lines.add(new LineSegment(new Point(100, 100), new Point(100, 150)));
}
public List<LineSegment> getLines() {
return lines;
}
}
public class LineSegment {
private final Point startPoint, endPoint;
public LineSegment(Point startPoint, Point endPoint) {
this.startPoint = startPoint;
this.endPoint = endPoint;
}
public Point getStartPoint() {
return startPoint;
}
public Point getEndPoint() {
return endPoint;
}
}
}
uj5u.com熱心網友回復:
首先,您的代碼存在一些問題:
class MyFrame extends JFrame {
//....
MyFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null); // !! Good God, no don't do this!
this.setBounds(0, 0, 464, 312); // and don't do this
避免像瘟疫一樣使用空布局和 setBounds,因為這會導致 GUI 非常不靈活,雖然它們在一個平臺上看起來不錯,但在大多數其他平臺或螢屏解析度上看起來很糟糕,并且很難更新和維護。相反,您將想要研究和學習布局管理器,然后嵌套 JPanel,每個 JPanel 使用自己的布局管理器來創建在所有作業系統上看起來都不錯的令人愉悅且復雜的 GUI。
另外,不要忘記在添加組件之后和設定可見之前呼叫pack()你的 JFrame ,以便布局管理器做他們的事情。
接著:
class MyPanel extends JPanel {
// ...
Graphics2D g2D; //!! -- no, don't do this
如果您創建 Graphics 或 Graphics2D 欄位,您很想在繪制方法之外使用它,這是災難性的,因為從組件獲得的任何 Graphics 都是短暫的,并且這樣做有創建脆弱圖形或拋出 NullPointerException 的風險
public void paint (Graphics g) {
g2D = (Graphics2D) g;
g2D.setStroke(new BasicStroke(1));
g2D.setPaint(Color.blue);
g2D.drawLine(5, 5, 445,5);
g2D.drawLine(445, 5, 445,195);
g2D.drawLine(445, 195, 5,195);
g2D.drawLine(5, 195, 5,5);
}
不要覆寫paint,而是覆寫paintComponent,因為這風險較小(paint 具有更大的責任,您不想弄亂)并且如果需要更平滑的影片,因為paintComponent 默認使用雙緩沖。
此外,您幾乎總是應該在自己的覆寫中呼叫 super 的繪制方法,因此請執行以下操作:
@Override
protected void paintComponent(Graphics g) {
// first call the super's method:
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g.create();
現在至于您的實際問題,在渲染 GUI 之后創建影像和繪圖,可能最簡單的方法是創建一個 BufferedImage 并在您的 GUI 中使用它進行繪制。您可以通過呼叫 Graphics 方法輕松完成此操作drawImage(...)。您可以隨時將 BufferedImage 傳遞到您的繪圖 JPanel 中。例如,您的代碼可能看起來像……
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Foo {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MainPanel mainPanel = new MainPanel();
MyMenu myMenu = new MyMenu();
myMenu.setMyPanel(mainPanel.getMyPanel());
myMenu.setMainPanel(mainPanel);
frame.add(mainPanel);
frame.setJMenuBar(myMenu);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class MainPanel extends JPanel {
private static final int GAP = 5;
private JTextArea textArea = new JTextArea(4, 40);
private MyPanel myPanel = new MyPanel();
public MainPanel() {
textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(myPanel);
add(scrollPane, BorderLayout.PAGE_END);
}
public MyPanel getMyPanel() {
return myPanel;
}
public void appendTextAreaText(String text) {
textArea.append(text);
}
public void setBuffImg(BufferedImage bImage) {
myPanel.setBuffImg(bImage);
}
}
class MyMenu extends JMenuBar {
private MainPanel mainPanel;
private MyPanel myPanel;
public MyMenu() {
JMenu fm = new JMenu("File");
JMenuItem loadItem = new JMenuItem("Load file");
loadItem.addActionListener(e -> {
// Emulate reading file here in a background thread
if (myPanel != null) {
int width = MyPanel.MY_WIDTH;
int height = MyPanel.MY_HEIGHT;
BufferedImage bImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bImg.createGraphics();
// draw with g2 here using data from file
// emulating this:
g2.setColor(Color.RED);
float strokeWidth = (float) (2 6 * Math.random());
g2.setStroke(new BasicStroke(strokeWidth));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int x2 = (int) (MyPanel.MY_WIDTH * (1 Math.random()) / 2);
int y2 = (int) (MyPanel.MY_HEIGHT * (1 Math.random()) / 2);
g2.drawLine(5, 5, x2, y2);
g2.dispose();
myPanel.setBuffImg(bImg);
if (mainPanel != null) {
mainPanel.appendTextAreaText("adding image \n");
}
}
});
fm.add(loadItem);
add(fm);
}
public void setMyPanel(MyPanel myPanel) {
this.myPanel = myPanel;
}
public void setMainPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
}
}
class MyPanel extends JPanel {
private static final int GAP = 5;
public static final int MY_WIDTH = 450;
public static final int MY_HEIGHT = 200;
private BufferedImage bImg = null;
// Graphics2D g2D; //!! -- no, never do this!!
MyPanel() {
// this.setPreferredSize(new Dimension(450, 200));
setBackground(Color.WHITE);
}
// better to override getPreferredSize
@Override
public Dimension getPreferredSize() {
return new Dimension(MY_WIDTH 2 * GAP, MY_HEIGHT 2 * GAP);
}
public void setBuffImg(BufferedImage bImg) {
this.bImg = bImg;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
// first call the super's method:
super.paintComponent(g);
if (bImg != null) {
g.drawImage(bImg, GAP, GAP, null);
}
Graphics2D g2D = (Graphics2D) g.create();
g2D.setStroke(new BasicStroke(1));
g2D.setPaint(Color.blue);
Rectangle rect = new Rectangle(GAP, GAP, getWidth() - 2 * GAP, getHeight() - 2 * GAP);
g2D.draw(rect);
}
// Don't override paint but rather paintComponent
// public void paint (Graphics g) {
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/396223.html
