Java 中的图形;不闪屏更新帧
Graphics in Java; Update frame without flashing screen
我写了一些代码,在 JPanel
的中心画了一条线。在 mouseMoved
动作侦听器中不断重绘该线以指向用户的光标。
一切似乎都很好,但在移动光标一段时间后,正在重绘的线开始闪烁并变得完全不一致。
此闪烁是由于我的 PC 性能不佳还是 clearRect()
方法是 'wrong' 所使用的东西造成的?
以上两个原因不能解释为什么只有在光标移动一定量后才开始闪烁。
请随时 运行 下面的代码,让我知道该行是否开始为您闪烁:
import java.awt.Graphics;
public class Frame1 extends javax.swing.JFrame {
private javax.swing.JPanel jPanel1;
int x;
int y;
public Frame1() {
initComponents();
x = jPanel1.getWidth()/2;
y = jPanel1.getHeight()/2;
}
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
jPanel1MouseDragged(evt);
}
public void mouseMoved(java.awt.event.MouseEvent evt) {
jPanel1MouseMoved(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1000, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 680, Short.MAX_VALUE)
);
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
pack();
}
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {
}
private void jPanel1MouseMoved(java.awt.event.MouseEvent evt) {
Graphics g = jPanel1.getGraphics();
g.clearRect(0, 0,jPanel1.getWidth(), jPanel1.getHeight());
g.translate(x, y);
g.drawLine(
0,
0,
(int)(120*Math.cos(Math.atan2(evt.getY() - y, evt.getX() - x))),
(int)(120*Math.sin(Math.atan2(evt.getY() - y, evt.getX() - x)))
);
}
public static void main(String args[])throws Exception {
Frame1 frame = new Frame1();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}
我怀疑有更好的方法来更新线的位置并在不调用 clearRect()
的情况下重新绘制它,如果您知道,我也很想知道。
Graphics g = jPanel1.getGraphics();
这不是 Swing 中绘画的完成方式。您已经避开了 Swing 组件提供的双缓冲支持。
相反,创建自定义 JPanel
并覆盖它的 paintComponent
方法(确保在进行任何自定义绘制之前调用 super.paintComponent
)并在那里执行绘制。
在你的自定义JPanel
中,将你的MouseListener
添加到其中,当mouseMoved
被触发时,更新你需要的状态变量(最后一个点的点和鼠标点) 并调用 repaint
请参阅 Painting in AWT and Swing and Performing Custom Painting 了解有关如何绘画的更多详细信息
我写了一些代码,在 JPanel
的中心画了一条线。在 mouseMoved
动作侦听器中不断重绘该线以指向用户的光标。
一切似乎都很好,但在移动光标一段时间后,正在重绘的线开始闪烁并变得完全不一致。
此闪烁是由于我的 PC 性能不佳还是 clearRect()
方法是 'wrong' 所使用的东西造成的?
以上两个原因不能解释为什么只有在光标移动一定量后才开始闪烁。
请随时 运行 下面的代码,让我知道该行是否开始为您闪烁:
import java.awt.Graphics;
public class Frame1 extends javax.swing.JFrame {
private javax.swing.JPanel jPanel1;
int x;
int y;
public Frame1() {
initComponents();
x = jPanel1.getWidth()/2;
y = jPanel1.getHeight()/2;
}
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
jPanel1MouseDragged(evt);
}
public void mouseMoved(java.awt.event.MouseEvent evt) {
jPanel1MouseMoved(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1000, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 680, Short.MAX_VALUE)
);
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
pack();
}
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {
}
private void jPanel1MouseMoved(java.awt.event.MouseEvent evt) {
Graphics g = jPanel1.getGraphics();
g.clearRect(0, 0,jPanel1.getWidth(), jPanel1.getHeight());
g.translate(x, y);
g.drawLine(
0,
0,
(int)(120*Math.cos(Math.atan2(evt.getY() - y, evt.getX() - x))),
(int)(120*Math.sin(Math.atan2(evt.getY() - y, evt.getX() - x)))
);
}
public static void main(String args[])throws Exception {
Frame1 frame = new Frame1();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}
我怀疑有更好的方法来更新线的位置并在不调用 clearRect()
的情况下重新绘制它,如果您知道,我也很想知道。
Graphics g = jPanel1.getGraphics();
这不是 Swing 中绘画的完成方式。您已经避开了 Swing 组件提供的双缓冲支持。
相反,创建自定义 JPanel
并覆盖它的 paintComponent
方法(确保在进行任何自定义绘制之前调用 super.paintComponent
)并在那里执行绘制。
在你的自定义JPanel
中,将你的MouseListener
添加到其中,当mouseMoved
被触发时,更新你需要的状态变量(最后一个点的点和鼠标点) 并调用 repaint
请参阅 Painting in AWT and Swing and Performing Custom Painting 了解有关如何绘画的更多详细信息