4

我有一个基于模型-视图-控制器范式的项目,但在让它正常工作方面遇到了很多麻烦。

该程序有 4 个面板,它们应该允许我以各种方式修改在屏幕上绘制的椭圆。这些似乎工作正常,经过相当多的麻烦后,我能够让它们显示在包含整个 shebang 的 JFrame 中。我已经设法通过脱离提供的说明来显示它们,但是当我这样做时,我似乎无法更新椭圆形。但是,如果我按照信中的说明进行操作,我只会看到一个空框。

该项目有非常具体的方向,我跟进了一点,但有些文档不清楚。我认为我缺少的东西一定很简单,因为没有什么是没有意义的。我不得不承认,虽然我的 Java 经验是有限的,而我在 GUI 设计/范式方面的经验更是如此。

无论如何,我一直在搜索网络和这个网站,试图找出问题所在,但这是一个有点具体的例子,老实说,我对此知之甚少,无法概括我在网上找到的任何答案和找出缺少的东西。我已经研究这段代码太久了,所以我真的希望有人能帮助我。

public class Model {
    private Controller controller;
    private View view;
    private MvcFrame mvcFrame;

    private int radius = 44;
    private Color color = Color.BLUE;
    private boolean solid = true;

    //bunch of mutators and accessors for the above variables

    public Model() {
        controller = new Controller(this);
        view = new View(this);
        mvcFrame = new MvcFrame(this);
    }
}

这是模型类。这似乎相当简单。我认为我对这里发生的事情的理解是可靠的,并且似乎没有任何问题。主要用于上下文。

public class Controller extends JPanel{
    private Model model;

    public Controller(Model model) {
        this.model = model;
        setBorder(BorderFactory.createLineBorder(Color.GREEN));
        setLayout(new GridLayout(4,1));
        add(new RadiusPanel(model));
        add(new ColorPanel(model));
        add(new SolidPanel(model));
        add(new TitlePanel(model));
    }
}

这是控制器类。据我所知,setBorder、setLayout 和一系列添加在这里什么都不做。我让他们注释掉了,但这是说明告诉我做事的方式,所以要么那里有错误,要么我的设置有问题。但是,当我这样做时,我会得到一个空窗口(JFrame),但没有任何面板会出现在其中。我为解决这个问题所做的是将这些添加函数放在 mvcFrame 类中:

public class MvcFrame extends JFrame {
    private Model model;

    public MvcFrame(Model model){
        this.model = model;
        //setLayout(new GridLayout(4,1));
        //add(new RadiusPanel(model));
        //add(new ColorPanel(model));
        //add(new SolidPanel(model));
        //add(new TitlePanel(model));

        //add(new View(model));


        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setSize(800,600);
        setVisible(true);
    }
}

所以这就是事情开始变得奇怪的地方。注释掉的第一块代码与 Controller 类中的代码相同。我把它注释掉的原因是因为这只是一个幸运的猜测——根据说明,它不应该是那样的。然而,这确实可以让面板显示出来——但那时我还在扯头发,试图让椭圆形显示出来。

另一条注释行( add(new View(model)); )是使事情正常进行的不同尝试。在这种情况下,我将这些添加函数放在 View 类中(参见下面注释掉的代码)。这实际上可以同时显示椭圆形和面板,但是该方法不允许我更新椭圆形。此外,虽然我刚刚展示了椭圆形,但我似乎无法弄清楚究竟是什么导致了这种情况发生,而且我似乎无法让它回来。

public class View extends JPanel{
private Model model;

    public View(Model model) {
        this.model = model;
        //setLayout(new GridLayout(4,1));
        //add(new RadiusPanel(model));
        //add(new ColorPanel(model));
        //add(new SolidPanel(model));
        //add(new TitlePanel(model));

        repaint();
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        //center of view panel, in pixels:
        int xCenter = getWidth()/2;
        int yCenter = getHeight()/2;

        int radius = model.getRadius();
        int xStart = xCenter - radius;
        int yStart = yCenter - radius;
        int xWidth = 2 * radius;
        int yHeight = 2 * radius;
        g.setColor(model.getColor());

        g.clearRect(0, 0, getWidth(), getHeight());

        if (model.isSolid()){
            g.fillOval(xStart, yStart, xWidth, yHeight);
        } else {
            g.drawOval(xStart, yStart, xWidth, yHeight);
        }        
    }
}

有点像以前的想法 - 注释掉的代码是我添加的东西,试图让事情正常工作,但不是基于提供的方向。在没有注释的情况下,我有 add(new View(model)); mvcFrame 行中的行也未注释。

各种面板类(SolidPanel、ColorPanel 等)只是扩展了一个名为 ControlPanel 的类,它扩展了 JPanel。这些似乎都按预期工作,对它们没有太大问题。还有一个启动 GUI 的驱动程序。这似乎也按预期工作。

