在我开始写答案之前,我需要鼓励您仔细阅读:如何创建有效的最小、完整且可验证的示例 https://stackoverflow.com/help/mcve and a 简短、独立、正确的示例 http://sscce.org/.
-
从你的(现已删除)代码中,我发现你还没有经历过Swing 自定义绘画教程 https://docs.oracle.com/javase/tutorial/uiswing/painting/然而或者你根本没有注意它,这条线会给你带来问题
static Graphics2D g = new Graphics2D()
过度使用static
修饰符会伤害你,static
不是一个跨方法的魔术词来使您的变量可以在程序中的任何位置访问,您应该创建程序的实例并从那里调用方法(它们不是静态的),请参阅为什么静态变量被认为是邪恶的? https://stackoverflow.com/questions/7026507/why-are-static-variables-considered-evil,你真的应该回去学习要点 https://docs.oracle.com/javase/tutorial/java/nutsandbolts/在使用 GUI 以及 Swing 自定义绘画为您的学习增加更多复杂性之前。
-
你正在利用setBounds()
方法,这表明(我可以在您删除的代码中确认)您正在使用null-layout
:
panel.setLayout(null);
你真的应该考虑检查布局管理器 https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
您正在使用已弃用的方法JFrame#show() https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#show()相反你应该使用JFrame#setVisible() https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#setVisible(boolean) method.
您正在手动设置尺寸JFrame
,您应该使用布局管理器并调用该方法JFrame#pack() https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#pack()这将计算您的首选尺寸JFrame
或覆盖你的组件的getPreferredSize()
.
在您删除的代码中,您有一个MouseListener
附于一个JButton
,相反你需要使用ActionListener
, see 如何使用动作 https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html学习这个。
-
你没有把你的程序放在事件调度线程 (EDT) https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html这可能会使您的程序冻结,因为 Swing 不是线程安全的。您可以通过编写您的main
方法如下:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Your constructor here
}
});
}
你应该更有礼貌:“更正我的代码,谢谢”听起来像是一个命令,我会这么说你可以帮帮我吗?这听起来像是请求某人帮助您,因为他们可以,而不是因为他们必须帮助您,以上所有要点都可以纠正您的代码。
说完上述所有内容(您应该仔细阅读),我们可以继续编码部分:
为了绘制矩形,我们需要了解一些关于矩形的知识:
- 矩形有宽度和高度,两者不同
- The way to draw a rectangle in Swing is with
drawRect(x, y, width, height) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#drawRect(int,%20int,%20int,%20int) draw(Shape) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#draw(java.awt.Shape) of the Graphics2D
method where Shape
would be an instance of Rectangle2D http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Rectangle2D.html
要绘制正方形,我们需要知道:
- 正方形有宽度和高度,两者大小相等
- The way to draw a square in Swing is with
drawRect(x, y, width, height) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#drawRect(int,%20int,%20int,%20int) draw(Shape) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#draw(java.awt.Shape) of the Graphics2D
method where Shape
would be an instance of Rectangle2D http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Rectangle2D.html
你一定是说...“但是你画正方形的方法和画长方形是一样的!”,嗯...是的,我们是,不同之处在于我们将通过一个width
and height
正方形大小相同,矩形大小不同。
要绘制三角形,您需要知道:
- 三角形有 3 条边,它们的大小可以相同或不同
- We have no method to
drawTriangle
in Swing, but we have drawPolygon(xPoints, yPoints, nPoints) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#drawPolygon(int%5B%5D,%20int%5B%5D,%20int) draw(Shape) https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#draw(java.awt.Shape) of the Graphics2D
method, which will draw a Polygon of nPoints
(3 in this case), taking the coords from each array element of xPoints
for the X
coords and yPoints
for the Y
coords and where Shape
would be an instance of Polygon https://docs.oracle.com/javase/7/docs/api/java/awt/Polygon.html
现在,将所有这些放在一起,我们应该将所有代码放在我们的重写方法中JPanel
called paintComponent() https://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)如教程中所示(参见第 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() https://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#getPreferredSize() on our JPanel
, (see: 我应该避免在 Swing 中使用 setPreferred|Maximum|MinimumSize 吗? https://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi普遍共识是肯定的),否则我们的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
and fillPolygon
代替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();
}
Edit
根据@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();
}
产生以下输出: