gpt4 book ai didi

Java Swing绘画和鼠标事件闪烁

转载 作者:行者123 更新时间:2023-12-01 15:51:07 24 4
gpt4 key购买 nike

我有一个扩展 JPanel 的类(如下),该面板位于 JScrollPane 内。它监听(自身)鼠标事件,并尝试重新定位自身(拖动时)并重新缩放自身(在滚轮上)以模拟鼠标移动和缩放。该面板还负责我的应用程序的主要视觉输出。它存储在 JScrollPane 的可视区域(但在面板的图形上)呈现的 BufferedImage。图像的大小和形状保持与可视区域相匹配。

我的问题就是这样;

1) 在鼠标事件上,我遇到大量闪烁和性能下降2)如果我用自己的绘画方法覆盖paint或paintComponent方法(这对于消除闪烁和其他绘画问题是可取的),我仍然会得到相同的闪烁效果,并且从具有透明区域的加载图像中绘制图形,然后将其着色区域黑色。当我手动调用paint方法而不重写paint和paintComponent方法时,我仍然会出现闪烁,但透明区域显示正常。

我是 Swing 绘画新手,显然做错了什么,有人能给我指出正确的方向来解决这个问题吗?

谢谢

    import jSim.simulation.Simulation;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JViewport;
import javax.swing.event.MouseInputListener;

public class SimPanel extends JPanel implements MouseWheelListener, MouseInputListener {
//Simulation

Simulation sim;
//Viewer
JViewport viewport;
Dimension viewSize;
BufferStrategy strat;
//Drawing
Image renderImage;
Graphics2D g2d;
boolean draw = true;
double scale = 1.0;
Object drawLock = new Object();
//Mouse events
int m_XDifference, m_YDifference;

public SimPanel(JViewport viewport) {
this.viewport = viewport;
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.addMouseWheelListener(this);

//this.setup();
}

public SimPanel(Simulation sim, JViewport viewport) {
this.sim = sim;
this.viewport = viewport;
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.addMouseWheelListener(this);
//this.setup();
}

//Used to initialise the buffered image once drawing begins
private void setup() {
synchronized (drawLock) {
viewSize = viewport.getExtentSize();
renderImage = new BufferedImage(viewSize.width, viewSize.height, BufferedImage.TYPE_INT_RGB);
g2d = (Graphics2D) renderImage.getGraphics();
}
}

// @Override
// public void paint(Graphics g)
// {
// synchronized(drawLock) {
// //super.paintComponent(g);
// paintSimulation();
// }
// }
//Paint the screen for a specific simulation
public void paintSimulation(Simulation sim) {
synchronized (drawLock) {
setSimulation(sim);
paintSimulation();
}
}

//Paint the screen with the panels simulation
public void paintSimulation() {
synchronized (drawLock) {
//if no image, then init
if (renderImage == null) {
setup();
}
//clear the screen
resetScreen();
//draw the simulation if not null, to the image
if (sim != null) {
sim.draw(this);
}
//paint the screen with the image
paintScreen();
}
}

private void resetScreen() {
Dimension newSize = viewport.getExtentSize();
if (viewSize.height != newSize.height || viewSize.width != newSize.width || renderImage == null) {
//System.out.println("Screen Size Changed: " + viewSize + " " + newSize);
viewSize = newSize;
renderImage = new BufferedImage(viewSize.width, viewSize.height, BufferedImage.TYPE_INT_RGB);
g2d = (Graphics2D) renderImage.getGraphics();
} else {
g2d.setBackground(Color.DARK_GRAY);
g2d.clearRect(0, 0, (int) (viewSize.width), (int) (viewSize.height));
}
}

private void paintScreen() {
Graphics g;
Graphics2D g2;
try {
//g = viewport.getGraphics();
g = this.getGraphics();
g2 = (Graphics2D) g;
if ((g != null) && (renderImage != null)) {
g2.drawImage(renderImage, (int) viewport.getViewPosition().getX(), (int) viewport.getViewPosition().getY(), null);
}
Toolkit.getDefaultToolkit().sync(); // sync the display on some systems
g.dispose();
g2.dispose();
this.revalidate();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}

//Simulation makes calls to this method to draw items on the image
public void draw(BufferedImage image, int x, int y, Color colour) {
synchronized (drawLock) {
Rectangle r = viewport.getViewRect();
if (g2d != null && draw) {
Point p = new Point((int) (x * scale), (int) (y * scale));
if (r.contains(p)) {
if (scale < 1) {
Graphics2D g2 = (Graphics2D) image.getGraphics();
Image test = image.getScaledInstance((int) (image.getWidth(null) * scale), (int) (image.getHeight(null) * scale), Image.SCALE_FAST);
g2d.drawImage(test, (int) ((x * scale - r.x)), (int) ((y * scale - r.y)), null);
} else {
g2d.drawImage(image, x - r.x, y - r.y, null);
}
}
}
}
}

public void setDraw(boolean draw) {
this.draw = draw;
}

public void setSimulation(Simulation sim) {
synchronized (drawLock) {
if (!(this.sim == sim)) {
this.sim = sim;
}
}
}

public void mouseWheelMoved(MouseWheelEvent e) {
synchronized (drawLock) {
updatePreferredSize(e.getWheelRotation(), e.getPoint());
}
}

private void updatePreferredSize(int wheelRotation, Point stablePoint) {
double scaleFactor = findScaleFactor(wheelRotation);
if (scale * scaleFactor < 1 && scale * scaleFactor > 0.05) {
scaleBy(scaleFactor);
Point offset = findOffset(stablePoint, scaleFactor);
offsetBy(offset);
this.getParent().doLayout();
}
}

private double findScaleFactor(int wheelRotation) {
double d = wheelRotation * 1.08;
return (d > 0) ? 1 / d : -d;
}

private void scaleBy(double scaleFactor) {
int w = (int) (this.getWidth() * scaleFactor);
int h = (int) (this.getHeight() * scaleFactor);
this.setPreferredSize(new Dimension(w, h));
this.scale = this.scale * scaleFactor;
}

private Point findOffset(Point stablePoint, double scaleFactor) {
int x = (int) (stablePoint.x * scaleFactor) - stablePoint.x;
int y = (int) (stablePoint.y * scaleFactor) - stablePoint.y;
return new Point(x, y);
}

private void offsetBy(Point offset) {
Point location = viewport.getViewPosition();
//this.setLocation(location.x - offset.x, location.y - offset.y);
viewport.setViewPosition(new Point(location.x + offset.x, location.y + offset.y));
}

public void mouseDragged(MouseEvent e) {
synchronized (drawLock) {
//Point p = this.getLocation();
Point p = viewport.getViewPosition();
int newX = p.x - (e.getX() - m_XDifference);
int newY = p.y - (e.getY() - m_YDifference);
//this.setLocation(newX, newY);
viewport.setViewPosition(new Point(newX, newY));
//this.getParent().doLayout();
}
}

public void mousePressed(MouseEvent e) {
synchronized (drawLock) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
m_XDifference = e.getX();
m_YDifference = e.getY();
}
}

public void mouseReleased(MouseEvent e) {
synchronized (drawLock) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}

public void mouseClicked(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}

public void mouseEntered(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}

public void mouseExited(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}

public void mouseMoved(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}

最佳答案

简而言之,查找双缓冲。

更长的答案...

重写paintComponent。创建一个离屏图形对象。在那个物体上画画。将其复制到传递给 Paint 方法的图形对象。

哦,并摆脱所有同步。你不需要它。

关于Java Swing绘画和鼠标事件闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6017063/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com