【问题标题】:JPanel background is doubled , but Panel is working expectedJPanel 背景翻倍,但 Panel 工作正常
【发布时间】:2020-10-14 05:05:25
【问题描述】:
package com.company;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayDeque;
import java.util.Random;

public class REcom {
    REcom() {
        JFrame jfm = new JFrame("Paint");
        jfm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        BorderLayout border = new BorderLayout();
        border.setVgap(10);

        jfm.setLayout(border);


        DrawPanel dw = new DrawPanel();

        dw.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                dw.setXY(e.getX() , e.getY());
                dw.repaint();
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                dw.previosPosition = new Position(e.getX() , e.getY());

            }
        });


        jfm.add(dw  ,BorderLayout.CENTER);
        jfm.setBackground(Color.white);
        jfm.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
        jfm.setSize(500 ,500);

        JPanel color = new JPanel(new FlowLayout(FlowLayout.LEFT));
        //that Jpanel background is doubled
       // color.setBounds(new Rectangle(0 ,0 , 100 , jfm.getHeight()));

        Button blue = new Button();
        blue.setBackground(Color.blue);
        blue.setSize(500 ,200);
        blue.addActionListener(e -> {
            dw.color = Color.blue;
        });
        color.add(blue);

        Button white = new Button();
        white.setBackground(Color.white);
        white.setSize(200 ,200);
        white.addActionListener(e -> {
            dw.color = Color.white;
        });

        color.add(white);

        jfm.add(color , BorderLayout.NORTH);
        jfm.setPreferredSize(new Dimension(500 ,500));
        jfm.pack();
        color.setBackground(Color.blue);
        jfm.setVisible(true);

    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(REcom::new);
    }

}
class DrawPanel extends JPanel {
    ArrayDeque<Position> ad = new ArrayDeque<>();
    Position previosPosition = null;
    Color color = Color.yellow;
    void setXY(int x , int y) {
        ad.push(new Position(x , y));
    }
    @Override
    protected void paintComponent(Graphics g) {


        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(color);

        g2.setStroke(new BasicStroke(12f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
        Position d = ad.pollLast();

        if(d != null) {

            if(previosPosition == null)
                g2.fillOval(d.x, d.y -10 , d.x , d.y-10);
            else{

                g2.drawLine(previosPosition.x -5 , previosPosition.y -10 , d.x-5 , d.y-10);
            }

            previosPosition = d;
        }


    }

}
class Position {
    int x, y;
    Position(int x, int y) {
        this.x=  x;
        this.y = y;
    }
    void setXY(int x , int y) {
        this.x = x;
        this.y = y;
    }
}

关于代码:两个面板,一个用于绘图,另一个用于颜色之间的切换。我决定将切换器添加到框架的顶部。但是它的背景移到了底部,我可以在上面画画。(因此它的背景超出了边界)。如果我要为其面板的中心 JPanel 设置边框(用于绘图),则边框顶部会加倍
我想将 Jpanel 添加到顶部以在颜色之间切换(background is doubled after drawing anything)以进行绘图。但是顶级Jpanel背景翻了一番。但是如果我将Jpanel(颜色)替换为通用面板,程序可以正常工作。我不知道为什么?请帮忙!如果您不明白,请尝试运行代码(我用翻译器写的这个问题)

【问题讨论】:

    标签: java swing jpanel border border-layout


    【解决方案1】:

    JPanel 背景翻倍

    当您进行自定义绘画时,您的方法中的第一条语句应该是:

    super.paintComponent(g);
    

    清除背景,否则您可能会出现绘画伪影,这就是您看到两条蓝线的原因。

    当然,当您添加 super.paintComponent(g) 时,绘画会因为背景被清除而消失。

    解决问题的方法有两种:

    1. 保留一个要绘制的对象的 ArrayList,并在 paintComponent() 方法中迭代 ArrayList 以绘制所有对象
    2. 绘制到 BufferedImage,然后只绘制整个图像。

    我建议在这种情况下选项 2 可能是最好的。

    查看Custom Painting Approaches 了解更多信息和每种方法的示例。

    【讨论】:

    • 听这个家伙的。他是 100% 的 Swing 专家。像他这样的人不多。
    • 我实际上建议不要使用选项 2。如果您不自己处理,您将失去 dpi 缩放。
    • 使用选项 2 我可以实现 undo 和 reendo
    • @ErnarJack,我不知道有什么有效的方法来做撤销/重做。在示例代码中,addRectangle(....) 方法在矩形绘制到 BufferedImage 之前被调用。因此,如果您希望能够撤消,则需要在每次更新图像之前保留 BufferedImage 的副本。如果您对绘制的每个椭圆都执行此操作,那么当您保留 BufferedImage 的多个副本时,这将导致大量内存需求。因此,如果您关心的是撤消/重做,那么方法 1 就是要走的路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多