【问题标题】:Java Graphics setColor does not workJava 图形 setColor 不起作用
【发布时间】:2016-07-02 10:06:51
【问题描述】:

我正在尝试在JFrame 中使用Canvas 来实现Julia Set 的情节。出于某种原因,setColor() 似乎不起作用。这是负责的代码:

@Override
public void paint(Graphics aGraphics) 
{
    // store on screen graphics
    Graphics cScreenGraphics = aGraphics;
    // render on background image
    aGraphics = m_cBackGroundImage.getGraphics();

    for(int i = 0; i < m_iWidth; i++) 
    {
        for(int j = 0; j < m_iHeight; j++) 
        {
            int r = m_iPixelRed[i][j];
            int g = m_iPixelGreen[i][j];
            int b = m_iPixelBlue[i][j];
            aGraphics.setColor(new Color(r, g, b));
            aGraphics.drawRect(i, j, 0, 0);
        }
    }
    // rendering is done, draw background image to on screen graphics
    cScreenGraphics.drawImage(m_cBackGroundImage, 1, 1, null);
}

起初我怀疑这些值没有正确传递给m_iPixel...,所以我在调用函数中将这些值硬编码为0xff。我通过rgb 进行了检查,并确定它们都设置为该值,但画布是黑色的。

有趣的是:当我输入aGraphics.setColor(Color.WHITE)aGraphics.setColor(0xff, 0xff, 0xff) 而不是变量rgb 时,它可以工作!即使我检查了变量是否具有相同的值,并且之前将它们硬编码为0xff。我完全不知道可能是什么问题......

编辑:

这些值被硬编码如下:

public void setPixelColour(int i, int j, int r, int g, int b)
{
    m_iPixelRed[i][j] = 0xff;
    m_iPixelGreen[i][j] = 0xff;
    m_iPixelBlue[i][j] = 0xff;
}

setPixelColour在这个方法中被超类调用:

private void calcColour(int i, int j, int aIterations)
{
    m_cCanvas.setPixelColour(i, j, 0XFF, 0xff, 0XFF);
}

这个循环又调用了它。

for(int i = 0; i < iCanvasHeight; i++){
    for(int j = 0; j < iCanvasWidth; j++){
        cSum.setRe(m_cCoordPlane[i][j].getRe());
        cSum.setIm(m_cCoordPlane[i][j].getIm());
        m_iIterations[i][j] = 0;
        do{
            m_iIterations[i][j]++;
            cSum = cSum.square();
            cSum = cSum.add(m_cSummand);
            m_dAbsSqValues[i][j] = cSum.getAbsSq();
        }while((m_iIterations[i][j] < MAXITER) && (m_dAbsSqValues[i][j] < m_iDivergThresh));
        this.calcColour(i, j, m_iIterations[i][j]);
        m_cMsgIter = "x = " + i + " , y = " + j;
        this.repaint();
    }
}

我检查并确保这个循环确实完成了。我在setColor() 之前使用调试器再次检查了这些值。由于我不信任调试器(缺乏经验),我再次检查了控制台,在 setColor() 之前添加了 System.out.println("r = " + Integer.toString(r) + " g = " + Integer.toString(g) + " b = " + Integer.toString(b));

编辑:

这是我JFrame的绘制方法:

public void paint(Graphics aGraphics) 
{
    Graphics cScreenGraphics = aGraphics;
    // render on background image
    aGraphics = m_cBackGroundImage.getGraphics();

    this.paintComponents(aGraphics);
    // drawString() calls are debug code only...
    aGraphics.setColor(Color.BLACK);
    aGraphics.drawString(m_cSMsg, 10, 450);
    aGraphics.drawString(m_cMsgIter, 10, 465);
    aGraphics.drawString(m_cMsgDivThresh, 10, 480);

    // rendering is done, draw background image to on screen graphics
    cScreenGraphics.drawImage(m_cBackGroundImage, 0, 0, null);
}

【问题讨论】:

  • 你能展示你如何检查变量内容的代码吗?或者你是如何对它们进行硬编码的?
  • @Mr.M 当然,我编辑了上面的代码。
  • @Mr.M 好的,我找到了解决方案,但不是错误的原因。当我将this.repaint() 更改为m_cCanvas.repaint() 时(呃,显然......)它可以工作。虽然这并没有改变m_cCanvas::paint() 使用r == 0xff, g == 0xff, b == 0xff 调用的事实,但这并不会改变屏幕的颜色。知道这怎么可能吗?
  • 好的,所以我尽可能地复制了您的代码并尝试自己查看。使用硬编码版本,我确实得到了一张白色的画布。显然我无法真正测试其他版本。但我没有遇到 r、g 和 b 的值与被绘制到屏幕上的值不同的情况。 (这让我相信错误一定出在其他地方)
  • 您应该考虑使用 drawLine() 而不是 drawRect() 来绘制单个像素。

