placing a transparent JPanel on top of another JPanel not working - java

I am trying to place a JPanel on top of another JPanel which contains a JTextArea and a button and i want to the upper apnel to be transparent. I have tried it by making the setOpaque(false) of the upper panel. but it is not working. Can anyone help me to get through this? Thanks in advance!
public class JpanelTest extends JPanel
{
public JpanelTest()
{
super();
onInit();
}
private void onInit()
{
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JTextArea(100,100),BorderLayout.CENTER);
panel.add(new JButton("submit"),BorderLayout.SOUTH);
JPanel glass = new JPanel();
glass.setOpaque(false);
add(panel,BorderLayout.CENTER);
add(glass,BorderLayout.CENTER);
setVisible(true);
}
public static void main(String args[])
{
new JpanelTest();
}
}

Indeed, it would be useful to tell the reason why you want panels one over another.
Starting with your code, and changing it a lot, I got it to work, but it might not do what you expect...
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame
{
public Test()
{
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 200);
onInit();
setVisible(true);
}
private void onInit()
{
JLayeredPane lp = getLayeredPane();
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JTextArea(), BorderLayout.CENTER);
panel.add(new JButton("Submit"), BorderLayout.SOUTH);
panel.setSize(300, 150); // Size is needed here, as there is no layout in lp
JPanel glass = new JPanel();
glass.setOpaque(false); // Set to true to see it
glass.setBackground(Color.GREEN);
glass.setSize(300, 150);
glass.setLocation(10, 10);
lp.add(panel, Integer.valueOf(1));
lp.add(glass, Integer.valueOf(2));
}
public static void main(String args[])
{
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Test();
}
});
}
}
If totally transparent, well, it is like it isn't here! When opaque, it just covers some of the GUI, but doesn't prevent mouse clicks, for example.

1) there are a few ways, there no issue to put JPanel, with covering full JFrames/JPanel area or only part of Rectangle / Dimension that returns JFrames/JPanel
use JLayer(Java7) based on JXLayer (Java6)
use GlassPane
use JViewport
use OverlayLayout
use transucent JDialog / JWindow
2) everything depends of if you want to protect against mouse and key events from the top layer to bottom, or not (to avoiding redispatch events from - to and vice versa)

Check out this tutorial on using Swing Root Panes.
The glass pane is useful when you want to be able to catch events or paint over an area that already contains one or more components. For example, you can deactivate mouse events for a multi-component region by having the glass pane intercept the events. Or you can display an image over multiple components using the glass pane.

Related

Center a JPanel with layout GridLayout inside another JPanel

