我基本上是试图通过调用第二个组件的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();
}
}
但我写这篇文章是因为它不起作用。
关于如何实现这一目标的任何想法?
答案 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)
前段时间,我为这些任务编写了一个框架。也许你觉得它很有用(图书馆是开源的):
教程:
http://softsmithy.sourceforge.net/lib/current/docs/tutorial/swing/customizer/index.html
的Javadoc:
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