在 Java Swing 中高效渲染占用网格
首先,如果这个问题很基础,请接受我的歉意,我主要了解 C#,但被迫在这个特定项目中使用 Java!
我正在尝试实现一个 GUI 来显示基于机器人传感器数据的 占用网格。占用网格将非常大,可能高达 1500x1500 网格方块,代表每个网格单元约 10cm2 的实际面积。
每个网格方块将简单地存储一个可枚举状态,例如:
- 未知
- 未占用
- 占用
- 机器人
我只是想找到将其呈现为网格的最佳方法,使用不同颜色的方块来描绘不同的网格单元状态。
我已经实现了一种简单的基本算法来绘制正方形和网格线,但是它在较大的占用网格上表现非常糟糕。类中的其他代码在收集新的传感器数据时每 0.5 秒重绘一次窗口,我怀疑性能非常差的原因是我每次都渲染每个单元格。有没有一种简单的方法可以选择性地渲染这些单元格,我应该将每个单元格包装在一个可观察的类中吗?
我当前的实现:
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int width = getSize().width;
int height = getSize().height;
int rowHeight = height / (rows);
int colWidth = width / (columns);
//Draw Squares
for (int row = 0; row < rows; row++) {
for (int col = 0; col < columns; col++) {
switch (this.grid[row][col]) {
case Unexplored:
g.setColor(Color.LIGHT_GRAY);
break;
case Empty:
g.setColor(Color.WHITE);
break;
case Occupied:
g.setColor(Color.BLACK);
break;
case Robot:
g.setColor(Color.RED);
break;
}
g.drawRect(col * colWidth, height - ((row + 1) * rowHeight), colWidth, rowHeight);
g.fillRect(col * colWidth, height - ((row + 1) * rowHeight), colWidth, rowHeight);
}
}
int k;
if (outline) {
g.setColor(Color.black);
for (k = 0; k < rows; k++) {
g.drawLine(0, k * rowHeight, width, k * rowHeight);
}
for (k = 0; k < columns; k++) {
g.drawLine(k * colWidth, 0, k * colWidth, height);
}
}
}
private void setRefresh() {
Action updateUI = new AbstractAction() {
boolean shouldDraw = false;
public void actionPerformed(ActionEvent e) {
repaint();
}
};
new Timer(updateRate, updateUI).start();
}
请帮忙!提前致谢。
First off, please accept my apologies if this question is basic, I mainly have knowledge of C# but am forced to use Java for this particular project!
I'm trying to implement a GUI to display an occupancy grid based on robot sensor data. The occupancy grid will be quite large, perhaps up to 1500x1500 grid squares representing real-world area of around 10cm2 per grid cell.
Each grid square will simply store an Enumerable status, for example:
- Unknown
- Unoccupied
- Occupied
- Robot
I would simply like to find the best way to render this as a grid, using different colour squares to depict different grid cell status'.
I have implemented a naive, basic algorithm to draw squares and grid lines, however it performs VERY badly on larger occupancy grids. Other code in the class redraws the window every 0.5s as new sensor data is collected, I suspect the reason for the very poor performance is the fact that i am rendering EVERY cell EVERY time. Is there an easy way i can selectively render these cells, should I wrap each cell in an observable class?
My current implementation:
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int width = getSize().width;
int height = getSize().height;
int rowHeight = height / (rows);
int colWidth = width / (columns);
//Draw Squares
for (int row = 0; row < rows; row++) {
for (int col = 0; col < columns; col++) {
switch (this.grid[row][col]) {
case Unexplored:
g.setColor(Color.LIGHT_GRAY);
break;
case Empty:
g.setColor(Color.WHITE);
break;
case Occupied:
g.setColor(Color.BLACK);
break;
case Robot:
g.setColor(Color.RED);
break;
}
g.drawRect(col * colWidth, height - ((row + 1) * rowHeight), colWidth, rowHeight);
g.fillRect(col * colWidth, height - ((row + 1) * rowHeight), colWidth, rowHeight);
}
}
int k;
if (outline) {
g.setColor(Color.black);
for (k = 0; k < rows; k++) {
g.drawLine(0, k * rowHeight, width, k * rowHeight);
}
for (k = 0; k < columns; k++) {
g.drawLine(k * colWidth, 0, k * colWidth, height);
}
}
}
private void setRefresh() {
Action updateUI = new AbstractAction() {
boolean shouldDraw = false;
public void actionPerformed(ActionEvent e) {
repaint();
}
};
new Timer(updateRate, updateUI).start();
}
Please help! Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
ROS - 来自 willowgarage 的机器人操作系统在 java 中有一个 ocupancygrid 实现:http://code.google.com/p/rosjava/source/browse/android_honeycomb_mr2/src/org/ros/android/views/map/OccupancyGrid.java?spec=s vn.android.88c9f4af5d62b5115bfee9e4719472c4f6898665&repo=android&name=88c9f4af5d&r=88c9f4af5d62b5115bfee9e4719472c4f6898665
您可以使用它或从中获得想法。
ROS - robot operating system from willowgarage has an occupancygrid implementation in java: http://code.google.com/p/rosjava/source/browse/android_honeycomb_mr2/src/org/ros/android/views/map/OccupancyGrid.java?spec=svn.android.88c9f4af5d62b5115bfee9e4719472c4f6898665&repo=android&name=88c9f4af5d&r=88c9f4af5d62b5115bfee9e4719472c4f6898665
You may use it or get ideas from it.
绘画时您需要尊重剪辑矩形(假设您的网格位于 JScrollPane 中)并适当地使用 JComponent#repaint(Rectangle) 。
请参阅此示例程序(虽然它与延迟加载单元格的值有关,但它也具有剪辑边界绘制):
You need to respect the clip rectangle when painting (assuming your grid is in a JScrollPane) and use JComponent#repaint(Rectangle) appropriately.
See this sample program (although it related to loading the value of a cell lazily, it also has the clip bounds painting):
创建矩形可能太慢了。相反,为什么不创建一个位图图像,每个像素都是网格的一个单元格,然后您可以将其缩放到您想要的任何大小。
以下类采用整数矩阵,并将其保存到位图文件中。
使用该类,您可以简单地执行以下操作:
生成整数矩阵 (
myOccupancyMatrix
) 很容易。避免使用Switch
语句的一个简单技巧是将颜色值分配给 Occupancy 枚举:将其保存到磁盘后,BMP 可以在小程序中显示并轻松缩放:
希望这会有所帮助!
Creating rectangles is probably too slow. Instead, why don't you create a bitmap image, each pixel being a cell of the grid, you can then scale it to whatever size you want.
The following class takes a matrix of integers, and saves it to a bitmap file.
With that class, you can simply do:
Generating the matrix of integers (
myOccupancyMatrix
) is easy. A simple trick to avoid theSwitch
statement is assigning the color values to your Occupancy enum:Once you save it do disk, the BMP can be shown in an applet and scaled easily:
Hope this helps!
即使渲染 2,250,000 个单元的子集也不是一件容易的事。您需要的两种模式是模型-视图-控制器,讨论了此处,以及flyweight,其中
JTable< /code>
可能有用。
Rendering even a subset of 2,250,000 cells is not a trivial undertaking. Two patterns you'll need are Model-View-Controller, discussed here, and flyweight, for which
JTable
may be useful.