GUI, JComboBox and opening a new window - java

I am new to Java and especially new to GUI and it's super confusing to me right now.
I'm making a program for class that is supposed to have a menu (JComboBox I'm assuming) that opens a new window when an option is selected. I am just working on the first option where you click "The Matrix" and a new window pops up with two buttons called "Red Pill" & "Blue Pill" and thats where I've hit a wall.
I got to the point where I am able to create a new window (not sure if this is even the right route to take for opening the new window) but, When I try to add Buttons to the new pop up window nothing shows up....
Thanks for any help or pointers in the right direction!
public class MultiForm extends JFrame{
private JComboBox menu;
private JButton bluePill;
private JButton redPill;
private static String[] fileName = {"", "The Matrix", "Another Option"};
public MultiForm() {
super("Multi Form Program");
setLayout(new FlowLayout());
menu = new JComboBox(fileName);
add(menu);
TheHandler handler = new TheHandler();
menu.addActionListener(handler);
}
private class TheHandler implements ActionListener{
public void actionPerformed(ActionEvent event) {
********************************************************************
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setLayout(new FlowLayout());
newFrame.setSize(500, 300);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
Icon bp = new ImageIcon(getClass().getResource("Blue Pill.png"));
bluePill = new JButton("Blue Pill", bp);
newFrame.add(bluePill);
Icon rp = new ImageIcon(getClass().getResource("Red Pill.png"));
redPill = new JButton("Red Pill", rp);
newFrame.add(redPill);
add(panel);
newFrame.setVisible(true);
}
}
public static void main(String[] args) {
MultiForm go = new MultiForm();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(400, 200);
go.setVisible(true);
}
}

I tried doing newFrame.add(BluePill) and it created a button that was the size of the entire window and it would not allow me to add both buttons that way
That's because the frame uses a BorderLayout by default. Unless you specify otherwise, the component's will be added to the CENTER position, BUT, BorderLayout will only allow a single component to be managed at each of the it's five available positions, so you are only seeing the last component you added.
See How to Use BorderLayout for more details
so I figured that wasn't the correct way
It's the right approach, you just need to use a layout manager which can accommodate more components or change the position which you are adding the buttons
In this little example, I've just use a FlowLayout, but you can use what ever is going to give you the effect you desire
JFrame newFrame = new JFrame();
newFrame.setLayout(new FlowLayout());
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
newFrame.add(bluePill);
redPill = new JButton("Red Pill");
newFrame.add(redPill);
newFrame.pack();
newFrame.setVisible(true);
As a general rule of thumb, I don't like adding components like this directly to a top level container, I prefer to use a intermediate container, like a JPanel, this gives me more possibilities for re-use, but that's me.
You should also only make the frame visible when it's actually ready, otherwise you may find that some times, the components won't show up
See Laying Out Components Within a Container for more details

You are not using the getContentPane() method from the new JFrame.
You have to actually use getContentPane() first because you're not adding any component to the JFrame itself but to an intermediate "panel".
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setSize(300, 200);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
panel.add(bluePill);
redPill = new JButton("Red Pill");
panel.add(redPill);
newFrame.getContentPane().add(panel);
newFrame.setVisible(true);
You'll have to add a Layout to the JPanel or/and the JFrame and play with the sizes of the component but with this you're on the right path.
I always put the setVisible method a the end, after adding all the components to the frame.

