使用Swing组件在JavaSwing中制作一个简单的GUI编辑器

使用Swing组件在JavaSwing中制作一个简单的GUI编辑器,java,swing,user-interface,editor,jcomponent,Java,Swing,User Interface,Editor,Jcomponent,我目前正在从事一个项目,在这个项目中,我需要一个非常简单的编辑器来处理类似GUI的对象。这个编辑器将是一个画布,在上面可以放置众所周知的GUI小部件。例如,可以将按钮和文本字段放在上面,移动它们并调整它们的大小。不需要与小部件本身进行交互 我一直在尝试通过修改一个非常简单的绘画教程来实现这一点,我认为用这种方式实现它会很容易,但在画布上绘制自定义形状和文本以及拖放这些形状时,我遇到了许多问题 我想知道是否可以在JPanel上重用真正的Swing小部件,让用户放置、移动并调整它们的大小。如果是,我

我目前正在从事一个项目,在这个项目中,我需要一个非常简单的编辑器来处理类似GUI的对象。这个编辑器将是一个画布,在上面可以放置众所周知的GUI小部件。例如,可以将按钮和文本字段放在上面,移动它们并调整它们的大小。不需要与小部件本身进行交互

我一直在尝试通过修改一个非常简单的绘画教程来实现这一点,我认为用这种方式实现它会很容易,但在画布上绘制自定义形状和文本以及拖放这些形状时,我遇到了许多问题

我想知道是否可以在JPanel上重用真正的Swing小部件,让用户放置、移动并调整它们的大小。如果是,我应该调查哪些事情


我知道这可能看起来信息很少,但老实说,我一直在寻找解决方案。

这听起来像一个有趣的项目


我肯定会使用JPanel作为容器,布局设置为null。为了能够在容器中移动诸如JButton、JLabel之类的组件,您必须在添加的组件上侦听MouseListener和MouseMotionListener事件,并相应地处理它们。每当一个组件被移动或调整大小时,您必须在容器上调用validate()和repaint()。

我将采用混合方法实现这一点:创建一个实现鼠标响应(拖动、调整大小)的类。此类负责管理用户交互

对于组件的实际绘制,请使用真实的Swing组件(用户交互类将引用其应该表示的组件,并将实际渲染委托给该组件)


这种方法避免了扩展原始Swing组件时出现的大多数复杂性,但您仍然可以重用它们的所有绘制代码。

我想我应该记住以前Swing的好日子,并为您编写一个概念证明来给您带来一点乐趣。它支持在主面板上添加一个按钮,然后进行移动和一些基本的调整大小

这只是一个概念证明,但它回答了你已经有很多问题。我在那里添加了一些待办事项,例如,您将知道下一步要做什么

享受

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;

public class UIBuilder {
  private static final int NONE = -1;

  private static final int BORDER = 3;

  private JFrame frame = new JFrame("Builder");

  private JToolBar toolbar = new JToolBar();

  private JPanel main = new JPanel();

  private int startX = NONE;

  private int startY = NONE;

  private int prevX = NONE;

  private int prevY = NONE;

  private boolean resize = false;

  public UIBuilder() {
    frame.setBounds(100, 100, 600, 450);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(toolbar, BorderLayout.PAGE_START);
    frame.getContentPane().add(main, BorderLayout.CENTER);
    frame.setVisible(true);
    buildToolbox();
    buildMainPanel();
  }

  private void buildToolbox() {
    JButton button = new JButton("Button");
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        JButton btn = new JButton("Button");
        addComponent(btn);
      }
    });
    toolbar.add(button);
  }

  private void buildMainPanel() {
    main.setLayout(null);
  }

  private void addComponent(JComponent comp) {
    comp.setBounds(10, 10, 80, 24);

    comp.addMouseListener(new MouseAdapter() {
      public void mouseReleased(MouseEvent e) {
        startX = NONE;
        startY = NONE;
        ((JComponent) e.getSource()).setCursor(Cursor.getDefaultCursor());
      }

      public void mousePressed(MouseEvent e) {
        startX = e.getX();
        startY = e.getY();
      }
    });

    comp.addMouseMotionListener(new MouseMotionAdapter() {
      public void mouseMoved(MouseEvent e) {
        JComponent source = (JComponent) e.getSource();
        int x = e.getX();
        int y = e.getY();
        Rectangle bounds = source.getBounds();
        resize = x < BORDER || y < BORDER || Math.abs(bounds.width - x) < BORDER || Math.abs(bounds.height - y) < BORDER;
        if (resize) {
          // TODO: there are a lot of resize cursors here, this is just of proof of concept
          source.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
        } else {
          source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        }
      }

      public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        if (startX != NONE && startY != NONE) {
          JComponent source = (JComponent) e.getSource();
          Rectangle bounds = source.getBounds();
          int deltaX = x - startX;
          int deltaY = y - startY;
          if (resize) {
            // TODO: handle all resize cases, left, right,...
            source.setSize(Math.max(10, bounds.width + x - prevX), Math.max(10, bounds.height + y - prevY));
          } else {
            source.setLocation(bounds.x + deltaX, bounds.y + deltaY);
          }
          // TODO: make sure you don't resize it as much as it disappears
          // TODO: make sure you don't move it outside the main panel
        } else {
          startX = x;
          startY = y;
        }
        prevX = x;
        prevY = y;
      }
    });
    main.add(comp);
    main.validate();
    main.repaint();
  }

  public static void main(String[] args) {
    new UIBuilder();
  }

}
导入java.awt.BorderLayout;
导入java.awt.Cursor;
导入java.awt.Rectangle;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionAdapter;
导入javax.swing.JButton;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JToolBar;
公共类UIBuilder{
私有静态final int NONE=-1;
私有静态最终整型边框=3;
专用JFrame=新JFrame(“建筑商”);
专用JToolBar工具栏=新建JToolBar();
private JPanel main=new JPanel();
私有int startX=无;
private int startY=无;
private int prevX=无;
private int prevY=无;
private boolean resize=false;
公共UIBuilder(){
框架.立根(100100600450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(新的BorderLayout());
frame.getContentPane().add(工具栏,BorderLayout.PAGE_START);
frame.getContentPane().add(main,BorderLayout.CENTER);
frame.setVisible(true);
buildToolbox();
buildMainPanel();
}
私有void buildToolbox(){
JButton按钮=新JButton(“按钮”);
addActionListener(新建ActionListener()){
已执行的公共无效操作(操作事件e){
JButton btn=新JButton(“按钮”);
添加组件(btn);
}
});
工具栏。添加(按钮);
}
私有void buildMainPanel(){
main.setLayout(空);
}
专用void addComponent(JComponent comp){
公司挫折(10,10,80,24);
公司地址MouseListener(新的MouseAdapter(){
公共无效MouseEvent(MouseEvent e){
startX=无;
startY=无;
((JComponent)e.getSource()).setCursor(Cursor.getDefaultCursor());
}
公共无效鼠标按下(MouseEvent e){
startX=e.getX();
startY=e.getY();
}
});
comp.addMouseMotionListener(新的MouseMotionAdapter(){
public void mouseMoved(MouseEvent e){
JComponent源=(JComponent)e.getSource();
int x=e.getX();
int y=e.getY();
矩形边界=source.getBounds();
resize=x