我遇到的主要问题是我无法显示椭圆形,有一次我可以让它显示出来,但似乎没有任何改变它的选项。我觉得我已经很接近了,但在这一点上,我对其他事情的尝试感到茫然。

任何能提供帮助的人都会有我最诚挚的感谢。

4

3 回答 3

2

这是一个非常仓促的重写,“只是为了让它工作”。

main.java

public class main {
    public static void main(String[] args) {
        // The JFrame could be created here, since it lasts the life
        // of the program.

        //...then, later, the model.
        Model mdl = new Model();    

        // ...and then move on to applying the view and control to the frame.
    }
}

控制器.java

// Nothing interesting here, added for consistency.
public class Controller {
    private final Model model;

    public Controller(Model model) {
        // The frame is shown automatically in the model here.
        this.model = model;

        // The frame's setVisible is a control issue, should be called
        // from in here, not automatically in the model.
    }
}

MvcFrame.java

import javax.swing.JFrame;

public class MvcFrame extends JFrame {
    private final Model model;

    public MvcFrame(Model model){
        this.model = model;
        // Anytime you add anything to a JFrame, use the content pane.
        this.getContentPane().add(model.getView());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // This line centers the frame on your screen.
        setLocationRelativeTo(null);
        setSize(800,600);
        // The frame won't paint until it's visible.
        // This means if you check dimensions, everything will be 0 x 0
        // until this line is called.
        setVisible(true);
    }
}

模型.java

import java.awt.Color;

public class Model {
    private final Controller controller;  // Not used yet
    private final View view;
    private final MvcFrame mvcFrame; // Not used yet

    // Mutators and accessors needed for these guys (set/get)
    private final int radius = 44;
    private final Color color = Color.BLUE;
    private final boolean solid = true;

    public Model() {
        controller = new Controller(this);
        view = new View(this);
        mvcFrame = new MvcFrame(this);
    }

    public View getView() {
        return view;        
    }

    public int getRadius() {
        return radius;      
    }

    public Color getColor() {
        return color;       
    }

    public boolean isSolid() {
        return solid;       
    }
}

查看.java

import java.awt.Graphics;
import javax.swing.JPanel;

public class View extends JPanel{
    private final Model model;

    public View(Model model) {
        this.model = model;
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        //center of view panel, in pixels:
        int xCenter = getWidth()/2;
        int yCenter = getHeight()/2;

        int radius = model.getRadius();
        int xStart = xCenter - radius;
        int yStart = yCenter - radius;
        int xWidth = 2 * radius;
        int yHeight = 2 * radius;
        g.setColor(model.getColor());

        g.clearRect(0, 0, getWidth(), getHeight());

        if (model.isSolid()){
            g.fillOval(xStart, yStart, xWidth, yHeight);
        } else {
            g.drawOval(xStart, yStart, xWidth, yHeight);
        }        
    }
}
于 2012-12-06T05:00:56.100 回答
1

您的问题有点杂乱无章,我不确定您为什么注释掉代码的关键部分,但第一个问题是:

//add(new View(model));

您是否将视图添加到框架中?椭圆形可以画得很好,但没有添加视图。


这段代码最有可能出现问题:

public class MvcFrame extends JFrame {
    ...

    public MvcFrame(Model model){
        ...
        //setLayout(new GridLayout(4,1));
        //add(new RadiusPanel(model));
        ...
    }
}

直接调用时add,它引用超类(JFrame)。不幸的是,JFrames 是偷偷摸摸的,因为它们有一个contentPane保存布局的框架。进一步偷偷摸摸:该内容窗格是一个空布局,只能通过放入您自己的面板来更改。

所以,你可能应该做这样的事情。即使您不完全遵循,这些方法也应该对您有很大帮助:

...
JPanel pnl = new JPanel(new GridLayout(4, 1));
this.setContentPane(pnl);
pnl.add(new RadiusPanel(model));
...

如果您不想明确设置内容窗格,可以使用this.getContentPane().add(foo).

空布局问题也可能影响您的椭圆绘图,因为当您添加 JPanel 时,未指定其大小,因此默认为(0,0).


另外,不确定您的控制器为什么扩展 JPanel。您的视图应该对控制器可用,并且应该是其中唯一包含任何摆动组件的视图。

于 2012-12-06T04:42:12.853 回答
0

尽管我遇到了不同的问题,但考虑到的问题是:

g.clearRect(0, 0, getWidth(), getHeight());

在我的项目中为我解决了所有问题,因为它没有抹去之前的 Oval,所以我只能看到更大的变化。谢谢你。

于 2013-04-30T15:03:26.107 回答