-1

This program just creates a UI1 and a Button. When I click on that button a new UI Appear which I coded so that it doesn't go outside the bounds of UI1. My main problem is that I'm trying to make the width and height of the button smaller so that it looks more like an app icon. But when I set the bounds on the button it doesn't change anything when I run the code.

//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
Abra
  • 19,142
  • 7
  • 29
  • 41
N Ib
  • 1
  • 2
  • 1
    sizing/locating of components is the exclusive task of a layoutManager - __never-ever__ try to do it yourself, instead use a suitable manager, https://docs.oracle.com/javase/tutorial/uiswing/layout/ BTW: please put some effort into formatting the code to make it readable (a code block needs at least 4 leading spaces, no tabs) – kleopatra Feb 01 '23 at 16:50
  • Okay thanks for the advice. I'm still new, I will try to make it more readable next time. – N Ib Feb 01 '23 at 17:22

1 Answers1

0

UI2 should be a dialog and not another JFrame since Swing applications should usually only have a single, top-level container.

You also don't need to do all the hard work yourself of placing GUI components on the screen nor sizing them. You should use layout managers and other, relevant parts of the rich, API – in order to make the JButton look like an app icon.

More notes after the code.

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

(Below notes are in no particular order.)

  • You don't need to create a new UI2 each time the user clicks the JButton (in UI1). Create it once and then just hide it when you close it and show it when you click the JButton. The default behavior is to hide the JDialog when it is closed.
  • A Swing application does not need to extend JFrame (or JPanel or any other JComponent). A Swing application can extend JComponent (or subclass thereof) but it does not have to.
  • The default layout for [the content pane of] JFrame is BorderLayout so no need to explicitly set this.
  • Printing a message, like Something's Wrong, in a catch block, might be user-friendly but it won't help you find the cause of the exception . I nearly always print the stack trace in my catch blocks.

Screen capture of running app.

screen capture

However, since you don't want UI2 to move outside of UI1, an alternative would be to use a JInternalFrame rather than a JDialog. Here is a demonstration.

(Again, there are notes after the code.)

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();
            }
        });
    }
}
  • The ActionListener is implemented using method references
  • The inspiration for keeping the JInternalFrame within the bounds of its parent JDesktopPane came from

Preventing JInternalFrame from being moved out of a JDesktopPane

(as well as looking at the source code for class DefaultDesktopManager)

You can also set the initial location of the JInternalFrame within the JDesktopPane. Refer to

How do I open a JInternalFrame centered in a JDesktopPane?

How it looks when I run it.

recording

Abra
  • 19,142
  • 7
  • 29
  • 41