标签: java swing canvas graphics awt


【解决方案1】:

不确定在 cmets 中发布大块代码是否有意义,所以这是我的测试代码:

package test;

import javax.swing.JFrame;

public class Test 
{
    public static void main(String[] args) 
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        MyCanvas canvas = new MyCanvas();
        frame.add(canvas);
        frame.pack();
        frame.setVisible(true);

        for(int i = 0; i < 800; i++)
        {
            for(int j = 0; j < 600; j++)
            {
                canvas.setPixelColour(i, j, 0XFF, 0xff, 0XFF);
                canvas.repaint();
            }
        }
    }
}

这是 MyCanvas 类:

package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class MyCanvas extends java.awt.Canvas
{
    private BufferedImage m_cBackGroundImage;
    private int[][] m_iPixelRed, m_iPixelGreen, m_iPixelBlue;
    private int m_iWidth, m_iHeight;

    public MyCanvas()
    {
        setPreferredSize(new Dimension(800, 600));
        m_iWidth = 800;
        m_iHeight = 600;
        m_cBackGroundImage = new BufferedImage(m_iWidth, m_iHeight, BufferedImage.TYPE_INT_ARGB);     
        m_iPixelRed = new int[m_iWidth][m_iHeight];
        m_iPixelGreen = new int[m_iWidth][m_iHeight];
        m_iPixelBlue = new int[m_iWidth][m_iHeight];
    }

    public void paint(Graphics aGraphics) 
    {
        Graphics cScreenGraphics = aGraphics;

        aGraphics = m_cBackGroundImage.getGraphics();

        for(int i = 0; i < m_iWidth; i++) 
        {
            for(int j = 0; j < m_iHeight; j++) 
            {
                int r = m_iPixelRed[i][j];
                int g = m_iPixelGreen[i][j];
                int b = m_iPixelBlue[i][j];
                aGraphics.setColor(new Color(r, g, b));
                aGraphics.drawRect(i, j, 0, 0);
            }
        }

        cScreenGraphics.drawImage(m_cBackGroundImage, 1, 1, null);
    }

    public void setPixelColour(int i, int j, int r, int g, int b)
    {
        m_iPixelRed[i][j] = r;
        m_iPixelGreen[i][j] = g;
        m_iPixelBlue[i][j] = b;
    }
}

我尝试尽可能接近您提供的内容(即使您的命名约定并不是我真正喜欢的)。主要更改在 main 方法的循环中,因为我不需要大部分代码。我还删除了 calcColor 方法,因为它只是调用了不同的方法。

无论如何,这对我有用(= 我得到了一张白色的画布)。我还尝试将 0xff 更改为 (int)(Math.random() * 255) 这将导致...让我们使用彩虹色的画布,所以它似乎工作正常。

【讨论】:

  • 非常感谢。我可以看到你确实使用了canvas.repaint(),我发现它也为我解决了这个问题。当我不小心调用了 this.repaint() from inside the extended JFrame` 类(嵌套的 for 循环在其中)时,canvas.paint() 方法也被调用了,RGB 值设置为 0xff,但画布并没有改变它的颜色。调用canvas.repaint() 解决了这个问题,但即使我在canvas.paint() 内部使用正确的参数进行调试,画布保持相同的颜色仍然没有意义。
  • 顺便说一句,我已经习惯了命名约定,因为在我工作的公司是代码指南 :) 我开始认为它非常好,很有帮助。但我们主要将 C/C++ 用于嵌入式项目。
  • this.repaint() 中的“this”是什么?因为如果我调用 frame.repaint() 它的工作原理都是一样的 ;) 这就是我开始的方式,然后我更改为 canvas.repaint() 以查看它是否仍然有效并忘记将其改回 ^^
  • 另外:我并不是不明白你为什么要这样命名你的变量,只是我觉得它总是让代码看起来比实际上更复杂;)在另一个注意:为什么m_cBackGroundImage是m_c? m 代表成员,c 不应该代表角色吗?
  • 我调用this.repaint()是因为调用this.repaint()的方法是扩展JFrame的类内部的方法,但我应该调用canvas.repaint()。它是m_c因为我们滥用它作为类类型的 c 前缀而不是原语。可以更好,我知道:)
猜你喜欢
  • 2014-05-16
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 2014-05-03
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多