在Java Swing中为按钮设置边界无效

zdwk9cvp  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(162)

这个程序只是创建了一个UI1和一个Button。当我点击那个按钮时,一个新的UI出现了,我编写了这个代码,这样它就不会超出UI1的范围。我的主要问题是,我试图把按钮的宽度和高度做得更小,这样它看起来更像一个应用程序图标。但是当我设置按钮的范围时,它没有。当我运行代码时,不要改变任何东西。

//Start
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;

public class MainUI extends JFrame {//MainUI
    private JButton button;
    private JPanel panel;

    public MainUI() {

        //UI1
        setSize(1000, 700);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        try {

            //Here is the Button--
            button = new JButton();
            button.setBounds(200,200,70,70);
            Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
            button.setIcon(new ImageIcon(img));
            button.setFocusable(false);
            panel = new JPanel();
            panel.add(button);
            add(panel);

            button.addActionListener(e -> {
                UI2 ui2 = new UI2();
                ui2.setLocationRelativeTo(panel);
                ui2.setVisible(true);

                ui2.addComponentListener(new ComponentAdapter() {

                    public void componentMoved(ComponentEvent e) {

                        //This makes the ui2 not go outside the Main UI
                        int x = ui2.getX();
                        int y = ui2.getY();
                        int width1 = getWidth();
                        int height1 = getHeight();
                        int width2 = ui2.getWidth();
                        int height2 = ui2.getHeight();

                        if (x < getX()) {
                            ui2.setLocation(getX(), y);
                        }
                        if (y < getY()) {
                            ui2.setLocation(x, getY());
                        }
                        if (x + width2 > getX() + width1) {
                            ui2.setLocation(getX() + width1 - width2, y);
                        }
                        if (y + height2 > getY() + height1) {
                            ui2.setLocation(x, getY() + height1 - height2);
                        }//end of if statements
                    }//componentMoved
                });//addComponentListener
            });//addActionListener
        } catch(Exception e) {
            System.out.println("Something's Wrong");
        }
    }//End of MainUI

    public static void main(String[] args) {
        MainUI mainFrame = new MainUI();
        mainFrame.setVisible(true);
    }
}//Class MainUI

class UI2 extends JFrame {

    public UI2() {
        setBounds(getX() + 50, getY() + 50, 200, 200);
        setResizable(false);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout());
    }
}//Class UI2
//End
zu0ti5jz

zu0ti5jz1#

UI2应该是一个dialog,而不是另一个JFrame,因为 Swing 应用程序通常应该只有一个top-level container
你也不需要自己动手把GUI组件放到屏幕上,或者调整它们的大小,你应该使用layout managersAPI的其他相关部分--为了让JButton看起来像一个应用图标。
代码后面还有更多注解。

import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;

public class MainUI {
    private JButton button;
    private JFrame frame;
    private JPanel panel;
    private UI2 ui2;

    public MainUI() {
        frame = new JFrame();
        frame.setSize(1000, 700);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try {
            button = new JButton();
            Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
            button.setIcon(new ImageIcon(img));
            button.setFocusable(false);
            button.setContentAreaFilled(false);
            button.setBorderPainted(false);
            panel = new JPanel();
            panel.add(button);
            frame.add(panel);
            button.addActionListener(e -> {
                if (ui2 == null) {
                    ui2 = new UI2(frame);
                }
                ui2.setVisible(true);
            });// addActionListener
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        frame.setVisible(true);
    }// End of MainUI

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new MainUI());
    }
}// Class MainUI

@SuppressWarnings("serial")
class UI2 extends JDialog {

