Java paintComponent()vs paint()和JPanel vs Canvas在paintbrush类型GUI中
我从和博文中得到了一些有趣的想法和批评(有关GUI的代码,请参阅上一篇博文)。不过,有些事情我还是很困惑。主要是,什么是最便宜的用户图形显示方式 更具体地说,我使用了Java paintComponent()vs paint()和JPanel vs Canvas在paintbrush类型GUI中,java,swing,user-interface,awt,jpanel,Java,Swing,User Interface,Awt,Jpanel,我从和博文中得到了一些有趣的想法和批评(有关GUI的代码,请参阅上一篇博文)。不过,有些事情我还是很困惑。主要是,什么是最便宜的用户图形显示方式 更具体地说,我使用了JPanel类中的paintComponent()方法,通过在MouseDragged()方法中创建此类的对象,以及paintComponent(getGraphics())方法(AuxClass2和AuxClass1) 显然,使用getGraphics()和paintComponent()而不是repaint()是个坏主意,我怀疑
JPanel
类中的paintComponent()
方法,通过在MouseDragged()
方法中创建此类的对象,以及paintComponent(getGraphics())
方法(AuxClass2
和AuxClass1
)
显然,使用getGraphics()
和paintComponent()
而不是repaint()
是个坏主意,我怀疑这与内存使用有关。每次用户拖动鼠标时也调用AuxClass2
,这也是一个坏主意
此外,JPanel与Canvas(即swing与awt)的对比也有点混乱。使用什么以及何时使用
我一直在试图找到解决办法,但没有找到,特别是对于getGraphics()
方法:如何将图形添加到面板中?重与轻
基本上说,重量级组件链接到它自己的本地对等点,其中轻量级组件共享一个通用的本地对等点
一般来说,混合使用重型和轻型组件不是一个好主意,因为z顺序存在问题,根据我的经验(尽管现在应该更好),可能会出现一些绘画问题
这就是为什么不鼓励您使用Canvas
类的原因,可能是因为您试图将其放在一个轻量级组件上……我想
控制的幻觉
对于新来的人来说,最大的问题之一是,他们会产生一种错觉,认为自己对绘画过程有某种控制,而实际上并没有。接受它更容易
您所能做的最好的事情就是请求重绘管理器在方便的时候尽早执行更新
此外,调用getGraphics
也不能保证返回非空值
事物的正确顺序
paint
vspaintComponent
这里的问题是paint
做了许多重要的工作,调用paintComponent
只是其中之一
在Swing中,我们强烈建议在需要执行自定义绘制时使用paintComponent
,这通常是组件的最低级别,并且在绘制子组件之前调用
如果调用super.paint
后覆盖paint
,然后在图形上进行绘制,则最终会在所有内容上进行绘制,这并不总是理想的结果
即使是这样,子组件也可以独立于其父容器进行绘制,从而使绘制“覆盖”您可能添加的任何绘制效果
有用的链接
- (谈论油漆工艺的工作原理)
离别的思念
只有实际添加到组件(连接到本机对等方)的组件才会调用paint
方法。因此,尝试绘制尚未添加到容器中的组件是毫无意义的
我一直在想办法,但还没有找到,
特别是对于getGraphics()方法:图形还能是什么
添加到面板中
记住需要作为变量绘制的内容,并在paintComponent()中使用它。
例如,在你的另一个问题中,你似乎想做的是:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintRectangle extends JPanel {
private Point mouseLocation;
public PaintRectangle() {
setPreferredSize(new Dimension(500, 500));
MouseAdapter listener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
updateMouseRectangle(e);
}
private void updateMouseRectangle(MouseEvent e) {
mouseLocation = e.getPoint();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
updateMouseRectangle(e);
}
@Override
public void mouseReleased(MouseEvent e) {
mouseLocation = null;
repaint();
}
};
addMouseListener(listener);
addMouseMotionListener(listener);
}
private Rectangle getRectangle() {
if(mouseLocation != null) {
return new Rectangle(mouseLocation.x - 5, mouseLocation.y - 5, 10, 10);
}
else {
return null;
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle rectangle = getRectangle();
if(rectangle != null) {
Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLUE);
gg.fill(rectangle);
gg.setColor(Color.BLACK);
gg.draw(rectangle);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new PaintRectangle());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
另见
…画笔类型GUI
使用buffereImage
作为绘制表面。在JLabel
中显示它。将标签放在JScrollPane
内的面板中央
根据需要调用bufferedImage.getGraphics()
,但记住在完成后对其执行dispose()
,然后调用label.repaint()
始终使用Swing组件,不要覆盖任何内容
这是一个例子
还有
我没有说屏幕截图更好,是代码更好 谢谢,问题是,调用repaint()
会删除以前绘制的内容。有可能避免吗?没有,因为您不知道需要重新绘制什么(用户可能已经在您的窗口上移动了另一个窗口),所以绘制组件应该重新绘制整个组件(在指定的剪辑内)。您可以使用Andrew绘制图像的方法,并在paintComponent中绘制该图像。这是否意味着,如果我需要保留整个“绘制”,例如保存到硬盘驱动器,我根本不应该使用Canvas
或JPanel
,而是使用BufferedImage
?这应该不是公认的答案。实际上没有解释,解释的两个句子中有一个是不完整的句子,没有意义,也没有意义,因为没有上下文可以推断任何东西。我有点想对此竖起大拇指,但“事物的正确顺序”的解释让我有点困惑。关于“绘制”的部分对我来说很有意义,但我不太清楚它如何与paintComponent配合(除了在绘制子组件之前发生编辑:链接“在Swing中绘制”已断开)。我将尝试您提供的链接,看看这是否给了我更多的见解。@searchengine27一般来说,绘制链类似于paint
->paintComponent
->paintBorder
->paintChildren
。调用super.paint
和产生奇怪的绘制结果很容易出错,但也很容易覆盖绘制(通过调用super.p