Java Swing绘图应用程序没有绘图

时间:2014-04-07 10:53:26

标签: java swing

我目前正在使用Swing库在Java中编写一个简单的绘画应用程序。一切似乎都运行正常 - mousePressed和mouseDragged都被调用 - 但程序不会在绘图板上绘制任何东西。如果有人能告诉我为什么没有在这里得到任何东西,我会很高兴。

代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PaintGUI extends JComponent {

    private static final long serialVersionUID = 1L;

    JButton red, green, blue, clear;
    Image img;
    Graphics2D gfx;
    JFrame drawFrame;
    JPanel drawPan;
    Container cont;
    MyListener ml;
    Action act;
    int x, y, prevX, prevY;

    public PaintGUI(){
        //Initialisering av panel, frame og content
        drawFrame = new JFrame("IFIPaint");
        drawPan = new JPanel();
        cont = drawFrame.getContentPane();
        cont.setLayout(new BorderLayout());
        cont.add(BorderLayout.SOUTH, drawPan);

        //Setter størrelser
        drawPan.setPreferredSize(new Dimension(30, 60));
        drawPan.setMinimumSize(new Dimension(30, 60));
        drawPan.setMaximumSize(new Dimension(30, 60));

        //Ordner knappene
        red = new JButton("Rød");
        green = new JButton("Grønn");
        blue = new JButton("Blå");
        clear = new JButton("Slett alt");

        //Putter knappene på panelet
        drawPan.add(red);
        drawPan.add(green);
        drawPan.add(blue);
        drawPan.add(clear);

        //Legger på action listeners
        act = new Action();
        red.addActionListener(act);
        green.addActionListener(act);
        blue.addActionListener(act);
        clear.addActionListener(act);

        //Fullfører vindu og setter synlighet
        drawPan.setVisible(true);
        drawFrame.setSize(500, 500);
        drawFrame.setVisible(true);
        drawFrame.add(this);
        this.setSize(500, 500);
        this.paintComponent(gfx);
        this.setVisible(true);

        drawFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        draw();
    }

    public void draw() {
        ml = new MyListener();
        this.addMouseListener(ml);
        this.addMouseMotionListener(ml);
    }

    public void paintComponent(Graphics g) {

        if (img == null) {
            img = createImage(drawFrame.getWidth(),drawFrame.getHeight());

            gfx = (Graphics2D) img.getGraphics();

            gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

            gfx.setPaint(Color.WHITE);
            gfx.fillRect(0, 0, this.getSize().width, this.getSize().height);
            gfx.setPaint(Color.RED);
            repaint();
        }

        gfx.drawImage(img, 0, 0, null);
    }


    class Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == red){
                gfx.setPaint(Color.RED);
                repaint();
            } else if (e.getSource() == green){
                gfx.setPaint(Color.GREEN);
                repaint();
            } else if (e.getSource() == blue) {
                gfx.setPaint(Color.BLUE);
                repaint();
            } else if (e.getSource() == clear) {
                gfx.clearRect(0, 0, drawFrame.getWidth(), drawFrame.getHeight());
                repaint();
            }
        }

    }

    class MyListener extends MouseAdapter {

        public void mousePressed(MouseEvent e) {
            prevX = e.getX();
            prevY = e.getY();
        }

        public void mouseDragged(MouseEvent e) {
            x = e.getX();
            y = e.getY();
            gfx.drawLine(prevX, prevY, x, y);
            repaint();
            prevX = x;
            prevY = y;

        }
    }

}

3 个答案:

答案 0 :(得分:1)

不要在任何绘制方法中直接或间接调用repaint,这样做会导致新的绘制事件一次又一次地安排到事件队列中,从而快速占用CPU。

你实际上并没有在屏幕设备上绘画,为了做到这一点,你需要绘制到提供的Graphics上下文

protected void paintComponent(Graphics g) {

    if (img == null) {
        img = createImage(drawFrame.getWidth(),drawFrame.getHeight());

        gfx = (Graphics2D) img.getGraphics();

        gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        gfx.setPaint(Color.WHITE);
        gfx.fillRect(0, 0, this.getSize().width, this.getSize().height);
        gfx.setPaint(Color.RED);
        // If you create it you should dispose of it...
        gfx.dispose();
    }

    g.drawImage(img, 0, 0, this);
}

因为默认情况下使用JComponent是透明的,所以调用super.paintComponent更为重要,如果你不这样做,你最终会得到各种令人讨厌的油漆工件

将组件添加到同一个绘图表面上的事实意味着您可能会模糊绘制的内容。请记住,并非所有组件都是透明的,JPanel默认情况下是不透明的。

一个更好的解决方案是创建一个专门的绘图面板,除了你想要的方式之外什么都不做,只是画出你想要的东西。然后将其与控件一起添加到另一个容器中。然后,您将使用setter来更改绘画的发生方式,例如使用颜色

您似乎正在尝试采用双缓冲方法。将缓冲区的绘制与组件的绘制分开可能更容易,这将允许您以任何方式修改缓冲区,然后调用重绘,这将简单地将图像绘制到组件Graphics上下文

答案 1 :(得分:0)

首先,在paint组件方法中调用super。

没有绘制任何内容的原因是,使用此代码时,如果目前没有图像,则只更新要绘制的图像。我会将paintComponent方法改为:

public void paintComponent(Graphics g) {

    super.paintComponent(g);

    img = createImage(drawFrame.getWidth(),drawFrame.getHeight());
    gfx = (Graphics2D) img.getGraphics();
    gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    gfx.setPaint(Color.WHITE);
    gfx.fillRect(0, 0, this.getSize().width, this.getSize().height);
    gfx.setPaint(Color.RED);

    gfx.drawImage(img, 0, 0, null);
}

答案 2 :(得分:0)

似乎drawPan阻碍了您看到图像。

删除其内容窗格的创建和添加。