在我开始写我的答案之前,我需要鼓励您仔细阅读:如何创建一个有效的最小、完整和可验证的示例和一个简短、自包含、正确的示例。
从您(现已删除)的代码中,我看到您还没有完成自定义绘画的 Swing 教程,或者您甚至没有注意它,这行会导致您出现问题
static Graphics2D g = new Graphics2D()
过度使用static
修饰符会伤害你,static
不是一个跨方法的魔法词,可以让你的变量在程序的任何地方都可以访问,你应该创建一个程序实例并从那里调用方法(它们不是静态的) ,请参阅为什么静态变量被认为是邪恶的?,并且在使用 GUI 为您的学习增加更多复杂性之前,您应该真正回去学习基本知识,甚至使用 Swing 自定义绘画增加更多复杂性。
您正在使用setBounds()
方法,这表明(我可以在您删除的代码中确认)您正在使用null-layout
:
panel.setLayout(null);
你真的应该考虑检查布局管理器
您正在使用不推荐使用的方法,JFrame#show()
而不是应该使用JFrame#setVisible()
方法。
您正在JFrame
手动设置.JFrame#pack()
JFrame
getPreferredSize()
在您删除的代码中,您MouseListener
附加了 a JButton
,而您需要使用 a ActionListener
,请参阅如何使用操作来了解这一点。
您没有将程序放在可能使您的程序冻结的事件调度线程 (EDT)上,因为 Swing 不是线程安全的。您可以通过main
如下编写方法来纠正此问题:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Your constructor here
}
});
}
你应该更有礼貌:“更正我的代码,谢谢”听起来像是命令,我会说你能帮我吗?这听起来像是请求/请愿某人帮助您,因为他们可以,而不是因为他们必须帮助您,以上所有要点都可以更正您的代码。
说了以上所有内容(您应该仔细阅读),我们可以继续编码部分:
为了画一个矩形,我们需要学习一些关于矩形的知识:
要画一个正方形,我们需要知道:
你一定是在说…… “但是你画正方形的方法和画矩形的方法是一样的!” ,嗯...是的,我们是,不同之处在于我们将为正方形传递一个相等的大小,width
而height
为矩形传递不同的大小。
要绘制三角形,您需要知道:
现在,将所有这些放在一起,我们应该将所有代码放在我们JPanel
调用的重写方法中paintComponent()
,如教程中所示(参见第 1 点)。它应该如下所示:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //ALWAYS call this method first!
g.drawRect(10, 10, 50, 50); //Draws square
g.drawRect(10, 75, 100, 50); //Draws rectangle
g.drawPolygon(new int[] {35, 10, 60}, new int[] {150, 200, 200}, 3); //Draws triangle
}
但是我们还需要覆盖getPreferredSize()
我们的另一个方法JPanel
,(请参阅:我应该避免在 Swing 中使用 setPreferred|Maximum|MinimumSize 吗?普遍的共识是肯定的),否则我们JFrame
将小于我们想要的,所以它应该看起来像这:
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
不要忘记调用@Override
这些方法!
仅使用这些方法,我们就完成了绘制形状的程序,但是我知道,如果我不发布整个代码,您最终会将上述方法编写在一个不起作用或导致编译错误的地方,因此产生以下输出的整个代码(实际上是 MCVE 或 SSCCE(请参阅此答案中的第一段以了解每个代码的含义))是:

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapesDrawing {
private JFrame frame;
private JPanel pane;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ShapesDrawing().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
pane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //ALWAYS call this method first!
g.drawRect(10, 10, 50, 50); //Draws square
g.drawRect(10, 75, 100, 50); //Draws rectangle
g.drawPolygon(new int[] {35, 10, 60}, new int[] {150, 200, 200}, 3); //Draws triangle
g.dispose();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
我真的希望你阅读我在这里发布的每个链接,因为它是值得的
如果您需要填充形状,请调用fillRect
andfillPolygon
而不是drawRect
and drawPolygon
:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //ALWAYS call this method first!
g.drawRect(10, 10, 50, 50); //Draws square
g.fillRect(150, 10, 50, 50); //Fills a square
g.drawRect(10, 75, 100, 50); //Draws rectangle
g.fillRect(150, 70, 100, 50); //Fills a square
g.drawPolygon(new int[] {35, 10, 60}, new int[] {150, 200, 200}, 3); //Draws triangle
g.fillPolygon(new int[] {185, 150, 215}, new int[] {150, 200, 200}, 3); //Fills triangle
g.dispose();
}

编辑
根据@MadProgrammer 的评论:
我们是否可以避免使用draw/fillPolygon
更新的 Shapes API 来支持...提供更多功能并且通常更易于使用:P
这是paintComponent
使用 Shapes API 的更新方法:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //ALWAYS call this method first!
Graphics2D g2d = (Graphics2D) g;
g2d.draw(new Rectangle2D.Double(10, 10, 50, 50));
g2d.fill(new Rectangle2D.Double(150, 10, 50, 50));
g2d.draw(new Rectangle2D.Double(10, 75, 100, 50));
g2d.fill(new Rectangle2D.Double(150, 75, 100, 50));
g2d.draw(new Polygon(new int[] {35, 10, 60}, new int[] {150, 200, 200}, 3));
g2d.fill(new Polygon(new int[] {185, 150, 215}, new int[] {150, 200, 200}, 3));
g2d.dispose();
g.dispose();
}
这会产生以下输出:
