【问题标题】:Painting a rectangle on a button click using JPanel使用 JPanel 在单击按钮时绘制矩形
【发布时间】:2014-09-24 20:36:46
【问题描述】:

我正在尝试使用 JPanel 绘制一个矩形。问题是,当我单击一个菜单项时,它应该绘制一个新矩形。但是,当我这样做时,只画了一部分。这就是我的意思:

    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            squares.addSquare(10, 10, 100, 100);
        }
    });

这样做:

但是当我将 squares.addSquare(...) 放在 ActionListener 的外部时,它会给出正确的形状(只是不是在我想要的时候)

    squares.addSquare(10, 10, 100, 100);
    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            //nothing on click...
        }
    });

这是正确的矩形:

知道为什么当我将它放入 ActionListener 时它不能正确绘制吗?谢谢。

完整代码

class UMLWindow extends JFrame {
Squares squares = new Squares();

private static final long serialVersionUID = 1L;

public UMLWindow() {
    addMenus();
}

public void addMenus() {

    getContentPane().add(squares);
    //squares.addSquare(10, 10, 100, 100);

    JMenuBar menubar = new JMenuBar();

    JMenu file = new JMenu("File");
    file.setMnemonic(KeyEvent.VK_F);

    JMenu shapes = new JMenu("Shapes");
    file.setMnemonic(KeyEvent.VK_F);

    JMenuItem rectangleMenuItem = new JMenuItem("New Rectangle");
    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            squares.addSquare(10, 10, 100, 100);
        }
    });

    shapes.add(rectangleMenuItem);

    menubar.add(shapes);

    setJMenuBar(menubar);

    setTitle("UML Editior");
    setSize(300, 200);
    setLocationRelativeTo(null);
}


}

class Squares extends JPanel {
private static final long serialVersionUID = 1L;

private List<Rectangle> squares = new ArrayList<Rectangle>();

public void addSquare(int x, int y, int width, int height) {
    Rectangle rect = new Rectangle(x, y, width, height);
    squares.add(rect);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setOpaque(true);
    this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    for (Rectangle rect : squares) {
        g2.draw(rect);
    }
}

}

【问题讨论】:

  • @Bene:请回答。贝尼?你去哪儿了?
  • 是的,这行得通。如果它成为答案,我会接受
  • @Harry 如果 Bene 没有回来,请自行回答
  • 我猜有人建议调用重绘?另外,不要从 paintComponent 方法中更改组件的状态,这可能会导致触发另一个重绘......一遍又一遍......
  • @MadProgrammer 你能详细说明一下吗?你的意思是不要设置背景颜色等?

标签: java swing jpanel paintcomponent


【解决方案1】:

Swing 使用被动渲染引擎,所以它不知道何时应该更新/重绘组件,除非你告诉它。

首先从您的addSquare 方法中调用repaint...

public void addSquare(int x, int y, int width, int height) {
    Rectangle rect = new Rectangle(x, y, width, height);
    squares.add(rect);
    repaint();
}

这将向重绘管理器发出请求,通知它当前组件需要重绘。

您还应该为您的组件提供大小提示,因此布局管理器将其大小设置为0x0

考虑重写Squares 类的getPreferredSize 方法并返回适当的默认大小...

@Override
public Dimension getPreferredSize() {
    return new Dimension(300, 200);
}

这也意味着您可以在主窗口中调用pack,它会“打包”自己的内容,非常整洁。

另外,不要调用会改变组件或其他组件状态或安排额外的repaint 请求的方法,因为这可能会设置一个无限循环的重绘,这会耗尽您的 PC 资源... .

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // This is bad...
    //this.setOpaque(true);
    // This is bad...
    //this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    for (Rectangle rect : squares) {
        g2.draw(rect);
    }
}

不透明度和颜色等内容应在绘制周期之外定义。此外,从JPanel 扩展的组件默认情况下是不透明的;)

【讨论】:

  • 感谢您的帮助:)
  • @Harry 不用担心,很高兴它有用
猜你喜欢
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多