我正在尝试用Canvas绘制简单的形状,在这个类中我设置了绘画
public class Game extends Canvas{
//FIELDS
public int WIDTH = 1024;
public int HEIGHT = WIDTH / 16 * 9;
//METHODS
public void start(){
Dimension size = new Dimension (WIDTH, HEIGHT);
setPreferredSize(size);
paint(null);
}
public void paint(Graphics g){
g.setColor(Color.GREEN);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillOval(100, 100, 30, 30);
}
}
在这个窗口
public class MainW {
public static void main(String[] args) {
Game ga = new Game();
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(ga);
frame.setVisible(true);
ga.start();
}
}
它可以工作,但JFrame不适应Canvas。我必须手动调整窗口大小才能看到对象。如何打包它以便JFrame自动包含Canvas?
编辑: 这真的很奇怪。虽然frame.pack()确实很重要,但还不够。 我所做的是更改start方法并将其转换为构造函数,如:
public class Game extends Canvas{
//FIELDS
public int WIDTH = 1024;
public int HEIGHT = WIDTH / 16 * 9;
//METHODS
public void Game(){
Dimension size = new Dimension (WIDTH, HEIGHT);
setPreferredSize(size);
}
然后,从另一个类开始,Eclipse抱怨直接调用构造函数(E.G.ga.Game),所以我按照它的提示改为:
public static void main(String[] args) {
Game ga = new Game();
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(ga);
frame.setVisible(true);
ga.getName();
}
这样我实现了我的想法,但我真的不知道为什么我不能调用构造函数。
答案 0 :(得分:5)
我不知道你要做的是什么,但你永远不应该打电话给paint
,特别是不要传递它null
。
首先查看Performing Custom Painting和Painting in AWT and Swing,了解有关绘画如何运作的详细信息。
为了使窗口适合您的组件,您需要提供一些重要信息。
虽然Window#pack
是您要查找的方法,但除非您提供适当的大小提示,否则它不会对您有所帮助。
在这种情况下,您需要覆盖组件的getPreferredSize
方法并提供适当的大小值。 Window#pack
将使用此值来确定容纳它所需的大小。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPaint {
public static void main(String[] args) {
new TestPaint();
}
public TestPaint() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillOval(100, 100, 30, 30);
}
}
}
油漆链非常重要,你应该避免在所有海岸都破坏油漆链。确保你总是打电话给super.paintXxx
或者为一些严重的怪异做好准备
也可能想要阅读Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
答案 1 :(得分:2)
使用java.awt.Window.pack
(JFrame
间接延伸Window
):
使此窗口的大小适合其子组件的首选大小和布局。
// ...
frame.add(ga);
frame.pack();
frame.setVisible(true);
// ...
答案 2 :(得分:0)
在画布上绘画后,尝试重新绘制JFrame
public static void main(String[] args) {
Game ga = new Game();
JFrame frame = new JFrame ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(ga);
frame.setVisible(true);
ga.start();
//repaint here
frame.repaint();
}
另请注意:
frame.pack
用于解决尺寸问题。
frame.revalidate
有时会有所帮助。