How to draw two JPanels on top of each other? - java

I am currently working on a N-Body simulation and I have made particles move on a black screen. My current problem is that there is no way of controlling it.
My plan:
Each color stands for a different JPanel. The blue one should contain the buttons and text fields, the red one the viewport.
But with my small knowledge in Java, I didn't succeed in creating this. I first tried with setBounds and setLayoutManager(null), in vain.
My structure goes like that:
Window class extends JFrame
Simulation class creating blueJPanel class (extends JPanel) and redJPanel,
adds them to the window.
But this is garbage code... So how would you draw these simple panels on top of each other?

Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
As I said in my comment, you create two JPanels. Here's an example.
Here's the complete runable code to create this example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BorderLayoutExampleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorderLayoutExampleGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("BorderLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButtonPanel(), BorderLayout.NORTH);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 100));
panel.setBackground(Color.blue);
// Add the buttons and text fields
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 380));
panel.setBackground(Color.red);
// Add the drawing code
return panel;
}
}

Related

Is it possible to create a panel with a class on the left and right side?

I have been practicing my code with Java Swing and have gotten decent on controlling where to place some items, such as labels and or buttons, but I was wondering if you can do the same with classes? I have just a simple class with enough code to put a button in it and that's it, that I am trying to create an instance of the class and then control for to put on the left and right side but when I do, all it does is create two separate windows with the button in the middle and that's it. Am I doing something wrong, or can you not do classes the same way?
The code:
import java.awt.Color;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Fun extends JFrame
{
private final int WIDTH = 500;
private final int HEIGHT = 400;
public Fun()
{
setTitle("Fun Management");
setSize(WIDTH, HEIGHT);
BuildPanel west = new BuildPanel(); /// BuildPanel is the name of the class that has just a button in it.
BuildPanel east = new BuildPanel(); ///
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(west, BorderLayout.WEST); /// I am doing the same thing with the instances as I would with buttons or labesl
add(east, BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args)
{
new Fun();
}
}
I took your code and created the following GUI.
Oracle has a rad tutorial, Creating a GUI With Swing, that will show you how to create Swing GUIs. Skip the Netbeans section.
Always start your Swing application with a call to the SwingUtilities invokeLater method. This method ensures that your Swing components are created and executed on the Event Dispatch Thread.
Use Swing components. Don't extend a Swing component unless you want to override one or more of the component methods.
The JFrame methods must be called in a specific order. This is the order I recommend for most Swing applications. Use the JFrame pack method and let the components size the JFrame.
I created a BuildPanel class to build a JPanel. There are good reasons to do this, but be careful. You have to manage each instance of the class you create. As an example, what if you want the text of the two buttons to be different? What if you want to assign two different ActionListener classes, one to each button?
Here's the complete runnable code. I made the BuildPanel class an inner class so I can post the code as one block.
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TwoPanelExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TwoPanelExample());
}
#Override
public void run() {
JFrame frame = new JFrame("Fun Management");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BuildPanel west = new BuildPanel();
BuildPanel east = new BuildPanel();
frame.add(west.getPanel(), BorderLayout.WEST);
frame.add(east.getPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class BuildPanel {
private final JPanel panel;
public BuildPanel() {
this.panel = createMainPanel();
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 30, 5, 30));
JButton button = new JButton("Click Me");
panel.add(button);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
}

How do i add an image in Java?

frame.add(new JLabel(new ImageIcon("C:/Users/Sam/Pictures/DesktopBackgrounds/image.png")));
I saw this on another question so i tried to use it and the class runs with no errors however no image is on the screen.
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
class FullSceenToggleAction extends AbstractAction {
private JFrame frame;
private GraphicsDevice fullscreenDevice;
public FullSceenToggleAction(JFrame frame) {
this(frame, GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice());
}
public FullSceenToggleAction(JFrame frame, GraphicsDevice fullscreenDevice) {
this.frame = frame;
this.fullscreenDevice = fullscreenDevice;
}
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
if (frame.isUndecorated()) {
fullscreenDevice.setFullScreenWindow(null);
frame.setUndecorated(false);
} else {
frame.setUndecorated(true);
fullscreenDevice.setFullScreenWindow(frame);
}
frame.setVisible(true);
frame.repaint();
}
}
public class Main {
public static final void addKeyBinding(JComponent c, String key, final Action action) {
c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(key), key);
c.getActionMap().put(key, action);
c.setFocusable(true);
}
public static void main(String[] args) {
final JFrame frame = new JFrame("Fullscreen Toggle Test");
Container contentPane = frame.getContentPane();
contentPane.add(new JLabel("Hey"), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(960, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setTitle("Virtual World");
frame.add(new JLabel(new ImageIcon("C:/Users/Sam/Pictures/DesktopBackgrounds/image.png")));
addKeyBinding(frame.getRootPane(), "F11", new FullSceenToggleAction(frame));
}
}
In case you need it this is the full code.
There are several issues with your codes. In Swing, the order of your codes does makes a difference.
Code order issue:
Currently you are adding an image to the frame after you set the size. When the frame size changes, the paint manager will be consulted to repaint the frame. Hence you will only be able to see the "Hey" label you added earlier but not the image.
It is advisable to set the size after you added all the components you need. If not, you may want to revalidate() your frame later.
I will usually setup the components in the following order:
// Create frame
// Set default close operation for frame
// Add components or container to frame
// pack the frame (frame will be repainted by this action)
// set visible as true
Layout issue:
You are using the frame's default layout (BorderLayout). If you do not state the position/direction for the components to be added in BorderLayout, it will be added to the CENTER by BorderLayout's default.
In your codes, you added the image (2nd label) without stating the position (String specification). Doing so will replace the first label with the second label. Hence only one component will be shown in the frame.
Other issues:
There are some other issues which I would summarize below:
It is advisable to setVisible(true) last to prevent flickering issues.
I would prefer to add another container such as JPanel into the JFrame and add the components in the panel instead of adding directly to the frame.
With the above, you can pack() the frame which allows it to determine its own preferredSize according to the added components.
Try adding imageIcon Label to content pane works.
Container contentPane = frame.getContentPane();
contentPane.add(new JLabel("Hey"), BorderLayout.SOUTH);
contentPane.add(new JLabel(new ImageIcon("C:/Users/Sam/Pictures/DesktopBackgrounds/image.png")));
you may find the code helpful.I posted this code for understanding purpose.
public class AddingIconJLabel {
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame();
frame.setTitle("JLabel Test");
frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon imageIcon = new ImageIcon("C:/Users/Sam/Pictures/DesktopBackgrounds/image.png");
JLabel label = new JLabel(imageIcon);
frame.add(label);
frame.pack();
frame.setVisible(true);
}
}
this will output the following..Hope you found my help useful.