    public UI2(JFrame owner) {
        super(owner);
        setSize(200, 200);
        setResizable(false);
        setLocationRelativeTo(owner);
        addComponentListener(new ComponentAdapter() {

            public void componentMoved(ComponentEvent e) {

                // This makes the ui2 not go outside the Main UI
                int x = getX();
                int y = getY();
                int width1 = owner.getWidth();
                int height1 = owner.getHeight();
                int width2 = getWidth();
                int height2 = getHeight();
                if (x < owner.getX()) {
                    setLocation(owner.getX(), y);
                }
                if (y < owner.getY()) {
                    setLocation(x, owner.getY());
                }
                if (x + width2 > owner.getX() + width1) {
                    setLocation(owner.getX() + width1 - width2, y);
                }
                if (y + height2 > owner.getY() + height1) {
                    setLocation(x, owner.getY() + height1 - height2);
                } // end of if statements
            }// componentMoved
        });// addComponentListener
    }
}// Class UI2

(以下注解不分先后。)

  • 用户每次单击JButton(在UI1中)时,您不需要创建一个新的UI2。创建一次,然后在关闭时隐藏它,在单击JButton时显示它。默认行为是在关闭时隐藏JDialog
  • Swing 应用程序需要扩展JFrame(或JPanel或任何其他JComponent)。Swing 应用程序可以扩展JComponent(或其子类),但并非必须如此。
  • JFrame的[内容窗格]的默认布局为BorderLayout,因此无需显式设置此布局。
  • catch块中打印一条消息,如 Something 's Wrong,可能对用户友好,但它不会帮助您找到exception的原因。我几乎总是在catch块中打印堆栈跟踪。

运行应用程序的屏幕截图。

但是,由于您不希望UI2移动到UI1之外,因此另一种选择是使用JInternalFrame而不是JDialog
(同样,代码后面有注解。)

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.Objects;

import javax.imageio.ImageIO;
import javax.swing.DefaultDesktopManager;
import javax.swing.DesktopManager;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;

public class IframTst {
    private JDesktopPane desktopPane;
    private JInternalFrame iFrame;

    public IframTst() throws IOException {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createButton(), BorderLayout.PAGE_START);
        frame.add(createDesktopPane(), BorderLayout.CENTER);
        frame.setSize(1000, 700);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createButton() throws IOException {
        JPanel panel = new JPanel();
        JButton button = new JButton();
        Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
        button.setIcon(new ImageIcon(img));
        button.setFocusable(false);
        button.setContentAreaFilled(false);
        button.setBorderPainted(false);
        button.addActionListener(this::showIframe);
        panel.add(button);
        return panel;
    }

    private JDesktopPane createDesktopPane() {
        desktopPane = new JDesktopPane();
        DesktopManager manager = new DefaultDesktopManager() {

            private static final long serialVersionUID = -4685522430190278205L;

            @Override
            public void dragFrame(JComponent f, int newX, int newY) {
                setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
            }

            @Override
            public void setBoundsForFrame(JComponent f,
                                          int newX,
                                          int newY,
                                          int newWidth,
                                          int newHeight) {
                Rectangle rect = desktopPane.getVisibleRect();
                if (newX < 0) {
                    newX = 0;
                }
                if (newX + newWidth > rect.width) {
                    newX = rect.width - newWidth;
                }
                if (newY < 0) {
                    newY = 0;
                }
                if (newY + newHeight > rect.height) {
                    newY = rect.height - newHeight;
                }
                super.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
            }
        };
        desktopPane.setDesktopManager(manager);
        return desktopPane;
    }

    private void showIframe(ActionEvent event) {
        if (iFrame == null) {
            iFrame = new JInternalFrame(null, false, true, false, false);
            iFrame.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
            iFrame.setSize(200, 200);
            desktopPane.add(iFrame);
        }
        iFrame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            try {
                new IframTst();
            }
            catch (IOException xIo) {
                xIo.printStackTrace();
            }
        });
    }
}
  • ActionListener是使用method references实现的
  • JInternalFrame限制在其父JDesktopPane范围内的灵感来自

Preventing JInternalFrame from being moved out of a JDesktopPane
(as以及查看类DefaultDesktopManager的源代码)
您还可以在JDesktopPane中设置JInternalFrame的初始位置。请参阅
How do I open a JInternalFrame centered in a JDesktopPane?
当我运行它的时候它看起来是什么样子。

相关问题