1

我基本上是在尝试通过调用第二个组件的绘画并将第一个组件的图形传递给它来在另一个内部绘制一个 JComponent。

我正在尝试创建一个 GUI 编辑器,(重新发明轮子,我知道,这只是一个概念证明)所以我有一个扩展 JPanel 的类,我想从 VectorControls 中绘制组件。

到目前为止,我在扩展的 JPanel 中得到了这个方法:

@SuppressWarnings("serial")
public class Sketch extends JPanel {
    private Vector<JComponent> controls = new Vector<JComponent>();

    public Sketch() {
        super();
        this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
    }

    public void addControl(JComponent c) {
        Dimension d = new Dimension(100,50);
        c.setPreferredSize(d);
        c.setMinimumSize(d);
        c.setMaximumSize(d);
        controls.add(c);
        this.repaint();
        this.revalidate();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(int i=controls.size()-1; i>=0; i--) {
            JComponent c = controls.get(i);
            c.paint(g);
        }       
    }
}

我正在构建/附加这样的草图面板:

public GUIEditor() {
  mainFrame = new JFrame("GUI EDITOR");
  mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  Sketch mainPanel = new Sketch();
  mainPanel.setPreferredSize(new Dimension(640,480));

  GridBagLayout gbl = new GridBagLayout();
  GridBagConstraints gbc = new GridBagConstraints();

  mainFrame.setLayout(gbl);

  JPanel toolsPanel = new JPanel();
  toolsPanel.setPreferredSize(new Dimension(160,480));
  toolsPanel.setLayout(new GridLayout(0,1));      

  for(Control c : toolBoxItems ) {
      AbstractAction action = new ToolBoxButtonAction(mainPanel, c.type);
      JButton b = new JButton(action);
      b.setText(c.title);
      toolsPanel.add(b);
  }

  gbc.gridx = 0;
  gbc.gridy = 0;
  gbl.setConstraints(mainPanel, gbc);
  mainFrame.add(mainPanel);

  gbc.gridx = 1;
  gbc.gridy = 0;
  gbl.setConstraints(toolsPanel, gbc);
  mainFrame.add(toolsPanel);

  mainFrame.pack();
  mainFrame.setLocationRelativeTo(null);
  mainFrame.setVisible(true);
}

在 ToolBoxButtonAction 内部,基本上我正在这样做:

public void actionPerformed(ActionEvent e) {
    try {
        sketch.addControl(control.newInstance());
    } catch (InstantiationException e1) {
        e1.printStackTrace();
    } catch (IllegalAccessException e1) {
        e1.printStackTrace();
    }
}

但我写这个是因为它不起作用。

关于如何实现这一目标的任何想法?

4

2 回答 2

4

我基本上是在尝试通过调用第二个组件的绘画将第一个组件的图形传递给它来在另一个内部绘制一个 JComponent。

只有当组件具有非零大小时,才能绘制组件。通常,组件的大小由布局管理器确定。

您的基本代码看起来很合理,但除非您有代码来调整大小和定位组件,否则您将看不到任何东西。如果您只是设置大小,那么所有组件将在彼此之上绘制。

或者问题可能是您的父面板没有尺寸,因此甚至没有绘制。默认 FlowLayout 使用子组件的首选大小来确定面板大小。由于您不直接将组件添加到面板,因此没有子组件,因此首选大小将为 0。当您重新发明轮子时,您需要重新发明一切。

如果没有 SSCCE,我们只能猜测您如何使用此代码的上下文。

编辑:

当您遇到问题时创建一个 SSCCE,并在尝试使其动态工作之前使其使用硬编码值。就像是:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class Sketch extends JComponent
{
    private Vector<JComponent> controls = new Vector<JComponent>();

    public void addControl(JComponent c)
    {
        c.setSize(100, 50);
        int location = controls.size() * 50;
        c.setLocation(location, location);
        controls.add(c);
        repaint();
    }

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

        for(int i=controls.size()-1; i>=0; i--)
        {
            JComponent c = controls.get(i);
            Point location = c.getLocation();
            g.translate(location.x, location.y);
            c.paint(g);
            g.translate(-location.x, -location.y);
        }
    }

    private static void createAndShowUI()
    {
        Sketch sketch = new Sketch();
        sketch.addControl( new JButton("button") );
        sketch.addControl( new JTextField(10) );
        sketch.addControl( new JCheckBox("Checkbox") );

        JFrame frame = new JFrame("Sketch");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( sketch );
        frame.setSize(400, 400);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}
于 2013-05-10T15:06:05.887 回答
2

前段时间,我为此类任务编写了一个框架。也许您觉得它很有用(该库是开源的):

教程:

http://softsmithy.sourceforge.net/lib/current/docs/tutorial/swing/customizer/index.html

Java 文档:

http://softsmithy.sourceforge.net/lib/current/docs/api/softsmithy-lib-swing-customizer/index.html

有关最新版本的信息:

http://puces-blog.blogspot.ch/2012/11/news-from-software-smithy-version-03.html

于 2013-05-10T14:33:29.260 回答