绘制在另一个类中创建的paintComponent对象

时间:2014-02-13 15:02:56

标签: java swing paintcomponent graphics2d repaint

对于大学作业,我正在制作解决旅行商问题的Java实现。我将删除大部分代码,使其不那么“繁忙”,但如果它不再有意义,请告诉我。 为了使它工作,我有一个用所有UI绘制窗口的类;

//suitable imports
public class Window extends JFrame implements ActionListener
{
    int gridX = 0;
    int gridY = 0;
    String[] xyLength = 
    {
        "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", 
        "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
        "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
        "31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
        "41", "42", "43", "44", "45", "46", "47", "48", "49", "50"
    };
    Canvas canvas = new Canvas();
    JPanel mainPanel = new JPanel(); 

    JPanel westPanel = new JPanel(); //Panel on the left which houses controls
    JComboBox<String> xSelectComboBox = new JComboBox<String>(xyLength);
    JComboBox<String> ySelectComboBox = new JComboBox<String>(xyLength);
    JButton redrawButton = new JButton(“Redraw”);
    JButton generateButton = new JButton(“Generate”);

    public static void main(String[] args)
    {
        new Window();
    }

    public Window()
    {
        super(“Travelling Salesman Problem”);
        setSize(900, 620);
        setResizeable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        mainPanel.setLayout(new BorderLayout());

        mainPanel.add(canvas, BorderLayout.CENTER);

        westPanel.add(xSelectComboBox);
        westPanel.add(ySelectComboBox);
        redrawButton.addActionListener(this);
        westPanel.add(redrawButton);
        generateButton.addActionListener(this);
        westPanel.add(generateButton);
        mainPanel.add(westPanel, BorderLayout.WEST);

        add(mainPanel);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e)
    {
        Object source = e.getSource();
        if(source.equals(redrawButton)
        {
            gridX = Integer.parseInt((xSelectComboBox.getSelectedItem()).toString());
            gridY = Integer.parseInt((ySelectComboBox.getSelectedItem()).toString());
            canvas.setXLength(gridX);
            canvas.setYLength(gridY);
            canvas.repaint();
        }
        if(source.equals(generateButton))
        {
            Algorithms.randomRoute(gridX, gridY);
        }  
    }
}

我还有Canvas类,它包含paint组件;

//suitable imports
public class Canvas extends JPanel
{
    int process = 0;
    int xLength;
    int yLength;
    Node point = new Node();

    public Canvas()
    {
        xLength = 0;
        yLength = 0;
    }

    public void setProcess(int set)
    {
        process = set;
    }

    public void setXLength(int x)
    {
        xLength = x;
    }

    public void setYLength(int y)
    {
        yLength = y;
    }

    public setNode(Node n)
    {
        point.copy(n)
    }

    public void paintComponent(Graphics g)
    {
        super paintComponent(g);
        switch(process)
        {
            case 0:
                drawGrid(g);
                break;
            case 1:
                point.draw(g);
                break;
        }
    }

    public void drawGrid(Graphics g)
    {
        //draws a grid based upon xLength and yLength
    }
}

第三,我有一个节点对象,我希望在那里有一个draw(g)方法;

//suitable imports
public class Node
{
    protected int xCoordinate;
    protected int yCoordinate;
    protected boolean visitedFlag;

    //skipping constructors, sets and gets
    public void draw(Graphics g)
    {
        g.setColor(Color.red);
        g.fillArc(xCoordinate, yCoordinate, 6, 6, 0 ,360);
    }
}

最后我有一个算法类,它将包含解决问题的所有不同算法,包括随机路由生成器;

//suitable imports
public class Algorithms
{
    public void randomRoute(int xMax, int yMax)
    {
        nodeMax = 10;
        Node[] point = new Node[nodeMax];
        Random rand = new Random();
        for(int i = 0; i < nodeMax; i++)
        {
            point[i] = new Node();
            point[i].setXCoordinate(rand.nextInt(xMax);
            point[i].setYCoordinate(rand.nextInt(yMax);
            //insert drawing point[i] here
        }        
    }
}

问题是,我想将我的处理代码与Window类分开,但是能够在Window中声明的Canvas实例上绘制。 我还需要能够刷新paintComponent中包含的内容。

代码中的任何小问题都是我为问题重新输入的结果

感谢。

编辑: 所以我修改了Canvas(现在的MyCanvas)类方法setProcess;

public void setProcess(int set)
{
    process = set;
    repaint();
}

我也可以接受一组节点;

public void setNode(Node[] n, int nodesMax)
{
    point = new Node[nodesMax];
    nodeMax = nodesMax;
    for(int i = 0; i < nodeMax - 1; i++)
    {
        point[i] = new Node();
        point[i].copy(n[i]);
    }
}

最后,我还更改了paintComponent中的switch case语句;

switch(process)
{
    case 1:
        drawGrid(g, this.xLength + 1, this.yLength + 1);
        process = 0;
        break;
    case 2:
        g.setColor(Color.red);
        for(int i = 0; i < nodeMax; i++)
        {
            g.fillArc((this.point[i].xCoordinate + 30), (this.point[i].yCoordinate + 30), 100, 100, 0, 360);
        }
        process = 0;
        break;
}

但是,setProcess中的repaint()不会重新运行paintComponent。 我出错的任何想法?

1 个答案:

答案 0 :(得分:0)

请勿致电您的班级Canvas。这个名称的AWT类已经存在,因此使用相同的名称会引起混淆。

  

但是能够在Window中声明的Canvas实例上绘制。

不要在另一个类中外部绘图。

相反,如果要对MyCanvas类进行更改,则需要引用该类,并且需要创建允许根据需要添加/删除节点的方法。然后addNode / removeNode方法只会调用repaint(),而MyCanvas类将重新绘制自己。

编辑:

process = set;
repaint();
process = 0;

你不能使用这样的逻辑。您无法控制何时完成组件的绘制。 repaint()方法调用RepaintManager,它将在适当的时间进行绘制。因此,在调用paintComponent()方法时,流程变量将为0.只需在代码中添加System.out.println(...)语句即可验证。

一套的目的???方法是更改​​类的属性。所以只保留值,不要将其重置为0.