jPanel and jButton customization

I'm trying to learn how to code Conway's game of life in Java, and I'm getting stuck creating the GUI. I want to make a JPanel within the JFrame, with a larger border at South, and then two buttons in the south border, one for "Play" and one for "Restart." But the Design element won't let me resize or move anything around. I was able to resize the JPanel by going into the code and creating a larger border in the South, but I can't figure out how to resize the JButton. Any ideas?
(I'm using Eclipse Kepler...I hear NetBeans is better at this kind of stuff, should I just ditch Eclipse and try it with NetBeans?)
Here's my code so far:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JButton;
public class GameOfLife extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameOfLife frame = new GameOfLife();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GameOfLife() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 518, 508);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(10, 10, 50, 10));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
panel.setBackground(Color.GRAY);
contentPane.add(panel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
contentPane.add(btnNewButton, BorderLayout.SOUTH);
}
}
Basically, instead of doing BorderLayout.SOUTH, I want to manually place it where I want it within the frame. I'd also love to be able to do that with the JPanel--the whole North/West/South/East/Center thing in general seems very constricting. What's the way around it?
Maybe you should look at Swing Layouts in Java documentation:
A Visual Guide to Layout Managers
And the layout which is able to give you the most flexibility is the GridBagLayout but you will write much code to display the User Interface as your needs.
You will have a detailled way to go with the following official tutorial:
How to Use GridBagLayout
In your code, you are using the simple BorderLayout which is very simple but not so much configurable.

How can I keep the vlcj player from taking up all the room?