You made some mistakes.
add(bluePill);
will not do what you want, even if it would, it would still be wrong.
(sounds weird, but I'll explain it)
First the "right" way to do it:
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
newFrame.setSize(300, 200);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
newFrame.getContentPane().add(bluePill);
redPill = new JButton("Red Pill");
newFrame.getContentPane().add(redPill);
newFrame.setVisible(true);
Notice I added "newFrame", because you were calling the method of MultiForm.
That's because "add()" is the same as "this.add()" and "this" points to MultiForm. Check it with this line if you want:
System.out.println(this.toString());
The "getContentPane()" is best explained with this image:
You were adding it directly to the JFrame (I don't even know what exactly happens then).
It is also good practice to set the frame visible when it is ready to be visible. Your frame did not contain anything when you made it visible.
Now to the JPanel. A JPanel can hold some elements like JButton,etc. and it can also have a layout. Since you didn't use the JPanel at all, i removed the line from your code. You can still add the JPanel to your ContentPane and add a Layout to the JPanel. (You can also add JPanels to JPanels to create complex layouts)
I hope this was clear for you.

Related

Reusing a Button in Java Makes Nothing Display

I am really new to GUI programming in Java so please forgive me if this code is really basic. In short, I want to have 2 panels that are the same design. After I press the "A" button on the panel 1, I want to make panel 2 appear with the same design. Making the GUI efficient or pretty doesn't currently matter to me. I just want it to work. I have parts of the code listed below.
JButton buttonA = new JButton("a");
JButton buttonB = new JButton("b");
JButton buttonC = new JButton("c");
JButton buttonD = new JButton("d");
JPanel pan1 = new JPanel();
JPanel pan2 = new JPanel();
setTitle ("Test");
setSize (640, 640);
setResizable(false);
GridLayout grid1 = new GridLayout();
setLayout (grid1);
FlowLayout flow1 = new FlowLayout();
pan1.setLayout (flow1);
pan1.add(buttonA);
pan1.add(buttonB);
pan1.add(buttonC);
pan1.add(buttonD);
buttonA.addActionListener(this);
buttonB.addActionListener(this);
buttonC.addActionListener(this);
buttonD.addActionListener(this);
FlowLayout flow2 = new FlowLayout();
pan2.setLayout (flow2);
pan2.add(buttonA);
pan2.add(buttonB);
pan2.add(buttonC);
pan2.add(buttonD);
add(pan1);
add(pan2);
pan1.setVisible(true);
pan2.setVisible(false);
setVisible(true);
public void actionPerformed(ActionEvent event) {
if (command.equals("a")){//i want to show the panel 2 after button a is pressed
System.out.println("HelloA");
pan1.setVisible(false);
pan2.setVisible(true);
}
Currently, it just shows nothing in the window. Any help guys?
Short answer is, you can't.
Long answer is, a component can only reside on a single parent. Adding a component to a second container will automatically remove it from the first container before its added to the new one.
Instead, you will need to create individual buttons for both containers.
Also, understand that BorderLayout can't support what you're trying to do, it will only manage one component at a time (in each of the 5 available positions)
A better solution would be to make use of the CardLayout which is designed to facilitate the action you are trying to achieve

How to implement pages in Java Swing app.?

I have some experience in Java creating Apps and would like to learn more, and so have decided to create an application that will have different pages. For example the initial frame will show a menu of buttons that will lead to different frames, showing different components and layouts.
I'm not too sure the best practice of implementing pages. I think I could store the JFrame windows in a list, then use a button handler class to maybe change the visibility of the different frames, only allowing the relevant frame to be visible when the user clicks on a button. I think this method could work, but is there a more efficient/practical way of doing this?
I am aware of CardLayout, however for this program I am trying to learn MigLayout; so that won't be possible (as far as I'm aware). I hope this question is not too vague, I'd just like to know the best practice when it comes to creating applications in Java with different pages.
Can use Tabbed Panes, it is the best for storing pages.
https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
Also I noticed that you need to consider top level containers properly, because you don't need to create every time a JFrame for each Page, at least if it was necessary(For example: an editor, create a new window so you need to create a new JFrame, in your case I don't think so) so please consider the link below.
https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html
JInternalFrame is a part of Java Swing . JInternalFrame is a container that provides many features of a frame which includes displaying title, opening, closing, resizing, support for menu bar, etc. Internal frames with components example
Code to create multiple internal frames:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
class solution extends JFrame {
// frame
static JFrame f;
// label to diaplay text
static JLabel l, l1;
// main class
public static void main(String[] args) {
// create a new frame
f = new JFrame("frame");
// set layout of frame
f.setLayout(new FlowLayout());
// create a internal frame
JInternalFrame in = new JInternalFrame("frame 1", true, true, true, true);
// create a internal frame
JInternalFrame in1 = new JInternalFrame("frame 2", true, true, true, true);
// create a Button
JButton b = new JButton("button");
JButton b1 = new JButton("button1");
// create a label to display text
l = new JLabel("This is a JInternal Frame no 1 ");
l1 = new JLabel("This is a JInternal Frame no 2 ");
// create a panel
JPanel p = new JPanel();
JPanel p1 = new JPanel();
// add label and button to panel
p.add(l);
p.add(b);
p1.add(l1);
p1.add(b1);
// set visibility internal frame
in.setVisible(true);
in1.setVisible(true);
// add panel to internal frame
in.add(p);
in1.add(p1);
// add internal frame to frame
f.add(in);
f.add(in1);
// set the size of frame
f.setSize(300, 300);
f.show();
}
}

JCheckBox centereing

I have been searching for a while now, but couldnt find a solution so I have decided to ask here.
I am using Java Swing for my gui implementation of calculator. I have custom made layout(which works correctly 100%). I have added all buttons and all buttons are positioned correctly, always. Last component I have inserted is "Inv" and it is checkbox which I cant find a way to center it inside its area. I have tried putting it in panel,in panel with borderlayout.center, setting the horizontal and vertical text alignment, but nothing works.
invert = new JCheckBox("Inv");
invert.setBackground(Color.decode("#8DA336"));
invert.addActionListener(new CommandListener(this,"invert"));
container.add(invert, new RCPosition(5, 7));
This RCPosition is nothing more than object which says in which row and column this component is (nothing wrong with that).
Checkbox is by default left-aligned. Try make it center-aligned:
invert = new JCheckBox("Inv");
invert.setHorizontalAlignment(SwingConstants.CENTER);
// styling and add to container
If it don't help, then you should publish your layout manager.
You could try putting it in a JPanel with BoxLayout, then add horizontal glue on the left and right.
final JFrame frame = new JFrame();
final JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.X_AXIS));
jp.add(Box.createHorizontalGlue());
final JCheckBox jcb = new JCheckBox("inv");
jp.add(jcb);
jp.add(Box.createHorizontalGlue());
frame.getContentPane().add(jp);
frame.pack();
frame.setLocationRelativeTo(null);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
This is just one way to do it, setHorizontalAlignment should work as well.

