gpt4 book ai didi

java - JPanel 在调整大小时会被重新绘制几次,有时根本不会

转载 作者:行者123 更新时间:2023-11-30 03:30:39 24 4
gpt4 key购买 nike

首先,一些背景知识。我正在用 Java 构建我的第一个 GUI 应用程序,但我不确定我是否以正确的方式进行操作,因为我不熟悉 GUI 类。最终目标是根据开放街道 map 数据构建可调整大小、可缩放、可滚动的 map 。

我现在拥有的是 JPanel 的子类,我在 JFrame 中调用 LinePanel,并使用 Graphics 对象来绘制代表道路的线条。这对于检查我是否正确解析和解释数据的目的来说效果很好,但它似乎不够且天真。我已经遇到了一个问题,即 JPanel 在调整大小时被重新绘制了几次,导致 map 错误到我的应用程序需要癫痫警告的地步。

这是我现在的代码:

package map;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MapDisplay {
private JFrame frame;
private LinePanel jpanel;

public MapDisplay(Map map) {
this.frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
jpanel.repaint();
}
});
jpanel = new LinePanel(map);
frame.add(jpanel, BorderLayout.CENTER);
}

public void display() {
frame.setSize(710, 935);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jpanel.repaint();
}

class LinePanel extends JPanel {
private static final long serialVersionUID = 1965018056953712219L;
private Map map;
private int width;
private int height;

private int latAsY(double lat) {
return height
- (int) (height * (lat - map.getMinLat()) / (map
.getMaxLat() - map.getMinLat()));
}

private int lonAsX(double lon) {
return (int) (width * (lon - map.getMinLong()) / (map.getMaxLong() - map
.getMinLong()));
}

private void recalculateDimensions() {
double mapRatio = (map.getMaxLat() - map.getMinLat())
/ (map.getMaxLong() - map.getMinLong());
double panelRatio = this.getHeight() / (double) this.getWidth();
if (mapRatio > panelRatio) {
width = (int) (this.getHeight() / mapRatio);
height = this.getHeight();
} else {
width = this.getWidth();
height = (int) (mapRatio * this.getWidth());
}
}

public LinePanel(Map map) {
super();
this.map = map;
}

public void repaint() {
if (map != null) {
recalculateDimensions();
Graphics2D g = (Graphics2D) this.getGraphics();
if (g != null) {
g.setStroke(new BasicStroke(2));
g.clearRect(0, 0, jpanel.getWidth(), jpanel.getHeight());
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
for (String wayId : map.getWays()) {
Way way = map.getWay(wayId);
Node prev = null;
for (String nodeId : way.getNodes()) {
Node cur = map.getNode(nodeId);
if (prev != null) {
int y1 = latAsY(prev.getLatitude());
int x1 = lonAsX(prev.getLongitude());
int y2 = latAsY(cur.getLatitude());
int x2 = lonAsX(cur.getLongitude());
g.drawLine(x1, y1, x2, y2);
}
prev = cur;
}
}
}
}
}
}
}

我在调整大小时调用重绘,因为它不会自动执行此操作,这是我做错了什么的另一个迹象。我还使用 g.fillRect 手动清除 JPanel,因为在重绘 map 之前调用 super.repaint() 会导致没有任何内容出现...

本质上,我只是想从更高级的 Java 程序员那里得到一些关于我应该如何进行这整个努力的指导。如果我走在正确的轨道上,请随意将我推向正确的方向,而不是让我走上一条新的道路,但我怀疑情况是否如此。

最佳答案

  • public void repaint() { 否,否,否
  • Graphics2D g = (Graphics2D) this.getGraphics(); - 否,否,否

这不是 Swing 中绘画的工作方式。请参阅Performing Custom PaintingPainting in AWT and Swing有关如何在 Swing 中进行绘画的更多详细信息

您应该首先删除 repaint 方法并将其替换为 paintComponent 方法...

public class MapDisplay {

private JFrame frame;
private LinePanel jpanel;

public MapDisplay(Map map) {
this.frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
jpanel.repaint();
}
});
jpanel = new LinePanel(map);
frame.add(jpanel, BorderLayout.CENTER);
}

public void display() {
frame.setSize(710, 935);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jpanel.repaint();
}

class LinePanel extends JPanel {

private static final long serialVersionUID = 1965018056953712219L;
private Map map;
private int width;
private int height;

private int latAsY(double lat) {
return height
- (int) (height * (lat - map.getMinLat()) / (map
.getMaxLat() - map.getMinLat()));
}

private int lonAsX(double lon) {
return (int) (width * (lon - map.getMinLong()) / (map.getMaxLong() - map
.getMinLong()));
}

private void recalculateDimensions() {
double mapRatio = (map.getMaxLat() - map.getMinLat())
/ (map.getMaxLong() - map.getMinLong());
double panelRatio = this.getHeight() / (double) this.getWidth();
if (mapRatio > panelRatio) {
width = (int) (this.getHeight() / mapRatio);
height = this.getHeight();
} else {
width = this.getWidth();
height = (int) (mapRatio * this.getWidth());
}
}

public LinePanel(Map map) {
super();
this.map = map;
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (map != null) {
recalculateDimensions();
Graphics2D g2d = (Graphics2D) g.create();
g2d.setStroke(new BasicStroke(2));
g2d.clearRect(0, 0, jpanel.getWidth(), jpanel.getHeight());
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.BLACK);
for (String wayId : map.getWays()) {
Way way = map.getWay(wayId);
Node prev = null;
for (String nodeId : way.getNodes()) {
Node cur = map.getNode(nodeId);
if (prev != null) {
int y1 = latAsY(prev.getLatitude());
int x1 = lonAsX(prev.getLongitude());
int y2 = latAsY(cur.getLatitude());
int x2 = lonAsX(cur.getLongitude());
g2d.drawLine(x1, y1, x2, y2);
}
prev = cur;
}
}
g2d.dispose();
}
}
}
}

是的,当组件调整大小时,可能会多次生成重绘事件,但重绘事件也可以由 RepaintManager 自动减少(即 RepaintManager code> 可能会被调用 100 次来重绘组件,可能只会产生 10 个实际的重绘事件 - 作为示例)...

关于java - JPanel 在调整大小时会被重新绘制几次,有时根本不会,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29136378/

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