I am writing a small Swing program which involves embedding a video player in the interface. In order to achieve this, I am using vlcj.
While the GUI itself has some more components, here is an analog code structure:
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import javax.swing.*;
import java.awt.*;
public class MyTestClass extends JFrame {
public MyTestClass(){
EmbeddedMediaPlayerComponent playerCmpt =
new EmbeddedMediaPlayerComponent();
playerCmpt.setPreferredSize(new Dimension(200, 100));
JPanel leftPane = new JPanel();
leftPane.setPreferredSize(new Dimension(100, 100));
JSplitPane mainSplit = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
leftPane, playerCmpt);
this.add(mainSplit);
this.pack();
this.setVisible(true);
}
public static void main(String[] args){
new MyTestClass();
}
}
(I tried this code separately, and I'm facing the same problem as in my GUI)
Basically, the window has two parts: a left panel in which I display some data, and a right panel in which the video is to be embedded. The panels are put together in a JSplitPane is order to allow the user to allocate the amount of room he desires for the player (and therefore, for the video itself). At first, the components get 100 and 200 pixels in width, respectively.
The problem is: EmbeddedMediaPlayerComponent is getting a little too confortable. While I have set it to a preferred size of 200x100, it refuses to shrink down once the vertical split has been moved. That is, I can't bring the player below 200 pixels in width, and once I've enlarge it, I can't bring it back to 200 pixels... Setting a maximum size doesn't change anything. This little problem is annoying because it forces my left panel to shrink again and again, until it becomes practically invisible.
Is there any way I could have the media player follow the constraints set by JSplitPane as the user tries to resize the components? If it's any use, the left pane contains a JTree in my application, which also gets crushed by the player.
This one works for me. Just improve the code to fit for your purpose.
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import java.awt.*;
import javax.swing.*;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
public class MyTestClass extends JFrame {
public MyTestClass() {
String vlcPath = "C:\\Program Files (x86)\\VideoLAN\\VLC";
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), vlcPath);
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
EmbeddedMediaPlayerComponent playerCmpt = new EmbeddedMediaPlayerComponent();
playerCmpt.setPreferredSize(new Dimension(200, 100));
JPanel leftPane = new JPanel();
leftPane.setPreferredSize(new Dimension(100, 100));
JPanel playerPanel = new JPanel(new BorderLayout());
playerPanel.add(playerCmpt);
JSplitPane mainSplit = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
leftPane, playerPanel);
playerPanel.setMinimumSize(new Dimension(10, 10));
this.add(mainSplit);
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new MyTestClass();
}
}

Wrapping JPanel around JCheckBox without any space - Swing

I want to display a vertical list of JCheckBox-es in a JPanel. But I have decided to wrap each JCheckBox with a JPanel, (thinking that i would need it in future). and i am going to stack these JPanels(containing one JCheckBox each) vertically in another JPanel using BoxLayout.
The BoxLayout is working as expected without any vertical space in between the JPanels added to them. My problem is with these inner JPanels containing individual checkbox. there is a considerable amount of space around the checkbox for each panel. I want to wrap these checkboxes tightly, so that the size of jcheckbox and that of the corresponding jpanel containing them are equal.
for these individual jpanel i have tried layouts - flowlayout and default layout. both didnt help.
How can i fix this? i just simply set the flowlayout and add the jcheckbox directly to the jpanel. no other code i have used.
I am adding an example code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TryBox implements Runnable{
/**
* #param args
*/
public static void main(String args[])
{
SwingUtilities.invokeLater(new TryBox());
}
public void run()
{
class InnerPanel extends JPanel
{
public InnerPanel(int i) {
// TODO Auto-generated constructor stub
setLayout(new FlowLayout());
setBackground(new Color(i*50, i*50, i*50));
add(new JCheckBox("CheckBox "+i));
}
}
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
for(int i=0;i<5;i++)
{
outerPanel.add(new InnerPanel(i));
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane sp = new JScrollPane(outerPanel);
frame.setPreferredSize(new Dimension(200, 600));
frame.getContentPane().add(new JScrollPane(outerPanel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
here frame.setPreferredSize(new Dimension(200, 600)); is making the difference. i want the jpanels to reduce to the size of jcheckboxes. i dont want the jcheckboxes to fit into jpanel's size. if any extra vertical space is there in the container i want it to be left free.
The default layout of JPanel is FlowLayout, and the default constructor creates "a default 5-unit horizontal and vertical gap." You can specify no gap:
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
In addition, the JCheckBox UI delegate adds Insets that vary by L&F. I would be wary of changing these: the size is negligible and typically required to accommodate selection indication.
Did you try setting the margin and border insets to 0 (on the Swing components)?

Categories