JPanel 背景加倍,但 Panel 正在按预期工作
JPanel background is doubled , but Panel is working expected
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 (color) 替换为通用面板,程序将正常运行。我不知道为什么?请帮忙!如果你不明白请尝试运行代码(我用翻译器写的这个问题)
JPanel background is doubled
自定义绘画时,方法中的第一条语句应该是:
super.paintComponent(g);
清除背景,否则会出现绘画伪像,这就是为什么您会看到两条蓝线。
当然,当您添加 super.paintComponent(g) 时,绘画会消失,因为背景已被清除。
问题有两种解决方案:
- 保留要绘制的对象的 ArrayList 并在 paintComponent() 方法中遍历 ArrayList 以绘制所有对象
- 绘制到 BufferedImage,然后绘制整个图像。
在这种情况下,我建议选项 2 可能是最好的。
查看 Custom Painting Approaches 了解每种方法的更多信息和示例。
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 (color) 替换为通用面板,程序将正常运行。我不知道为什么?请帮忙!如果你不明白请尝试运行代码(我用翻译器写的这个问题)
JPanel background is doubled
自定义绘画时,方法中的第一条语句应该是:
super.paintComponent(g);
清除背景,否则会出现绘画伪像,这就是为什么您会看到两条蓝线。
当然,当您添加 super.paintComponent(g) 时,绘画会消失,因为背景已被清除。
问题有两种解决方案:
- 保留要绘制的对象的 ArrayList 并在 paintComponent() 方法中遍历 ArrayList 以绘制所有对象
- 绘制到 BufferedImage,然后绘制整个图像。
在这种情况下,我建议选项 2 可能是最好的。
查看 Custom Painting Approaches 了解每种方法的更多信息和示例。