Display a grid of JPanels in a JFrame? - java

I'm very new to Java but have some experience with C++. This is a homework assignment so I'm really just looking for someone to point me in the right direction.
The assignment requires a JFrame with JPanel objects displaying every card in a deck in a 13x4 grid. The Professor has supplied us with some code to get us started:
import javax.swing.*;
import java.awt.*;
public class Main
public static void main(String[] args)
{
//load the card image from the gif file.
final ImageIcon cardIcon = new ImageIcon("cardImages/tenClubs.gif");
//create a panel displaying the card image
JPanel panel = new JPanel()
{
//paintComponent is called automatically by the JRE whenever
//the panel needs to be drawn or redrawn
public void paintComponent(Graphics g) {
super.paintComponent(g);
cardIcon.paintIcon(this, g, 20, 20);
}
};
//create & make visible a JFrame to contain the panel
JFrame window = new JFrame("Title goes here");
window.add(panel);
window.setPreferredSize(new Dimension(200,200));
window.pack();
window.setVisible(true);
}
}
I have tried out a few things, but I can't seem to get multiple panels to display. Should I use a gridLayout() feature? or just create multiple panels and specify each one's location in the frame?
Again if someone can just point me in the right direction that would be awesome.

For displaying elements at the same size, evenly distributed within the container, then yes, GridLayout would be a good choice.
If you need to display the components in the grid at there preferred size (which may be different for each component) then GridBagLayout would be a better choice
If the code was supplied by a your professor, then you need to go back and make them fix it.
Firstly, a JLabel would be easier and provide better support for what you are trying to achieve...
Secondly, because the JPanel doesn't override getPreferredSize, most of the layout managers will set the size of the component to 0x0

There is a way to display multiple JPanels in one JFrame. Unlucky you the way is not so easy. Java has many diffrent LayoutManagers.
For your purpose I would recommend GridBagLayout, it is more complex, but definately the thing you need.
Here is a good tutorial, which helped me to understand it:
GridBagLayout
Hope it is a help.

Related

JFrame and JPanel sizing