JLabels not showing up

I am trying to figure why I can't see my labels like when I try to put 2 labels into 1 panel they dissapear, the only way I can seem to get it to work is if I add everything to JFrame with no type of hierarchy.
import javax.swing.*;
import java.awt.*;
public class GUI extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
static JRadioButton tirebg1 = new JRadioButton();
static JRadioButton tirebg2 = new JRadioButton();
static JRadioButton tirebg3 = new JRadioButton();
static ButtonGroup tirebg = new ButtonGroup();
public static void main(String[] args) {
Car cspeed = new Car();
int carspeed = cspeed.getSpeed();
Motorcycle mspeed = new Motorcycle();
int motospeed = mspeed.getSpeed();
Truck tspeed = new Truck();
int truckSpeed = tspeed.getSpeed();
JRadioButton wide = new JRadioButton();
JLabel tbuttons = new JLabel();
JPanel topPane = new JPanel();
tirebg.add(tirebg1);
tirebg.add(tirebg2);
tirebg.add(tirebg3);
JFrame GUIframe = new JFrame();
JLabel label1 = new JLabel();
label1.setLayout(new FlowLayout());
JLabel tireLabel = new JLabel();
String[] names = new String[5];
names[0] = "Car";
names[1] = "Truck";
names[2] = "Motorcycle";
String[] hello = new String[5];
GUIframe.setSize(500, 500);
GUIframe.setDefaultCloseOperation(EXIT_ON_CLOSE);
JList list = new JList(names);
list.setBorder(BorderFactory.createRaisedSoftBevelBorder());
label1.add(list);
tireLabel.add(tirebg1);
tireLabel.add(tirebg2);
tireLabel.add(tirebg3);
topPane.add(tbuttons);
topPane.add(tireLabel);
topPane.setLayout(new FlowLayout());
label1.setBackground(Color.cyan);
GUIframe.add(topPane);
GUIframe.validate();
GUIframe.setBackground(Color.GREEN);
GUIframe.setVisible(true);
}
}
Since you posted a lot of code and I'm not sure what were you trying to achieve, I modified your code adding 3 JLabels at the topPane. And 3 JRadioButtons (I didn't add the ButtonGroup) below on a second JPanel, I commented how to make them appear on a vertical and horizontal align.
Something you should take into account is:
Don't extend and create objects from JFrame (One or the other, not both, I recommend you to create objects).
You were giving your JPanel a Layout after adding components to it, it should be done before.
From the above point, you were also giving your Layout to your JLabel not your JPanel.
You were adding a JList into a JLabel.
You missed to have a class constructor too.
Don't have multiple JFrames for more see The use of multiple JFrames, Good / Bad practice
Next time post a code which has no dependencies such as your Truck, Car and Motorcycle classes (i.e. a Runnable example). And use plain text instead so we can copy-paste the code and see the issue. Also try posting images (or the link and we can edit to add it).
Now, the outpus of my own program are:
And it was done with the following code.
import javax.swing.*;
import java.awt.*;
public class GUIExample {
JFrame frame;
JLabel label1, label2, label3;
JPanel topPane, radioPane;
JRadioButton radio1, radio2, radio3;
public static void main(String[] args) {
new GUIExample();
}
GUIExample () {
frame = new JFrame();
topPane = new JPanel();
radioPane = new JPanel();
topPane.setLayout(new FlowLayout());
// radioPane.setLayout(new BoxLayout(radioPane, BoxLayout.PAGE_AXIS)); //Vertical align
radioPane.setLayout(new FlowLayout()); //Horizontal align
label1 = new JLabel("Car");
label2 = new JLabel("Motorcycle");
label3 = new JLabel("Truck");
radio1 = new JRadioButton("Radio1");
radio2 = new JRadioButton("Radio2");
radio3 = new JRadioButton("Radio3");
topPane.add(label1);
topPane.add(label2);
topPane.add(label3);
radioPane.add(radio1);
radioPane.add(radio2);
radioPane.add(radio3);
frame.add(topPane, BorderLayout.PAGE_START);
frame.add(radioPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Your code has several issues, but the reason that you're not seeing the tireLabel or the tbuttons component is because you're using a JLabel. Understand that JLabel is not built to act as a container for other components. The key concept is that it calculates its preferred size based on the text it holds and/or the icon it holds and (and this is key) not on the sizes or preferred sizes of any components it might hold.
The solution is to not use JLabel for a purpose it wasn't intended for but rather to use a JPanel which does adjust its own preferred size depending on the sizes of its held components and its layouts.
Other unrelated issues:
Your program extends JFrame but never uses itself as a JFrame, something that will confuse anyone who reads your code. If you're not going to use the instance of the class as a JFrame, then don't extend the class.
Your program isn't an OOP-compliant program, one with instance fields, public methods, and such, but rather is little more than one large static main method, and this will result in a large God-method, one with too much responsibility, and one that is very difficult to debug and to maintain. Don't throw out the OOP baby with the bath water -- Create Swing GUI's in a well-behaved OOP-compliant way.
You're trying to set background colors to components that are not opaque (a JLabel), to components that are never added to the GUI (label1), or are not fully displayed (the JFrame).
You're using FlowLayout an awful lot, and in places where other layouts would probably serve you better. It's as if it's the only layout that you know how to use, and so you use it. Try branching out and using other layouts including GridLayout for your JRadioButton container and perhaps BorderLayout for the main container (JPanel).

JTabbedPane in JPanel?

I have a simple problem when I want to add tabs in my jpanel. The alignment of the tabs get horizontal instead of vertical, wich looks like crap =/.
It looks like this:
If I discard the panel instead and add the tabbedPane directly to the frame, everything works fine.
If you uncomment the three lines of code and remove the getContentPane().add(jtp); you can reproduce my probleme.
working Code:
public class TabbedPane extends JFrame
{
public TabbedPane()
{
setTitle("Tabbed Pane");
setSize(300, 300); // set size so the user can "see" it
JTabbedPane jtp = new JTabbedPane();
// JPanel panel = new JPanel();//uncomment all three lines
// panel.add(jtp);
// getContentPane().add(panel);
getContentPane().add(jtp);//remove me
JPanel jp1 = new JPanel();// This will create the first tab
JPanel jp2 = new JPanel();// This will create the second tab
JLabel label1 = new JLabel();
label1.setText("This is Tab 1");
jp1.add(label1);
jtp.addTab("Tab1", jp1);
jtp.addTab("Tab2", jp2);
JButton test = new JButton("Press");
jp2.add(test);
setVisible(true); // otherwise you won't "see" it
}
public static void main(String[] args)
{
TabbedPane tab = new TabbedPane();
}
}
Thanks a lot!
If I discard the panel instead and add the tabbedPane directly to the frame, everything works fine.
The default layout of JPanel is FlowLayout, which "lets each component assume its natural (preferred) size." The default layout of JFrame is BorderLayout, the CENTER of which ignores preferred size. In either case, invoking setSize() precludes the layout from functioning initially; re-size the frame to see the effect. Instead, use pack(), which "Causes this Window to be sized to fit the preferred size and layouts of its subcomponents."
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true); // otherwise you won't "see" it
There are many things I would change in that code, starting with the recommendations of #trashgod. OTOH this is the minimal change needed in order to stretch the tabbed pane to the width/height of the parent container.
// give the panel a layout that will stretch components to available space
JPanel panel = new JPanel(new GridLayout());//uncomment all three lines
panel.add(jtp);
getContentPane().add(panel);
//getContentPane().add(jtp);//remove me
For more details see this answer.
Well firstly you can try this:
JPanel panel = new JPanel();//uncomment all three lines
panel.setLayout(new GridLayout());
JPanel jp1 = new JPanel();// This will create the first tab
JPanel jp2 = new JPanel();// This will create the second tab
JLabel label1 = new JLabel();
label1.setText("This is Tab 1");
jp1.add(label1);
jtp.addTab("Tab1", jp1);
jtp.addTab("Tab2", jp2);
JButton test = new JButton("Press");
jp2.add(test);
getContentPane().add(jtp);
and in the main:
TabbedPane tab = new TabbedPane();
tab.pack();
tab.setVisible(true);
May I suggest using MigLayout to set layouts, it will make your life easier. Hope it helps.
Try GridbagLayout. Once you have mastered it, you can design UI of any sort with this layout.
I agree with prasanth regarding the use of GridBagLayout
I have gone through this problem once and I solved it by adding the JTabbedPaneto the panel via GridBagLayout, make sure you add the JTabbedPane using the ipadx and ipady according to your requirements in your GridBagConstraints object
e.g.
JPanel myPanel=new JPanel();
myPanel.setLayout(new GridBagLayout());
JTabbedPane jTP=new JTabbedPane();
jTP.add("Tab1",new JPanel());//substitute your component instead of "new JPanel"
GridBagConstraints myConstraints=new GridBagConstraints();
myConstraints.ipadx=400;//streches the component being added along x axis - 200 px on both sides
myConstraints.ipady=600;//streches the component being added along y axis - 200 px on both sides
myPanel.add(jTP,myConstraints);
You can adjust both these properties according to what is perfect for your need

Categories