使用其图形在另一个内部绘制控件

时间:2013-05-10 14:27:22

标签: java swing user-interface controls awt

我基本上是试图通过调用第二个组件的paint将第一个组件的Graphics传递给另一个组件中的一个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);
        }       
    }
}

我正在构建/附加Sketch面板,如下所示:

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();
    }
}

但我写这篇文章是因为它不起作用。

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

2 个答案:

答案 0 :(得分:4)

  

我基本上是试图通过调用第二个组件的paint将第一个组件的Graphics传递给另一个组件中的一个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();
            }
        });
    }
}

答案 1 :(得分:2)