I have a JFrame and a few JPanels that are displayed depending on where the user goes (to login, homepage etc), is there a way to set all JPanels to the same size without having to manually specify?
public mainApp() {
main = new JFrame("Application");
main.setSize(640, 480);
main.setVisible(true);
}
private JPanel loginScreen() {
login = new JPanel(null);
login.setSize(640, 480);
login.setVisible(true);
}
For example I have 5 different JPanels, and have to specify the size in each, is there a way to set a default size that is the same as the JFrame?
You have different valid options here. Knowing that you want to change from one view to another and keep the same size, it sounds like the best option would be to use a CardLayout allowing you to change between the different views without having to worry about repainting and revalidating stuff (this tutorial from Oracle helped me a lot back when I was learning to use this layout: Oracle - How to use CardLayout.
However, as usual with Swing/AWT this is not the only valid option. For example, you could also use the BorderLayout that is applied by default to the ContentPane from the JFrame and add the desired JPanel to the Center of that BorderLayout. However, you would have to manage the view-changing process in this case.

Elements don't appear in a Panel with a GridLayout or FlowLayout, but with a setBounds they do

I'm doing a program that is composed by multiple panels in a JFrame.
I need to do every elements in differents classes (It's because in my school, we need to have every elements separeated in different classes for clean code), but every example that I see with my kind of problem, they do everything in one class.
And I think that my problem comes from having multile classes so I show you my classes.
I have a panel in wich I need to put 2 panel, here is the code :
public class Inscription extends JPanel{
private PanneauBoutons panneauBoutons = new PanneauBoutons();
private PanneauFormulaire panneauFormulaire = new PanneauFormulaire();
public Inscription(){
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
this.add(panneauFormulaire,BorderLayout.CENTER);
this.add(panneauBoutons,BorderLayout.SOUTH);
this.setVisible(true);
}
}
And here is the Panel panneauFormulaire :
public class PanneauFormulaire extends JPanel{
private JLabel labelMatricule;
private JTextField zoneTexteMatricule;
public PanneauFormulaire(){
this.setLayout(new GridLayout(8,2,10,10));
this.setBorder(BorderFactory.createLineBorder(Color.black));
labelMatricule = new JLabel("Matricule : ");
this.add(labelMatricule);
zoneTexteMatricule = new JTextField(30);
this.add(zoneTexteMatricule);
this.setVisible(true);
}
So the problem Inscription don't appear on the main Frame if I don't do setBounds, but I want a BorderLayout...
(I tested and with a set bounds I can see the borders, so I think that it means the panel are really added to the Frame so why without setBounds I see anything?).
And the other problem is that the panel PanneauFormulaire don't appear on the Inscription panel...
So if I miss something, can you help me? thank you
And here it is the class that extends JFrame :
public class FenetrePrincipale extends JFrame {
private Container cont;
private Inscription inscriptionForm;
public FenetrePrincipale(){
super("IESN");
setBounds(100,100,1200,960);
getContentPane().setLayout(null);
setLocationRelativeTo(null);
setResizable(false);
...
inscription.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
cont.removeAll();
inscriptionForm = new Inscription();
inscriptionForm.setOpaque(true);
cont.add(inscriptionForm);
invalidate();
repaint();
}
});
You should NOT be using a null layout and setBounds(). Swing was designed to be used with layout managers.
but when I click on an option in the menu, the current panel need to be change by another one,
Then you should be using a CardLayout.
Read the section from the Swing tutorial on How to Use CardLayout for working examples. So download the example and use it as the starting point of your project. The code will be better structured then what you currently have and it is easier to change working code than it is to fix broken code.
so why without setBounds I see anything?
That is because you set your layout to null in getContentPane().setLayout(null);.
Java containers comes with a default layout which you are allowed to set to a different one. How the components are arranged in the container are dependent on the layout you use. The layout will directly affects the location, alignment, spacing, dimension, preferredSize of the components.
However, if you choose not to use any layout (.setLayout(null)). Swing will not know how you want the components to be arranged, hence you see nothing in your content pane.
Since you wanted "absolute control" over the components, you will be expected to set the bounds (location and dimension) of each added component manually by yourself. This is why you are not seeing any components (even if you already added it) until you set the bounds for them.
Java, elements don't appear in a Panel with a GridLayout or FlowLayout, but with a setBounds they do
Every layout has their own characteristics and for some of them the order of your codes does makes a difference. Hence, I will advise you to go through what each layout can do for you. Then, depending on your needs, choose one (or a combination of a few) and study how to use it.
And here it is the class that extends JFrame :
You probably won't want to extends to a JFrame. You can always make a customized Container like JPanel and add it to the frame.
(Why would you want to paint your paintings on a frame instead of a piece of paper?)

How to add a drawing (paint method) and another panel with controls in one frame?

I need to have a JFrame where the upper part is a drawing made by paint() and the lower part is a panel composed of JLabel, JTextField and JButton components.
Is this possible? How am I supposed to do this?
I need to have a Jframe where the upper part is a drawing made by paint() and the lower part is a panel composed of JLabel, JTextField and JButtons.
There is no conflict on what you want to do. You can have a main JPanel with 2 sub panels. One on the top for your drawings, the other at the bottom for containing your JComponents such as JButtons:
The structure in code may look like this:
class MainPanel extends JPanel{
private DrawingSpace drawingSpace; //Customized JPanel for drawing
private JPanel subPanel;
public MainPanel(){
setPreferredSize(new Dimension(400, 400));
initComponents();
}
private void initComponents(){
drawingSpace = new DrawingSpace();
subPanel = new JPanel();
}
}
You can have a customized JPanel as follows (this is optional):
class DrawingSpace extends JPanel
{
public DrawingSpace(){
//Set size..etc
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//perform your drawings here..
}
}
After the implementations for the JPanels, you can just add an instance of MainPanel to the JFrame:
JFrame frame = new JFrame();
frame.add(new MainPanel());
//Other codes for JFrame not shown here
The soulution suggested by user3437460 (use a JPanel for the upper part, and override the painting methods in that JPanel) is the preferrable way to solve this.
However as you asked for a solution to directly paint the upper part (which is not advised, but there are solutions):
A (nasty) workaround for the question would be overriding the necessary paint method of JFrame, draw your upper part, translate the graphics context by some 100 pixels and call inherited paint methods to draw the bottom part. (Note that you'll have layout manager issues, as the layout manager won't see the 100px height of the upper part. However, if you're using an absolute layout, it could work. Hacks, hacks hacks :(
Another super-hack is to actually make the lower part big enough (if you use absolute layout, position your lower part at y=100px). Then add your own GlassPane and render the content for the upper part (or anywhere) on the glassPane.
Of course you can create a dedicated layout manager, which leaves the top 100 px part empty. Use that layout manager, and then you get some empty space on the top, which you can draw on.
I think now you can agree that the problem is rather "how to put a custom drawn component on the top of the window", which is solved by putting a custom drawn JPanel on the top of the window. Keep it easy! Peace!
ps: override paintComponent() instead of paint() of JPanel. See bottom of http://www.oracle.com/technetwork/java/painting-140037.html
For the painting portion, create a JPanel (or other paintable component) and override the paint method. Use a second JPanel and place all of your other components in that.
From there, check out how to do layout management at https://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#set
The simplest way to do this is to use GridLayout, with the painted panel on the top half and the components panel on the bottom half.

Making a glassPane fit with the dimensions of a JPanel

StackOverflow!
I'm working on a project, in regards to making a navigation system, and we're in the beginning stages, working with drawing the map and navigating it itself.
We have a function, where you should be able to draw a square on top of the current data having been drawn already. I want to avoid having to repaint all of the data for the roads all over again, with each mouseDragged action event. To do this, I found that using a glass pane would be the optimal choice.
The problem recides with the dimensions of the glasspane and the coordinates it reads. When I click on a certain spot on our JPanel (which we use to draw on), it knows how and where to zoom in properly, but when I draw my square, it is being drawn a specific amount of pixels above my mouse's position. This seems to be due to the fact that my glass pane dimension does not correspond to my JPanel dimensions. The glass pane seems to also cover my menubar, whereas the JPanel itself does not read clicks which occur on the menubar.
I want to somehow fit a glasspane to my JPanel, and I've tried a few different things.
One thing I tried, was to draw on a JRootPane instead of a JPanel, but that doesn't seem to be possible. Then I tried to just retrieve the "MyGlassPane" class from my JPanel (which also has its own class), and call it's repaint method, but that's where the issue originated from.
Most lately, I've retrieved the JRootPane which the JPanel itself uses or is part of, and then retrieved the glasspane of this JRootPane, but it seems that my menubar, added to the JFrame, is also part of this JRootPane, meaning that the glasspane covers the menubar as well.
Here is some very simplified code, which covers the issue, but not the mouse-listening nor data-drawing aspects. It does however show off the fact that it's annoying that the rectangle is being drawn on top of the menubar.
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
public class TestForRootPaneStuff {
JFrame frame = new JFrame();
JRootPane root;
JPanel panel = new JPanel();
JLabel label = new JLabel("Hello there!");
public void rootPanePls()
{
frame.add(panel);
panel.add(label);
root = panel.getRootPane();
JMenuBar menubar = new JMenuBar();
JMenu prettyMenu = new JMenu("Pretty");
menubar.add(prettyMenu);
frame.setJMenuBar(menubar);
MyGlassPane gp = new MyGlassPane();
root.setGlassPane(gp);
gp.setVisible(true);
gp.setEnabled(true);
gp.repaint();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(250, 250));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
TestForRootPaneStuff derp = new TestForRootPaneStuff();
derp.rootPanePls();
}
private class MyGlassPane extends JComponent implements ItemListener
{
//React to change button clicks.
#Override
public void itemStateChanged(ItemEvent e) {
setVisible(e.getStateChange() == ItemEvent.SELECTED);
}
//Draw the square for zoomToSquare
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.BLUE);
g.drawRect(10, 10, 100, 100);
}
}
}
And this is a corresponding screenshot, as a result of running this code. (I can't post direct images, due to lack of activity on here)
I hope my explaination makes at least a bit of sense. I'm aware that my explaination is perhaps a bit too in-depth as for actually resolving the issue, but I felt like it was necessary to invelop you guys a little bit more into my situation, and my reason for needing a solution for this.
TL;DR:
I need a way to make a glassPane (retrieved/set from somewhere) completely fit the dimensions of a specific JPanel, so that I can receive the same mouse event coordinates for both the JPanel and the glasspane. See code above for visualization of the issue.
Is there a smart way to go about this? Setting the RootPane glasspane was my final idea...
Thanks in advance, if anyone has any insight to bring!
Kirluu~
not an asnwer longer comment, just guessing based on wrong/uncomplete code posted here
use JLabel instead of JComponent, JComponent hasn't any LayoutManager in API, sure JLabel too, but it to be container very simple like as contianer, is transparent, anything in paintComponent can be (semi) transparent
your code is incompleted why is there ItemListener, don't put JComponents to JComponent as contianer, use JPanel instead, or mentioned opaque JLabel is easiests of ways for GlassPane, 1st code line should be super.paintComponent in paintComponent, dispose() all custom painting for anything placed/laid in GlassPane
JLabel can has easilly to copy the coordinates from JPanel, use ComponentListener added to JPanel, with delaing (350-600) events from ComponentListener (one event per one pixel) by using Swing Timer, EDIT if resize continue call timer.restart() </EDIT, if resize ended then Swing Action/ActionListener will fire setBounds for JLabel (whatever) placed in GlassPane
search for simple RepaintManager (just by covering JLabels bounds in GlassPane) for animation in GlassPane

What kind of box is this in java?

On the bottom of the container where it says Statistic, what kind of box is that. I am using JFrame and would like to duplicate that.
Thanks
The container you're seeing is a JPanel. Followed by adding a border to it. You can add a border with text, by doing.
// panel is a JPanel
panel.setBorder(BorderFactory.createTitledBorder("Title"));
You can read more about it on the Java Docs there is even a lot of examples, showing the various borders, etc.
There is even a "BorderDemo.java" you can get from the Java Docs.
It's a JPanel. It provides means for visually structuring elements into box-like containers. You can find more information on how to effectively use and style them here.
EDIT: Since you seem to be more interested in the style of the border than the name of the component being used in the example above here's a snippet using the border style on a panel.
import javax.swing.*;
public class MyPanelTestDrive{
public static void main(String [] args){
JFrame myFrame = new JFrame("Panel Test Drive");
myFrame.setSize(800,600);
JPanel myPanel = new JPanel();
myPanel.setBorder(BorderFactory.createTitledBorder("Panel Title"));
myFrame.add(myPanel);
myFrame.setVisible(true);
}
}

Categories