I am attempting to make a Chess game and while trying to work on the GUI, I encountered this issue:
I cannot seem to be able to vertically center my chess board on my JFrame. The JPanel is horizontally centered, but it is off-center, stuck to the top, vertically.
Code where the panel using GridLayout is added to its container and the frame is initialized:
public class ChessGUI extends JFrame
{
private static final long serialVersionUID = 1L;
private static Dimension appDimention = new Dimension(1000, 600);
public static JFrame frame = new JFrame("Chess");
public static JPanel background = new JPanel();
public static BoardGUI board = new BoardGUI();
public static int width;
public static int height;
public static void createFrame()
{
JFrame.setDefaultLookAndFeelDecorated(true);
//Set stuff that JFrame needs
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//Set stuff that JPanel needs
background.setPreferredSize(appDimention);
frame.getContentPane().add(background);
frame.pack();
//This 'board' is my Chess Board JPanel which I can't seem to centre
//'background' is a JPanel which is, as the name suggests, the background
background.add(board);
//Set the location of the JFrame and set it visible
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
BoardGUI
#SuppressWarnings("serial")
public class BoardGUI extends JPanel
{
GridLayout chessBoard = new GridLayout(8, 8);
Dimension boardDims = new Dimension(500, 500);
public BoardGUI()
{
this.setLayout(chessBoard);
this.setBackground(Color.BLACK);
this.setPreferredSize(boardDims);
}
}
I'm not really doing anything in the code above to center the BoardGUI object, but I did tried the following two ways with negative results:
background.add(board, JPanel.CENTER_ALLIGNMENT)
background.add(board, BorderLayout.CENTER)
The result I'm getting at the moment:
As you can see it is not vertically centered, and my desired behavior is for it to be both horizontally and vertically centered on the frame.
Any help or insights on any mistakes I might be making would be very welcome! Thanks!
background is a JPanel which has a default layout of FlowLayout, which is where your problem is coming from.
I would change
public static JPanel background = new JPanel();
to
public static JPanel background = new JPanel(new GridBagLayout());
Suggestions...
Okay, so suggestions.
Avoid static, especially if all you want to do is access information from one class in another - there are better ways to achieve this that won't tightly couple your code
Avoid setPreferredSize - it's not a recommend way of defining custom sizing hints, override getPreferredSize instead, this prevents other people from changing it.
Instead of setting the preferredSize of the background panel, I would simple make use of either an EmptyBorder or the margins/inserts support of GridBagLayout

Two JPanels in one JFrame

I want to use two JPanels in one JFrame, with an invisible horizontal line between them. I played a little bit and got this:
public class Application {
public static void main(String[] args)
{
JFrame jframe = new JFrame();
jframe.setSize(500,700);
jframe.setVisible(true);
jframe.setTitle("Title");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);
JSplitPane splitPane = new JSplitPane();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setDividerLocation(250);
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
jframe.add(splitPane);
}
}
Now, the first problem is how can I turn off the "resizability" of the Line between the panels? And how do I make it "invisible"? Maybe use something else than split pane?
Second of all, how do can I work with only one side of the JPanel?
(I am working on an application that lets you draw a circle on the left hand side).
This seems like an easy question but I am relatively new to Java.
As said before in a comment by #MadProgrammer you can use BorderLayout or GridBagLayout but as you're placing the "split" line right in the middle of both panels you could use GridLayout which will make both panels be of the same size no matter if the window is resized.
I didn't tried with GridBagLayout but I did an example on how you could achieve this pane separation without using a JSplitPane.
With GridLayout all you need to do is add the elements to the left pane (in my example I used a JLabel to differentiate them) while in BorderLayout you need to specify that the panel where you'll be painting the circle to be aligned to the left (WEST constant) as I did.
However if you use BorderLayout approach and add text or elements to the right pane, they will be aligned to the right, you can fix it by "boxing" the elements in another pane with a different Layout.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Application {
private JFrame frame;
private JPanel containerPane;
private JPanel topPane;
private JPanel bottomPane;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Application().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame("Example of 2 panels");
containerPane = new JPanel();
topPane = new JPanel();
bottomPane = new JPanel();
containerPane.setLayout(new GridLayout(2, 1));
topPane.setLayout(new GridLayout(1, 2));
bottomPane.setLayout(new BorderLayout());
topPane.add(new JLabel("Left side"));
topPane.add(new JLabel("Right side"));
bottomPane.add(new JLabel("Left side"), BorderLayout.WEST);
bottomPane.add(new JLabel("Right side"), BorderLayout.EAST);
topPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE), "Using GridLayout"));
bottomPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE), "Using BorderLayout"));
containerPane.add(topPane);
containerPane.add(bottomPane);
frame.add(containerPane);
// frame.pack();
frame.setSize(500, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I didn't call pack() in this example because the size of both panels (or JLabels in this case was not tall enough to show the difference:
Using pack():
Calling setSize():
Additional tips
Don't forget to place your program on the Event Dispatch Thread (EDT), I did it by writing these lines on the main method:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Application().createAndShowGui();
}
});
Don't place all your code on the constructor, otherwise it will be hard to maintain
It looks like you can use GridLayout to do this. Here is what i think,
public class Application {
public static void main(String[] args) {
JFrame jframe = new JFrame();
jframe.setTitle("Title");
jframe.setResizable(false);
//This creates one row and two equally divided columns
GridLayout gridLayout = new GridLayout(0, 2);
jframe.setLayout(gridLayout);
gridLayout.layoutContainer(jframe);
JPanel leftPanel = new JPanel();
leftPanel.add(new Label("Left side"));
jframe.add(leftPanel);
JPanel rightPanel = new JPanel();
rightPanel.add(new Label("Right side"));
jframe.add(rightPanel);
jframe.setSize(800, 500);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Here is how it looks:
The panels will not resize as well as there is no line visible that seprates them.

Problems with BorderLayout() in Java

I've tried a lot of different ways, but I will explain two and what was happening (no error messages or anything, just not showing up like they should or just not showing up at all):
First, I created a JPanel called layout and set it as a BorderLayout. Here is a snippet of how I made it look:
JPanel layout = new JPanel();
layout.setLayout(new BorderLayout());
colorChoice = new JLabel("Choose your color: ");
layout.add(colorChoice, BorderLayout.NORTH);
colorBox = new JComboBox(fireworkColors);
colorBox.addActionListener(this);
layout.add(colorBox, BorderLayout.NORTH);
In this scenario what happens is they don't show up at all. It just continues on with whatever else I added.
So then I just tried setLayout(new BorderLayout()); Here is a snippet of that code:
setLayout(new BorderLayout());
colorChoice = new JLabel("Choose your color: ");
add(colorChoice, BorderLayout.NORTH);
colorBox = new JComboBox(fireworkColors);
colorBox.addActionListener(this);
add(colorBox, BorderLayout.NORTH);
In this scenario they are added, however, the width takes up the entire width of the frame and the textfield (not shown in the snippet) takes up basically everything else.
Here is what I have tried:
setPreferredSize() & setSize()
Is there something else that I am missing? Thank you.
I also should note that this is a separate class and there is no main in this class. I only say this because I've extended JPanel instead of JFrame. I've seen some people extend JFrame and use JFrame, but I haven't tried it yet.
You created a JPanel, but didn't add it to any container. It won't be visible until it is added to something (a JFrame, or another panel that is in a frame somewhere up the hierarhcy)
You added two components to the same position in the BorderLayout. The last one added is the one that will occupy that position.
Update:
You do not need to extend JFrame. I never do, instead I always extend JPanel. This makes my custom components more flexible: they can be added in another panel, or they can be added to a frame.
So, to demonstrate the problem I will make an entire, small, program:
public class BadGui
{
public static void main(String[] argv)
{
final JFrame frame = new JFrame("Hello World");
final JPanel panel = new JPanel();
panel.add(new JLabel("Hello"), BorderLayout.NORTH);
panel.add(new JLabel("World"), BorderLayout.SOUTH);
frame.setVisible(true);
}
}
In this program I created a panel, but did not add it to anything so it never becomes visible.
In the next program I will fix it by adding the panel to the frame.
public class FixedGui
{
public static void main(String[] argv)
{
final JFrame frame = new JFrame("Hello World");
final JPanel panel = new JPanel();
panel.add(new JLabel("Hello"), BorderLayout.NORTH);
panel.add(new JLabel("World"), BorderLayout.SOUTH);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}
Note that in both of these, when I added something to the panel, I chose different layout parameters (one label I put in 'North' and the other in 'South').
Here is an example of a JPanel with a BorderLayout that adds a JPanel with a button and label to the "North"
public class Frames extends JFrame
{
public Frames()
{
JPanel homePanel = new JPanel(new BorderLayout());
JPanel northContainerPanel = new JPanel(new FlowLayout());
JButton yourBtn = new JButton("I Do Nothing");
JLabel yourLabel = new JLabel("I Say Stuff");
homePanel.add(northContainerPanel, BorderLayout.NORTH);
northContainerPanel.add(yourBtn);
northContainerPanel.add(yourLabel);
add(homePanel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setTitle("Cool Stuff");
pack();
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(Frames::new);
}
}
The below suggestion is assuming that your extending JFrame.
Testing
First of all, without seeing everything, theres always a numerous amount of things you can try.
First off, after you load everything, try adding this in (Again, assuming your extending JFrame:
revalidate();
repaint();
I add this into my own Swing projects all the time, as it refreshes and checks to see that everything is on the frame.
If that doesn't work, make sure that all your JComponent's are added to your JPanel, and ONLY your JPanel is on your JFrame. Your JFrame cannot sort everything out; the JPanel does that.
JPanel window = new JPanel();
JButton button = new JButton("Press me");
add(window);
window.add(button); // Notice how it's the JPanel that holds my components.
One thing though, you still add your JMenu's and what-not through your JFrame, not your JPanel.

Java GUI FullScreen window with smaller window inside

I am working on a Java desktop application. It uses MySQL database to store all data etc. I use swing for the GUI.
The GUI of this application is layed out as follows:
Main Window taking the entire screen size (with image in the
background)
Internal Window 800 x 600 centered within the Main
Window (that holds current content that can be switched between
using menu and/or event within the application.
LoginPanel.java:
import javax.swing.*;
import java.awt.*;
public class LoginPanel {
private JPanel loginPanel;
public void loginForm()
{
JButton loginSubmit = new JButton("Login");
loginPanel = new JPanel();
loginPanel.add(loginSubmit);
loginPanel.setSize(800, 600);
}
public JComponent getGUI()
{
return loginPanel;
}
public static void main(String[] args)
{
}
}
Main.java:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args)
{
JFrame mainFrame;
mainFrame = new JFrame();
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setTitle("Caledonian Library System");
LoginPanel loginObj = new LoginPanel();
mainFrame.add(loginObj.getGUI());
mainFrame.pack();
mainFrame.setVisible(true);
}
}
Should I maybe use box layout? any suggestions?
Ok, I have just run a test program, and have achieved the result you are looking for. I have used a GridBagLayout which defaults to centre into the Container it is added to. It will not show up with the borders or other buttons built into a JFrame (though you can add a border if you wish later).
JFrame mainframe = new JFrame();
JPanel mainPanel = new JPanel();
GridBagLayout gridLayout = new GridBagLayout();
mainPanel.setLayout(gridLayout);
//GridBagConstraints allow you to set various features of the way the components appear
//in the grid. You can set this up as you wish, but defaults are fine for this example
GridBagConstraints gridConstraints = new GridBagConstraints();
//Just using FlowLayout as a test for now
JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(new JLabel("Hello"));
centerPanel.add(new JLabel("Centered"));
mainPanel.add(centerPanel, gridConstraints);
mainFrame.add(mainPanel);
If you found that the space around the side of your centered panel wasn't being used, and you wanted it to be use, you could try nesting mainPanel inside another panel that is using a BorderLayout, making sure that it is in BorderLayout.CENTER.
In the example I didn't bother changing GridBagConstraints from the default, as it was ok for this demonstration. However you can edit it as you wish, and then apply to each component you add to the GridBagLayout, making sure to include the GridBagConstraints object in each mainPanel.add(). Check the GridBagLayout tutorials for some good information.
Of course, if you would like more components in the centre other than the main window, you can then simply add them to the mainPanel (making sure to change the position in the GridLayout). There are going to be numerous ways of achieving what you want, but it really depends on what you feel looks good. The Layout Managers will do all of the resizing work for you.

JButton and jgraphx wont show up at the same time

I have tried several ways, but still havent found the solution. I have a jgraph in a frame and I want to add a Jbutton in that frame also in a specific location. However I only get one of them when i run the program, because they expand to the whole window. Any ideas how to fix this?
Thanks in advance.
public class GUIquery extends JFrame {
JFrame frame;
static JGraph jgraph;
final mxGraph graph = new mxGraph();
final mxGraphComponent graphComponent = new mxGraphComponent(graph);
public GUIquery() {
super("Test");
GraphD();
imgbtn();
}
public void GraphD() {
Object parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
try {
........
}catch {
........
} finally {
graph.getModel().endUpdate();
}
getContentPane().add(graphComponent);
}
public void imgbtn() {
JPanel jpanel = new JPanel();
jpanel.setSize(100, 100);
jpanel.setLocation(1200, 60);
JButton imgbtn = new JButton("Export as Image");
imgbtn.setSize(100, 100);
imgbtn.setLocation(1200, 60);
jpanel.add(imgbtn);
add(jpanel);
}
public static void main(String[] args) {
GUIquery frame = new GUIquery();
frame.setLayout(null);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 320);
frame.setVisible(true);
}
}
Don't use null layouts. They inevitably result in trouble.
From your code snippet it is impossible to tell where you want them to be relative to each other, the following puts the button below the graph.
The content pane uses BorderLayout by default. For BorderLayout, you need to use place components at different positions:
// the default position, but it does not hurt to be explicit
add(graph, BorderLayout.CENTER);
...
// and the panel
add(jpanel, BorderLayout.SOUTH);
If the positioning is not what you want, take a look at the visual guide to layout managers to pick the layout manager that suits your needs best.
In the button panel the setLocation() and setSize() calls are useless. The layout manager of the panel is responsible for setting the button's bounds. If the default FlowLayout is not what you want for it, use the guide to pick another for the panel too.

Categories