【问题标题】:How to draw in JPanel? (Swing/graphics Java)如何在 JPanel 中绘图? (摇摆/图形Java)
【发布时间】:2011-09-01 09:39:27
【问题描述】:

我正在做一个项目,我正在尝试制作一个绘画程序。 到目前为止,我已经使用 Netbeans 创建了 GUI 并设置了程序。

到目前为止,我可以调用所有必要的协调来在其中绘制,但我对如何在其中实际绘制感到非常困惑。

在我的代码接近尾声时,我尝试在面板内绘图失败。

谁能解释/展示如何在这样的示例中使用图形?

我发现的所有示例都创建了一个类并使用JPanel 扩展它,但我不知道我是否可以这样做,因为它是在 netbeans 中生成的。

我需要在JPanel 内,在我的JFrame 内绘图。我不知道把图形类放在哪里。

JavaPaintUI 类

package javapaint;

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

public class JavaPaintUI extends javax.swing.JFrame {

public JavaPaintUI() {
    initComponents();
}


private void initComponents() {


    jPanel2 = new javax.swing.JPanel();

    jPanel2.setBackground(new java.awt.Color(255, 255, 255));
    jPanel2.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
    jPanel2.addMouseListener(new java.awt.event.MouseAdapter() {
        public void mousePressed(java.awt.event.MouseEvent evt) {
            jPanel2MousePressed(evt);
        }
        public void mouseReleased(java.awt.event.MouseEvent evt) {
            jPanel2MouseReleased(evt);
        }
    });
    jPanel2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
        public void mouseDragged(java.awt.event.MouseEvent evt) {
            jPanel2MouseDragged(evt);
        }
    });
    pack();
}// </editor-fold>                        

int currentX, currentY, oldX, oldY;

private void jPanel2MouseDragged(java.awt.event.MouseEvent evt) {                                     
    if (tool == 1) {
        currentX = evt.getX();
        currentY = evt.getY();
        oldX = currentX;
        oldY = currentY;
        System.out.println(currentX + " " + currentY);
        System.out.println("PEN!!!!");
    }

}                                    

private void jPanel2MousePressed(java.awt.event.MouseEvent evt) {                                     
    oldX = evt.getX();
    oldY = evt.getY();
    System.out.println(oldX + " " + oldY);
}                                    


//mouse released//
private void jPanel2MouseReleased(java.awt.event.MouseEvent evt) {                                      
    if (tool == 2) {
        currentX = evt.getX();
        currentY = evt.getY();
        System.out.println("line!!!! from" + oldX + "to" + currentX);
    }
}                                     

//set ui visible//
public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {

        public void run() {
            new JavaPaintUI().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JPanel jPanel2;
// End of variables declaration                   

class jPanel2 extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawString("BLAH", 20, 20);
        g.drawRect(200, 200, 200, 200);
    }
}
}

屏幕截图

整个东西是JFrame,中间的白色部分是jPanel2,这是我想画的。

【问题讨论】:

  • 一个非常简单的Java绘画例子,请看我在这个帖子里的回复:changing-jpanel-graphics-g-color-drawing-line。此外,不要与 NetBeans 生成的代码混为一谈,因为学习自己首先编写 Swing/图形代码会带来即时和长期的收益。
  • “我找到的所有示例都创建了一个类并使用 jpanel 扩展它,但我不知道我是否可以这样做,因为它是在 netbeans 中生成的。”那么这是您的基本问题,不了解如何使用您的自动 IDE。在这种情况下,我建议将您不理解的 IDE 放在一边,它似乎已经抓住了您的腹股沟短毛,并学习如何编写 Java 代码。也许稍后,在 IDE 的 F1 工具的帮助下,您将了解如何使用自定义组件。但暂时不要考虑它,因为它是您不需要的额外复杂功能。
  • 当然,我在几个网站上意识到了这一点,因为作弊者不会赢:) 现在比以前更感谢大家

