在 JFrame 上绘制画布 [英] Drawing Canvas on JFrame

查看:58
本文介绍了在 JFrame 上绘制画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用 Canvas 绘制简单的形状,在这个类中我已经设置了绘画

公共类游戏扩展画布{//字段公共 int 宽度 = 1024;公共 int 高度 = 宽度/16 * 9;//方法公共无效开始(){维度大小 = 新维度 (WIDTH, HEIGHT);setPreferredSize(大小);油漆(空);}公共无效油漆(图形g){g.setColor(Color.GREEN);g.fillRect(0, 0, WIDTH, HEIGHT);g.setColor(Color.BLACK);g.fillOval(100, 100, 30, 30);}}

在这个窗口中

公共类 MainW {公共静态无效主要(字符串[]参数){游戏 ga = 新游戏();JFrame 框架 = 新的 JFrame ();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLocationRelativeTo(null);框架.add(ga);frame.setVisible(true);ga.start();}}

它可以工作,但 JFrame 不适应 Canvas.我必须手动调整窗口大小才能看到对象.如何打包它以便 JFrame 自动包含 Canvas?

这真的很奇怪.虽然 frame.pack() 确实是必不可少的,但这还不够.我所做的是更改 start 方法并将其变成构造函数,如下所示:

 公共类游戏扩展画布{//字段公共 int 宽度 = 1024;公共 int 高度 = 宽度/16 * 9;//方法公共无效游戏(){维度大小 = 新维度 (WIDTH, HEIGHT);setPreferredSize(大小);}

然后,在另一个类中,Eclipse 抱怨直接调用构造函数(例如 ga.Game),所以我按照它的提示更改为:

 public static void main(String[] args) {游戏 ga = 新游戏();JFrame 框架 = 新的 JFrame ();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLocationRelativeTo(null);框架.add(ga);frame.setVisible(true);ga.getName();}

这样我实现了我的想法,但我真的不知道为什么我不能调用构造函数.

解决方案

我不知道你想做什么,但你不应该调用 paint 尤其是不通过它 null.

首先查看

I'm trying to draw simple shapes with Canvas, in this class I've set the painting

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);
    }
}

And in this the Window

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();

    }

}

It works, but the JFrame is not adapting to the Canvas. I have to manually resize the window to see the objects. How can I pack it so that JFrame automatically encompasses the Canvas?

EDIT: That's really weird. While frame.pack() is indeed essential, it's not enough. What I did was change the start method and turn it into a constructor, like that:

    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);
    }

then, from the other class, Eclipse complained about calling the constructor directly(E.G. ga.Game), so I followed it's tip and changed to:

    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();

    }

This way I achieve what I have in mind but I really don't know why I can't call the constructor.

解决方案

I don't know what it is you're trying to do, but you should NEVER be calling paint and especially not pass it null.

Start by taking a look at Performing Custom Painting and Painting in AWT and Swing for details about how painting works.

In order to get the window to size to you component, you need to provide it some important information.

While Window#pack is the method you are looking for, it will not help you unless you provide appropriate sizing hints.

In this case, you need to override the getPreferredSize method of you component and provide an appropriate size value. Window#pack will use this value to determine what size it needs to be in order to accommodate it.

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);
        }
    }
}

The paint chain is very important and you should avoid breaking it at all coasts. Make sure you always call super.paintXxx or be prepared for some serious weirdness

Also may want to have a read of Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?

这篇关于在 JFrame 上绘制画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