簡體   English   中英

使用Swing組件在Java Swing中創建一個簡單的GUI編輯器

[英]Make a simple GUI editor in Java Swing using Swing components

我目前正在開發一個項目,我需要一個非常簡單的GUI類對象編輯器。 該編輯器將是一個可以放置眾所周知的GUI小部件的畫布。 例如,可以在那里放置一個按鈕和一個文本字段,移動它們並調整它們的大小。 不需要與小部件本身進行交互。

我一直試圖通過調整一個非常簡單的繪畫教程來實現這一目標,我認為以這種方式實現它很容易,但是我在畫布上繪制自定義形狀和文本以及拖放這些形狀時會遇到很多問題。

我想知道我是否可以在JPanel上重用真正的Swing小部件,讓用戶放置,移動並調整大小。 如果是這樣,我應該研究什么?

我知道這可能看起來很少,但老實說我堅持尋找解決方案。

我以為我應該記住那些古老的Swing日子,並且為此寫一個概念證明會有一點樂趣。 它支持在主面板上添加一個按鈕,然后移動一些基本調整大小。

它只是一個概念證明,但它回答了你已經擁有的很多問題。 我在那里添加了一些TODO,例如你將知道下一步該做什么。

請享用...

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

}

這聽起來像一個有趣的項目。

我肯定會將JPanel作為容器,布局設置為null。 為了能夠在容器中移動JButton,JLabel等組件,您必須在添加的組件上偵聽MouseListener和MouseMotionListener事件並相應地處理它們。 每當移動或調整一個組件時,您必須在容器上調用validate()和repaint()。

我將以混合方式實現它:創建一個實現鼠標響應的類(拖動,調整大小)。 該類負責管理用戶交互。

對於組件的實際繪制,使用真正的 Swing組件(用戶交互類將引用其應該表示的組件並將實際呈現委托給該組件)。

這種方法避免了擴展原始Swing組件時出現的大多數復雜性,但您仍然可以重用所有繪制代碼​​。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM