How to layout the JComponents by resolution of JPanel or JFrame?
Hello, I'm new to java coding and I'm having problem layoutting components
in JPanel.
Is there Good way to reset the size and location of components whenever Frame's resolution changes?
here is my code.
public class TestPanel extends JPanel{
private GameBoard SuperFrame;
/*SuperFrame is JFrame where this Panel attach to..*/
public TestPanel(GameBoard SuperFrame) {
.....
this.SuperFrame=SuperFrame;
this.setLayout(null);
.......
add(new Maximizebutton());
........
}
private class MaxmizeButton extends MYUI{
/*MYUI is abstract class which extends JComponent, and it inherits
preferredSize,preferredLocation and abstract void method revalidateSize ...*/
JButton maxButton;
public MaxmizeButton (){
preferredSize = new Dimension(SuperFrame.getWidth()/10,SuperFrame.getHeight()/10);
/*This is my crude solution about setting the size of Component
by resolution of SuperFrame(JFrame) :( */
preferredLocation = new Point();
/*Is there good way to set or calculate the location of this component? */
this.setSize(preferredSize);
this.setLocation(preferredLocation);
maxButton = new JButton("최대화");
maxButton.setSize(preferredSize);
maxButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SuperFrame.MaxmizeFrame();
/*MaximizeFrame method maximizes the SuperFrame..*/
}
});
add(maxButton,0);
}
#Override
void revalidateSize() {
/*whenever resolution of SuperFrame changes this method will be called
and should change the size and location of Components Ideally..*/
preferredSize = new Dimension(SuperFrame.getWidth()/10,SuperFrame.getHeight()/10);
preferredLocation = new Point();
this.setSize(preferredSize);
this.setLocation(preferredLocation);
maxButton.setSize(preferredSize);
}
}
}
I want to resize all Components in Panel by resolution of JFrame.
But couldn't found good solution for that.
Related
Beginner programming student here. Trying to simply create JFrame object that allows me to click on the boundaries of the window and display the coordinates where I click. However, whenever I click a new location, the previous coordinates need to disappear. I have been told that one way to do this is by adding a JPanel to the center of the JFrame object. However when I do so I am getting an error that says that I am adding a window to a container. I may be extending something incorrectly from what I have read but I can't seem to figure it out.
public class Proj07 {
public static void main(String[] args){
new Proj07Runner();
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Proj07Runner{
GUI gui = new GUI();
}
class MyFrame extends JFrame{
int XCoor;
int YCoor;
public void paint(Graphics g){
g.drawString("x = " + XCoor + ", y = " + YCoor, XCoor, YCoor);
}
}
class GUI{
public GUI(){
MyFrame displayWindow = new MyFrame();
displayWindow.setSize(300,100);
displayWindow.setTitle("Insert name here");
displayWindow.addWindowListener(new WProc1());
JPanel myPanel = new JPanel();
displayWindow.getContentPane().add(myPanel, "Center");
displayWindow.setVisible(true);
}
}
class MouseProc extends MouseAdapter{
public void mousePressed(MouseEvent e){
((MyFrame)e.getComponent()).XCoor = e.getX();
((MyFrame)e.getComponent()).YCoor = e.getY();
e.getComponent().repaint();
}
}
class WProc1 extends WindowAdapter{
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
Thank you guys for your help!
I am not 100% sure but I think the problem is where you put the listener:
You need to do everything on the JPanel, not the frame that is the container, so you should replace the declares with:
MyFrame displayWindow = new MyFrame();
displayWindow.setSize(300,100);
displayWindow.setTitle("Insert name here");
displayWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel myPanel = new JPanel();
myPanel.setSize(300,100);
myPanel.addMouseListener(new myMouse)
displayWindow.getContentPane().add(myPanel, "Center");
displayWindow.setVisible(true);
And then create a mouseListener instead of a mouseAdapter to add in the JPanel.
Also remove the last WindowsAdapter thing, just use exitonclose.
Edit:
When it comes down to what the frame should do it should only contain the panel, so you also need to move everything you were doing on the frame to the panel (such as the public void paint() and stuff).
I would go as far as saying that if you want to add multiple panels on a frame, you should consider putting all panels inside another panel (as a container) and then putting that panel inside the frame.
I have a JFrame. It uses a JPanel as its content pane, and that JPanel uses GridBagLayout as its LayoutManager. That JPanel contains two more items: a button, and another JPanel. On program start, an image is loaded from file into the lowest-level JPanel as a BufferedImage using ImageIO.read(...). Here is where everything goes to pieces.
The image loads correctly, I can see a small corner of it on screen (14px square as specified in debugger). There is nothing I can figure out that will cause the layout to grow and fit the entire image in the lowest level JPanel on screen. The image in debuggers shows correct size of 500px. The preferred size of the CardImagePanel shows up correctly as the same size as the image. But the layout will not respect the preferred size unless I manually set the CardImagePanel size using setSize(...) which I'm pretty sure is not supposed to be necessary with GBL.
I have tried putting revalidate() and repaint() calls on every single JFrame, JPanel, layout, grid bag, image, etc throughout the entire program and just can't find the correct place or time to call them to make this thing work. Currently I've been trying to just let the image load incorrectly and use the button to force revalidation and repaint, but even this explicit call is not doing anything.
I'm losing my mind, I'll do anything to get this thing working.
Here is all my code for the whole stupid thing (minus imports and package specification.
P1s1.java:
public class P1s1 {
public static void main(String[] args) {
// TODO code application logic here
build();
}
public static void build()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(640, 480));
frame.setContentPane(new GuiPanel(frame));
frame.setVisible(true);
}
}
GuiPanel.java:
public class GuiPanel extends JPanel {
JFrame parentFrame;
JButton imageLoaderButton;
CardImagePanel cardImagePanel;
LayoutManager layout;
GridBagLayout gridBagLayout;
GridBagConstraints constraints;
public GuiPanel(JFrame frame)
{
parentFrame = frame;
constraints = new GridBagConstraints();
gridBagLayout = new GridBagLayout();
layout = gridBagLayout;
this.setLayout(layout);
this.setBorder(BorderFactory.createLineBorder(Color.black));
setupImageLoaderButton(imageLoaderButton);
cardImagePanel = new CardImagePanel();
this.add(cardImagePanel);
}
private void setupImageLoaderButton(JButton button)
{
button = new JButton("Click to load image!");
ActionListener imageLoaderListener;
imageLoaderListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Button clicked.");
cardImagePanel.revalidate();
cardImagePanel.repaint();
GuiPanel.this.revalidate();
GuiPanel.this.repaint();
parentFrame.revalidate();
parentFrame.repaint();
}
};
button.addActionListener(imageLoaderListener);
this.add(button);
}
}
CardImagePanel.java:
public class CardImagePanel extends JPanel {
BufferedImage cardImage;
public CardImagePanel()
{
this.setBorder(BorderFactory.createLineBorder(Color.black));
try {
cardImage = ImageIO.read(new File("c:\\dev\\cards\\2_of_clubs.png"));
this.setPreferredSize(new Dimension(cardImage.getWidth(), cardImage.getHeight()));
} catch (IOException ex) {
System.out.println("Exception trying to load image file.");
}
}
// The getPreferredSize() override was suggested by MadProgrammer.
// It did not solve the issue, but see MadProgrammer's updated,
// accepted answer below for the correct solution. The rest of the
// code reflects my original attempt to solve the issue.
#Override
public Dimension getPreferredSize()
{
return cardImage != null ? new Dimension(cardImage.getWidth(), cardImage.getHeight()) : super.getPreferredImage();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(cardImage, 0, 0, this);
}
}
GridBagLayout relies on a component telling it what size it would like to be (along with it's minimum and maximum size when it's relievent). You need to override the getPreferredSize method of the CardImagePanel, returning the size you would like the component to be
public class CardImagePanel extends JPanel {
BufferedImage cardImage;
public CardImagePanel() {
this.setBorder(BorderFactory.createLineBorder(Color.black));
try {
cardImage = ImageIO.read(new File("c:\\dev\\cards\\2_of_clubs.png"));
} catch (IOException ex) {
System.out.println("Exception trying to load image file.");
}
}
#Override
public Dimension getPreferredSize() {
return cardImage != null ? new Dimension(cardImage.getWidth(), cardImage.getHeight()) : super.getPreferredSize();
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(cardImage, 0, 0, this);
}
}
Have a look at How to Use GridBagLayout for more details
You CardImagePanel has no preferred size, so the layout manager doesn't know how to handle the size properly.
A couple of solutions:
There is no need to create a custom class to display the image. Just use a JLabel to display the image. The JLabel will return the preferred size of the image.
If you do use the CardImagePane, then you need to override the getPreferredsize() method of the CardImagePanel to return the size of the image.
Working on a homework assignment and I'm having issues with figuring out how to print a line of text when a mouse cursor enters and exits a certain colored area (a JPanel called panel in this case) while using the MouseListener interface.
I choose a color from the bottom panel (either Red, blue, or yellow) and then when I move to the upper panel it should be able to print which color the mouse has entered in while the mouse is in the panel and which color I exited from when my mouse finds itself outside of said panel...
Hopefully that makes sense. Here's a code snippet of what I have so far. This is for the color RED:
class RedButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
panel.setBackground(Color.RED);
class RedMouseListener implements MouseListener
{
public void mouseEntered(MouseEvent event)
{
}
public void mouseExited(MouseEvent event)
{
}
public void mousePressed(MouseEvent event) { }
public void mouseReleased(MouseEvent event) { }
public void mouseClicked(MouseEvent event) { }
}
}
}
ActionListener redListener = new RedButtonListener();
bRed.addActionListener(redListener);
Here's a relevant question from Stack Overflow Mouse moved event within JPanel
I'd recommend once you ensure that triggers are being correctly listened to (try printing "Hello World") From there you need to get the communication of the color state within the mouse event. If everything is within the same instance you can just access the variables needed within the event listener.
Here are the docs on MouseEvent http://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseEvent.html
Make sure you added the mouse listener try the following
panel.addMouseListener(new RedMouseListener());
start simple making the following work
public void mouseEntered(MouseEvent event)
{
System.out.println("Hello World!");
}
if you need to access the color of the panel within the event listener try the following snippet
panel.getBackground();
This returns a Color object.
Its worth mentioning the extra class declaration can be avoided by using an anonymous inner class. see How are Anonymous (inner) classes used in Java? These overridden methods are essentially a sub class of MouseListener but we don't need to call it by name.
panel.addMouseListener(new MouseListener(){
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {}
});
Introduction
Since this is such an old question, I thought I'd put together a simple Swing GUI to illustrate how a MouseListener works.
Here's the GUI before I do anything.
The main panel in the center will take on the selector color when the mouse is moved into the selection area. The main panel will return to it's original color when the mouse is moved out of the selection area.
Here's the GUI when my mouse is in the blue selection area.
Explanation
If you're not familiar with Java Swing, Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
When I create a Swing GUI, I use the model/view/controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
The MVC pattern implies that you create the model first, then the view, then the controller. This is more of an iterative process than a waterfall.
In Java Swing, the MVC pattern means:
The view reads information from the model.
The view may not update the model.
The controller updates the model and repaints / revalidates the view.
The model consists of one or more plain Java getter/setter classes.
The view consists of a JFrame and however many JPanels it takes to create the GUI.
There's usually not one controller "to rule them all". Each listener acts as an independent controller to manage its part of the model and view.
This is a simple application, so it consists of two model classes, one view class, and one controller class. The model is not updated at all in this example.
I did not code this entire application at one time. I wrote a few lines of code and ran tests. I made lots of changes to the code before I was satisfied with how it worked.
Model
The ColorSelection class is a plain Java getter/setter class that holds the color name, background color, and foreground color.
The MouseMovementModel class is a plain Java getter/setter class that holds the ColorSelection instances. The GUI builds the selection JPanel based on this information. If you want to add another selection color, you would add it here.
View
The view consists of a JFrame, a selection JPanel, and the main JPanel.
The JFrame has a default BorderLayout. The selection JPanel goes into the NORTH section and the main JPanel goes into the CENTER section. Only one component can be placed in a section. That component is usually a JPanel.
The selection JPanel uses a FlowLayout to hold the color selection JPanels. The color selection JPanels are created based on the number of ColorSelection instances in the application model.
A color selection JPanel is a simple JPanel created to use the information from a ColorSelection instance.
The main JPanel is a simple JPanel that will show a background color. The controller will be responsible for changing the background color.
Controller
The ColorListener class extends a MouseAdapter. The MouseAdapter class implements the MouseListener, MouseMotionListener, and MouseWheelListener interfaces. Using the MouseAdapter class allows me to implement just the mouse listener methods I'm writing code for.
The mouseEntered method sets the main JPanel to the ColorSelection color. The code is really simple. It updates the view with the ColorSelection background color.
The mouseExited method sets the main JPanel back to its original color.
Code
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MouseMovementExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MouseMovementExample());
}
private final JPanel mainPanel;
private final JPanel[] colorPanel;
private final MouseMovementModel model;
public MouseMovementExample() {
this.model = new MouseMovementModel();
this.mainPanel = createMainPanel();
this.colorPanel = new JPanel[model.getSelections().length];
}
#Override
public void run() {
JFrame frame = new JFrame("Mouse Movement Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createSelectionPanel(), BorderLayout.NORTH);
frame.add(mainPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createSelectionPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
ColorSelection[] selections = model.getSelections();
for (int index = 0; index < selections.length; index++) {
ColorSelection selection = selections[index];
ColorListener listener = new ColorListener(this, selection);
colorPanel[index] = createColorPanel(selection, listener);
panel.add(colorPanel[index]);
}
return panel;
}
private JPanel createColorPanel(ColorSelection selection, ColorListener listener) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(selection.getBackgroundColor());
panel.addMouseListener(listener);
panel.setPreferredSize(new Dimension(200, 100));
JLabel label = new JLabel(selection.getColorName());
label.setFont(panel.getFont().deriveFont(Font.BOLD, 36f));
label.setForeground(selection.getForegroundColor());
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label, BorderLayout.CENTER);
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
return panel;
}
public Color getMainPanelBackground() {
return this.mainPanel.getBackground();
}
public void setMainPanelBackground(Color color) {
this.mainPanel.setBackground(color);
}
public class ColorListener extends MouseAdapter {
private final Color originalBackgroundColor;
private final ColorSelection selection;
private final MouseMovementExample view;
public ColorListener(MouseMovementExample view, ColorSelection selection) {
this.view = view;
this.selection = selection;
this.originalBackgroundColor = view.getMainPanelBackground();
}
#Override
public void mouseEntered(MouseEvent e) {
view.setMainPanelBackground(selection.getBackgroundColor());
}
#Override
public void mouseExited(MouseEvent e) {
view.setMainPanelBackground(originalBackgroundColor);
}
}
public class MouseMovementModel {
private final ColorSelection[] selections;
public MouseMovementModel() {
this.selections = new ColorSelection[3];
this.selections[0] = new ColorSelection("Red", Color.RED, Color.WHITE);
this.selections[1] = new ColorSelection("Green", Color.GREEN, Color.BLACK);
this.selections[2] = new ColorSelection("Blue", Color.BLUE, Color.WHITE);
}
public ColorSelection[] getSelections() {
return selections;
}
}
public class ColorSelection {
private final Color backgroundColor, foregroundColor;
private final String colorName;
public ColorSelection(String colorName, Color backgroundColor, Color foregroundColor) {
this.colorName = colorName;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
public String getColorName() {
return colorName;
}
}
}
I need to display chessboard. I have a BoardPanel class which extends JPanel and a GamePanel (also extending JPanel) class containing BoardPanel. GamePanel fills all the application frame.
I want BoardPanel to always be a square with size equal to the minimum of GamePanel's width and height (if GamePanel's width is greater than height there should be empty space on the left and right, if it's smaller there should be empty space on top and bottom). It's also important that BoardPanel should be displayed in the center of parent panel.
I wrote sth like this:
public GamePanel() {
setLayout(new BorderLayout(0, 0));
boardPanel = new BoardPanel(...);
this.add(boardPanel, BorderLayout.CENTER);
...
}
and in BoardPanel:
public void paintComponent(Graphics g) {
super.paintComponent(g);
int size = Math.min(this.getParent().getHeight(), this.getParent().getWidth());
this.setSize(size, size);
...
}
It resizes well, but chessboard is always displayed in top left corner of GamePanel (all the empty space is displayed on bot or right) and I don't know how to fix it.
Any help? Thanks in advance!
Center it using a GridBagLayout.
import java.awt.*;
import javax.swing.*;
public class CenteredPanel {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JPanel gui = new JPanel(new GridBagLayout());
JPanel square = new SquarePanel();
square.setBackground(Color.RED);
gui.add(square);
JFrame f = new JFrame("SquareBoard");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.add(gui);
f.setMinimumSize(new Dimension(400,100));
f.pack();
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
class SquarePanel extends JPanel {
#Override
public Dimension getPreferredSize() {
Container c = this.getParent();
int size = Math.min(c.getHeight(), c.getWidth());
Dimension d = new Dimension(size,size);
return d;
}
}
No need for new BorderLayout(0,0) simply use default constructor for BorderLayout
Dont call setSize() rather override getPreferredSize() of JPanel like so:
#Override
public void getPreferredSize() {
int size = Math.min(this.getParent().getHeight(), this.getParent().getWidth());
return new Dimension(size,size);
}
also its never good to do work in your paintComponent as this should be used exclusively for painting only.
If the above does not work I'd suggest a SSCCE to illustrate specific problems you might have
Current I can add a bunch of customed component objects to the JPanel by pressing "add" JButton. I also got a "delete" JButton which I wish to do the opposite of "add".
My intention is that I can select a component with a mouse and click the delete button and pressto!, the component is gone.
I hook a MouseListener to the panel, and use MouseEvent, e.getComponent() to get w/e current component the mouse clicks on. So if it returns a custom component then a variable "private myComponent current" (already set to null) will point to that component. Then I can just click on "delete" button to remove it. An actionListener already added in "delete" button and in the body it calls this.remove(current) (if current is not null).
However, this doesn't work as I can't remove a component! Any pointer?
If there is an elegant way to managing add/remove components please suggest!
public class MainDisplayPanel extends JPanel implements ActionListener, MouseListener{
private JButton newClassButton;
private JButton deleteButton;
private Resizable current;
private Resizable resizer;
public MainDisplayPanel(LayoutManager layout) {
super(layout);
newClassButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addResizer();
}
});
deleteButton = new JButton("Delete");
deleteButton.addActionListener(this);
this.addMouseListener(this);
this.add(newClassButton);
this.add(deleteButton);
}
public void addResizer() {
//JPanel panel = new JPanel();
//panel.setBackground(Color.white);
resizer = new Resizable( new ClassBox());
this.add(resizer);
this.revalidate();
this.repaint();
}
public void actionPerformed(ActionEvent e) {
if(current!=null)
{
this.remove(current);
this.revalidate();
this.repaint();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println(e);
Component component = e.getComponent();
if(component instanceof Resizable)
current= (Resizable) e.getComponent();
}
public static void main(String[] args) {
JFrame jframe = new JFrame();
jframe.add(new MainDisplayPanel(null));
jframe.setSize(new Dimension(600,400));
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Doh!
Now, in the addResizer() method. Every time I press the add button to add a new Resizable object, what'd happen to the previously added objects? I'm certain that they become null because resizer variable no longer referring to it them??? Even if this is the case, they are still displayed on the panel...And if I pressed delete only the newly added Resizable object gets removed. So am I on the right track here?
Edit: to sum up my problem, I hooked the MouseListener to wrong object. It should be Resizable object instead of the panel. Therefore, variable current is always null.
Your problem is your MouseLisetener. You are listening to the MainDisplayPanel, and so when you click on the JPanel, the MouseEvent#getComponent method returned by, e, in your mousePressed method will return the MainDisplayPanel instance since that is what is being listened to, not the Resizable instance that is under the mouse.
Solutions include:
creating one MouseListener object and adding this same object to each Resizable as a MouseListener for the Resizable, or
using your current set up, but hold your Resizable's in an ArrayList and then iterating through the array list in the mousePressed method to see if any Resizable has been clicked by using the componentAt(...) method.
Note that I had to create my own SSCCE to solve this. Again in the future, please do us all a favor and do this for us as it really is in your and our best interest, and shows that you respect our time and our help.
Edit 1
My SSCCE:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class MainDisplayPanel extends JPanel {
private static final int RESIZABLE_COUNT = 40;
private JButton deleteButton;
private Resizable current;
private Resizable resizer;
private List<Resizable> resizableList = new ArrayList<Resizable>();
public MainDisplayPanel(LayoutManager layout) {
super(layout);
deleteButton = new JButton("Delete");
deleteButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
deleteButtonActionPerformed(e);
}
});
this.addMouseListener(new MyMouseAdapter());
this.add(deleteButton);
for (int i = 0; i < RESIZABLE_COUNT; i++) {
addResizer();
}
}
private void deleteButtonActionPerformed(ActionEvent e) {
if (current != null) {
this.remove(current);
resizableList.remove(current);
current = null;
this.revalidate();
this.repaint();
}
}
public void addResizer() {
resizer = new Resizable();
this.add(resizer);
resizableList.add(resizer);
this.revalidate();
this.repaint();
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
current = null;
Component c = getComponentAt(e.getPoint());
for (Resizable resizable : resizableList) {
if (resizable == c) {
current = resizable;
resizable.setFill(true);
} else {
resizable.setFill(false);
}
}
}
}
public static void main(String[] args) {
JFrame jframe = new JFrame();
// !! jframe.add(new MainDisplayPanel(null));
jframe.add(new MainDisplayPanel(new FlowLayout()));
jframe.setSize(new Dimension(600, 400));
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
#SuppressWarnings("serial")
class Resizable extends JPanel {
private static final int RESIZE_WIDTH = 50;
private static final int RESIZE_HEIGHT = 40;
private static final int THICKNESS = 5;
private static final Color FILL_COLOR = Color.pink;
public Resizable() {
Random rand = new Random();
// different color border so we can see that it was the clicked one that was deleted.
Color color = new Color(
rand.nextInt(255),
rand.nextInt(255),
rand.nextInt(255));
setBorder(BorderFactory.createLineBorder(color, THICKNESS));
}
#Override // so we can see it
public Dimension getPreferredSize() {
return new Dimension(RESIZE_WIDTH, RESIZE_HEIGHT);
}
public void setFill(boolean fill) {
Color fillColor = fill ? FILL_COLOR : null;
setBackground(fillColor);
repaint();
}
}
it very crazy idea, but everything is possible, but
1) in case that you Layed JComponent by using some of LayoutManager you can remove JComponents from Container, and thenafter you must/have to call revalidate() + repaint(), but this actions has side effect -> ReLayout Container and then Container's contents could be look very ***
2) in case that you layed Container with AbsoluteLayout, that should be maybe nicest but question is what with emtpy space inside Container
there is very easy way how to do it, you need to add JPopupMenu to the Container,
on RightMouseClick you have to finding JComponent under the MouseCursor
then call Container#remove(myComponent), thenafter you have to call revalidate() + repaint() for refresh GUI
or is same for me
call myComponent.setVisible(false), no re-layout, no revalidate + repaint, JComponent waiting on same place for (eventually) reusing
excelent thread about how to LayoutManagers add/remove JComponents + revalidate + repaint
I believe the problem is you need to force Swing to layout the components again after removing one. After you remove(current), call revalidate().