标签: java swing jpanel draw paintcomponent


【解决方案1】:

Bijaya Bidari 的代码变体已被 Java 8 接受,而没有关于构造函数中可覆盖的方法调用的警告:

public class Graph extends JFrame {
    JPanel jp;

    public Graph() {
        super("Simple Drawing");
        super.setSize(300, 300);
        super.setDefaultCloseOperation(EXIT_ON_CLOSE);

        jp = new GPanel();
        super.add(jp);
    }

    public static void main(String[] args) {
        Graph g1 = new Graph();
        g1.setVisible(true);
    }

    class GPanel extends JPanel {
        public GPanel() {
            super.setPreferredSize(new Dimension(300, 300));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            //rectangle originated at 10,10 and end at 240,240
            g.drawRect(10, 10, 240, 240);
                    //filled Rectangle with rounded corners.    
            g.fillRoundRect(50, 50, 100, 100, 80, 80);
        }
    }
}

【讨论】:

    【解决方案2】:

    这是一个简单的例子。我想这很容易理解:

    import java.awt.*;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Graph extends JFrame {
    JFrame f = new JFrame();
    JPanel jp;
    
    
    public Graph() {
        f.setTitle("Simple Drawing");
        f.setSize(300, 300);
        f.setDefaultCloseOperation(EXIT_ON_CLOSE);
    
        jp = new GPanel();
        f.add(jp);
        f.setVisible(true);
    }
    
    public static void main(String[] args) {
        Graph g1 = new Graph();
        g1.setVisible(true);
    }
    
    class GPanel extends JPanel {
        public GPanel() {
            f.setPreferredSize(new Dimension(300, 300));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            //rectangle originates at 10,10 and ends at 240,240
            g.drawRect(10, 10, 240, 240);
            //filled Rectangle with rounded corners.    
            g.fillRoundRect(50, 50, 100, 100, 80, 80);
        }
    }
    

    }

    输出如下:

    【讨论】:

    • 您可以使用extends JFrame 或使用JFrame f = new JFrame();。通过同时执行这两个操作,您可以创建 2 个 JFrame 对象。你也可以省略g.drawRect(10, 10, 240, 240);
    【解决方案3】:

    注意额外的 cmets。

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.*;
    
    class JavaPaintUI extends JFrame {
    
        private int tool = 1;
        int currentX, currentY, oldX, oldY;
    
        public JavaPaintUI() {
            initComponents();
        }
    
        private void initComponents() {
            // we want a custom Panel2, not a generic JPanel!
            jPanel2 = new Panel2();
    
            jPanel2.setBackground(new java.awt.Color(255, 255, 255));
            jPanel2.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
            jPanel2.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent evt) {
                    jPanel2MousePressed(evt);
                }
                public void mouseReleased(MouseEvent evt) {
                    jPanel2MouseReleased(evt);
                }
            });
            jPanel2.addMouseMotionListener(new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent evt) {
                    jPanel2MouseDragged(evt);
                }
            });
    
            // add the component to the frame to see it!
            this.setContentPane(jPanel2);
            // be nice to testers..
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            pack();
        }// </editor-fold>
    
        private void jPanel2MouseDragged(MouseEvent evt) {
            if (tool == 1) {
                currentX = evt.getX();
                currentY = evt.getY();
                oldX = currentX;
                oldY = currentY;
                System.out.println(currentX + " " + currentY);
                System.out.println("PEN!!!!");
            }
        }
    
        private void jPanel2MousePressed(MouseEvent evt) {
            oldX = evt.getX();
            oldY = evt.getY();
            System.out.println(oldX + " " + oldY);
        }
    
    
        //mouse released//
        private void jPanel2MouseReleased(MouseEvent evt) {
            if (tool == 2) {
                currentX = evt.getX();
                currentY = evt.getY();
                System.out.println("line!!!! from" + oldX + "to" + currentX);
            }
        }
    
        //set ui visible//
        public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new JavaPaintUI().setVisible(true);
                }
            });
        }
    
        // Variables declaration - do not modify
        private JPanel jPanel2;
        // End of variables declaration
    
        // This class name is very confusing, since it is also used as the
        // name of an attribute!
        //class jPanel2 extends JPanel {
        class Panel2 extends JPanel {
    
            Panel2() {
                // set a preferred size for the custom panel.
                setPreferredSize(new Dimension(420,420));
            }
    
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.drawString("BLAH", 20, 20);
                g.drawRect(200, 200, 200, 200);
            }
        }
    }
    

    屏幕截图

    其他示例 - 更适合多条线和多条线段

    HFOE 将一个很好的链接作为对该线程的第一条评论。 Camickr 还在Custom Painting Approaches 文章中描述了主动绘画与绘画到BufferedImage

    另请参阅使用painting in a BufferedImage 的这种方法。

    【讨论】:

    • @Andrew,您回答的唯一一件事就是重命名内部类......我的回答为如何编写绘图程序提供了一个可行的解决方案。我不是在攻击你的答案。我是说这可能是一个单行评论,并且会产生同样的影响。问题是“任何人都可以在这样的示例中解释/展示如何使用图形吗?”现在,你的答案能回答吗?
    • @Yanick:“你回答的唯一事情就是重命名内部类。”检查从以下开始的 cmets 以查看对源代码的 5 值得注意的更改。 // 我们想要一个自定义的 Panel2,而不是一个通用的 JPanel! // 将组件添加到框架中以查看它! // 善待测试人员.. // 这个类名很容易混淆,因为它也被用作 // 属性的名称! // 设置自定义面板的首选尺寸。
    • 我已经阅读了您的“修改”(阅读我上次评论的更新);它仍然没有回答这个问题。我真的很惊讶你有一个赞成票。
    • +1 用于通过调整原始代码用工作代码回答问题。
    • 感谢您的回答,但是当我进行这些更改时,它会覆盖我所有其他 UI 和 Swing 组件(可能是所有 netbeans 的东西)。现在可以在使用 g.drawLine(oldX, oldY, currentX, currentY); 移动鼠标时让它绘制。但如果我把它放在我的paintcomponent 后面跟着repaint() 它只会临时画线。 I want it do draw lines similar to how i have it output (when pen is selected, every movement paints a line from new and previous cords and when the line is selected it paints a line when released from the first point to the second point)
    【解决方案4】:

    使用图形用户界面时,您需要记住在窗格上绘图是在Java AWT/Swing event queue 中完成的。您不能只在paint()/paintComponent()/etc 之外使用Graphics 对象。方法。

    但是,您可以使用一种称为“Frame buffering”的技术。基本上,您需要有一个 BufferedImage 并直接在其上绘制(请参阅它的 createGraphics() 方法;那个图形上下文您可以保留并重用于同一个 BufferedImage 实例上的多个操作,不需要一直重新创建它,仅在创建新实例时)。然后,在您的JPanelpaintComponent() 中,您只需将BufferedImage 实例绘制到JPanel。使用此技术,您可以通过affine transformations 非常轻松地执行缩放、平移和旋转操作。

    【讨论】:

    • 感谢您的回答,我在几个示例中看到了这个,但不确定它做了什么。我试试看。
    • 我觉得我对这一点的了解太多了,我对这些概念的了解还不够。
    • @Nick,使用方便的绘图方法等查看缓冲图像,例如像素值的美化二维数组等。您的应用程序通过缓冲图像的 Graphics 上下文绘制到缓冲图像 - 和您的 JPanel 在准备好更新时使用该图像进行自我更新(当操作系统重绘它时)。在您的情况下,这是最简单的解决方案;对于光栅图形。一个更复杂的解决方案是保留 Andrew 建议的绘图元素数组,而不是缓冲图像,并在 paintComponent 方法中绘制这些元素; 矢量图形解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多