Java Swing:抽绳非常慢
我正在使用swing编写一个java应用程序,其中需要在正方形上方绘制一个网格。为此,我使用了Java Swing:抽绳非常慢,java,swing,graphics,fullscreen,doublebuffered,Java,Swing,Graphics,Fullscreen,Doublebuffered,我正在使用swing编写一个java应用程序,其中需要在正方形上方绘制一个网格。为此,我使用了Graphics类提供的drawLine(…)方法 一切都很好,只是画每条线需要很多时间(50条线需要20秒以上…)。我甚至可以看到实时绘制的线条。一件奇怪的事情是水平线的绘制速度比垂直线快(几乎是瞬间) 我可能做错了什么。下面是网格的代码 public void drawGrid(Graphics g){ g.setColor(new Color(255, 255, 255, 20));
Graphics
类提供的drawLine(…)
方法
一切都很好,只是画每条线需要很多时间(50条线需要20秒以上…)。我甚至可以看到实时绘制的线条。一件奇怪的事情是水平线的绘制速度比垂直线快(几乎是瞬间)
我可能做错了什么。下面是网格的代码
public void drawGrid(Graphics g){
g.setColor(new Color(255, 255, 255, 20));
int width = getWidth();
int height = (int) (width * Utils.PLATE_RATIO);
int step = pixelSize*gridSpacing;
Color bright = new Color(255, 255, 255, 100);
Color transparent = new Color(255, 255, 255, 20);
for(int ix = insets.left + step;
ix < width; ix += step){
if(((ix - insets.left) / step) % 10 == 0){
g.setColor(bright);
}
else{
g.setColor(transparent);
}
g.drawLine(ix, insets.top, ix, height+insets.top);
}
for(int iy = insets.top+step;
iy < (insets.top + height); iy += step){
if(((iy - insets.top) / step) % 10 == 0){
g.setColor(bright);
}
else{
g.setColor(transparent);
}
g.drawLine(insets.left, iy, width + insets.left, iy);
}
}
public void drawGrid(图g){
g、 setColor(新颜色(255、255、255、20));
int width=getWidth();
内部高度=(内部)(宽度*最终板厚比);
int step=像素大小*网格间距;
颜色明亮=新颜色(255、255、255、100);
颜色透明=新颜色(255、255、255、20);
对于(int ix=插图左+步;
ix<宽度;ix+=步长){
如果(((ix-插图左)/步骤)%10==0){
g、 设置颜色(明亮);
}
否则{
g、 setColor(透明);
}
g、 抽绳(ix,插图顶部,ix,高度+插图顶部);
}
对于(int iy=插图顶部+台阶;
iy<(插图顶部+高度);iy+=台阶){
如果((iy-insets.top)/步骤)%10==0){
g、 设置颜色(明亮);
}
否则{
g、 setColor(透明);
}
g、 抽绳(插图左,iy,宽度+插图左,iy);
}
}
您发布的代码很好,没有问题。下面是使用您的方法(稍微简化)的组件的工作示例:
公共静态类MyGrid扩展了JComponent
{
私有整数步长=10;
公共MyGrid()
{
超级();
}
公共维度getPreferredSize()
{
返回新维度(500500);
}
受保护组件(图形g)
{
超级组分(g);
牵引格栅(g);
}
公共空心绘图网格(图形g)
{
int-width=getWidth();
intheight=getHeight();
颜色明亮=新颜色(255、255、255、200);
颜色透明=新颜色(255、255、255、100);
用于(int ix=步长;ix<宽度;ix+=步长)
{
如果((ix/步)%10==0)
{
g、 设置颜色(明亮);
}
其他的
{
g、 setColor(透明);
}
g、 抽绳(ix,0,ix,高度);
}
对于(int iy=步长;iy<高度;iy+=步长)
{
如果((iy/步)%10==0)
{
g、 设置颜色(明亮);
}
其他的
{
g、 setColor(透明);
}
g、 抽绳(0,iy,宽度,iy);
}
}
}
我想这段代码之外还有一些问题
附言,有点离题,但
我建议您计算绘画区域的可见部分(使用JComponent的getVisibleRect()
方法或Graphicsg.getClip().getBounds()
方法),并仅使用该区域限制绘画
如果组件非常大(例如,组件的面积为10000x1000像素),那么这种小优化可以加快组件的绘制速度。下面是我如何使用双缓冲解决问题的,正如@sureshKumar建议的那样。我只是在屏幕外的图像上画图,画图结束后只需调用
drawImage()
。这似乎奏效了
编辑:这似乎只有在您希望从paintComponent(…)
方法外部调用绘制方法(在我的例子中是drawGrid()
)时才有用
代码如下:
private Graphics bufferGraphics;
private Image offScreen;
private Dimension dim;
//other attributes not shown...
public CentralPanel(){
//Some initialization... (not shown)
//I added this listener so that the size of my rectangle
//and of my grid changes with the frame size
this.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
dim = getVisibleRect().getSize();
offScreen = createImage(dim.width, dim.height);
bufferGraphics = offScreen.getGraphics();
repaint();
revalidate();
}
//other methods of ComponentListener not shown
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(offScreen, 0, 0, null);
}
public void drawGrid(){
int width = dim.width - insets.left - insets.right;
width -= (width % plateSize.getXSize());
int height = (int) (width*Utils.PLATE_RATIO);
height -= (height % plateSize.getYSize());
int step = pixelSize*gridSpacing;
Color bright = new Color(255, 255, 255, 100);
Color transparent = new Color(255, 255, 255, 20);
for(int ix = insets.left + step;
ix < (width+insets.left); ix += step){
if(((ix - insets.left) / step) % 10 == 0){
bufferGraphics.setColor(bright);
}
else{
bufferGraphics.setColor(transparent);
}
//I am now drawing on bufferGraphics instead
//of the component Graphics
bufferGraphics.drawLine(ix, insets.top, ix, height+insets.top);
}
step *= Utils.PLATE_RATIO;
for(int iy = insets.top+step;
iy < (insets.top + height); iy += step){
if(((iy - insets.top) / step) % 10 == 0){
bufferGraphics.setColor(bright);
}
else{
bufferGraphics.setColor(transparent);
}
bufferGraphics.drawLine(insets.left, iy, width + insets.left, iy);
}
}
私有图形缓冲图形;
屏幕外的私人图像;
私有维度;
//其他属性未显示。。。
公共CentralPanel(){
//某些初始化…(未显示)
//我添加了这个侦听器,这样矩形的大小
//我的网格的大小随帧大小而变化
this.addComponentListener(新的ComponentListener(){
@凌驾
公共无效组件已恢复(组件事件e){
dim=getVisibleRect().getSize();
屏幕外=创建图像(尺寸宽度、尺寸高度);
bufferGraphics=屏幕外的.getGraphics();
重新油漆();
重新验证();
}
//未显示ComponentListener的其他方法
});
}
@凌驾
受保护组件(图形g){
超级组件(g);
g、 drawImage(屏幕外,0,0,空);
}
公共网格(){
int width=dim.width-insets.left-insets.right;
宽度-=(宽度%plateSize.getXSize());
内部高度=(内部)(宽度*最终板厚比);
高度-=(高度%plateSize.getYSize());
int step=像素大小*网格间距;
颜色明亮=新颜色(255、255、255、100);
颜色透明=新颜色(255、255、255、20);
对于(int ix=插图左+步;
ix<(宽度+插图左);ix+=步长){
如果(((ix-插图左)/步骤)%10==0){
bufferGraphics.setColor(明亮);
}
否则{
bufferGraphics.setColor(透明);
}
//我现在正在绘制缓冲区图形
//组件图形的设计
缓冲图形.抽绳(ix,插图顶部,ix,高度+插图顶部);
}
步骤*=最终板率;
对于(int iy=插图顶部+台阶;
iy<(插图顶部+高度);iy+=台阶){
如果((iy-insets.top)/步骤)%10==0){
bufferGraphics.setColor(明亮);
}
否则{
bufferGraphics.setColor(透明);
}
缓冲图形绘制线(插图左,iy,宽度+插图左,iy);
}
}
附言:如果这是对我的问题的编辑,请告诉我一个答案
private Graphics bufferGraphics;
private Image offScreen;
private Dimension dim;
//other attributes not shown...
public CentralPanel(){
//Some initialization... (not shown)
//I added this listener so that the size of my rectangle
//and of my grid changes with the frame size
this.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
dim = getVisibleRect().getSize();
offScreen = createImage(dim.width, dim.height);
bufferGraphics = offScreen.getGraphics();
repaint();
revalidate();
}
//other methods of ComponentListener not shown
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(offScreen, 0, 0, null);
}
public void drawGrid(){
int width = dim.width - insets.left - insets.right;
width -= (width % plateSize.getXSize());
int height = (int) (width*Utils.PLATE_RATIO);
height -= (height % plateSize.getYSize());
int step = pixelSize*gridSpacing;
Color bright = new Color(255, 255, 255, 100);
Color transparent = new Color(255, 255, 255, 20);
for(int ix = insets.left + step;
ix < (width+insets.left); ix += step){
if(((ix - insets.left) / step) % 10 == 0){
bufferGraphics.setColor(bright);
}
else{
bufferGraphics.setColor(transparent);
}
//I am now drawing on bufferGraphics instead
//of the component Graphics
bufferGraphics.drawLine(ix, insets.top, ix, height+insets.top);
}
step *= Utils.PLATE_RATIO;
for(int iy = insets.top+step;
iy < (insets.top + height); iy += step){
if(((iy - insets.top) / step) % 10 == 0){
bufferGraphics.setColor(bright);
}
else{
bufferGraphics.setColor(transparent);
}
bufferGraphics.drawLine(insets.left, iy, width + insets.left, iy);
}
}