Java Swing interface issue - java

here's my problems : I tried to create a simple interface from where I can click on several buttons that call differents functions, and show the result (which always is text) in a jlabel.I tried to have 2 separates parts (north/south or east/west) The first area would contain a gridlayout or flowlayout of all my buttons and the 2nd area would show the text result.
Here are my declarations :
private static JButton b0 = new JButton("Creer Zone");
private static JButton b1 = new JButton("1");
private static JButton b2 = new JButton("2");
...
private static JButton b11= new JButton("11");
private static JButton b12 = new JButton("12");
private static JButton b14 = new JButton("Help");
private static JFrame windows = new JFrame();
private static JPanel container = new JPanel();
private static JLabel res = new JLabel();
and here is how i added them to the JFrame (which is really awfull to see) :
container.add(b0);
container.add(b1);
container.add(b2);
...
container.add(b12);
container.add(b14);
container.add(res);
windows.setSize(450,500);
windows.setContentPane(container);
windows.setLocation(150 , 150);
windows.setVisible(true);
I've tried to declare my jpanel with a gridlayout, a borderlayout and change the location (N S E W) and a flowlayout, i always ended up with the jlabel disapearing (which is bad because this jlabel show the result of my functions)
Any one have a simple way to help me overcome this ? Thanks a lot for any time you take

nicely explained on http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html

Another possible solution for your future endeavors is to look into WindowsBuilder. It basically simplifies your layout design by allowing you to just simply drag and drop your elements (Jframe, JtextField, etc) and then in the background WindowsBuilder will write the code for you. Mind you the only thing that you will have to really add/change is the naming conventions of the buttons and of course the eventHandlers, but honestly those are something that any designer would want to control... Hopefully this helps you!
https://developers.google.com/java-dev-tools/wbpro/

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

Is it possible to add multiple components to JPanel in one statement?

Question is quite simple. I realized my code could be cleaned up a little if I was allowed to add components to a JPanel like this:
//north panel
JPanel northPanel = new JPanel(new GridLayout(0,3));
btnAdd = new JButton("Add");
btnEdit = new JButton("Edit");
btnDelete = new JButton("Delete");
northPanel.add(btnAdd, btnEdit, btnDelete);
instead of like this:
//north panel
JPanel northPanel = new JPanel(new GridLayout(0,3));
btnAdd = new JButton("Add");
btnEdit = new JButton("Edit");
btnDelete = new JButton("Delete");
northPanel.add(btnAdd);
northPanel.add(btnEdit);
northPanel.add(btnDelete);
Is there a way to do it? I've looked around SO and the internet, including Oracle's documentation and I know there's not an .add() method built to this particular syntax, but I would like to know if there is another method with this functionality.
Good Solution:
Thank you all for your feedback. It does make sense that a single statement would actually be more convoluted if accomplished in the way I described. L. Mehmeti suggested storing the components in an array and creating a method which adds all components in the array, which suits the question perfectly. In this way, when there gets to be a lot of components, the order is easily kept track of, instead of having to search through a bunch of separate constructors and add statements.
I am very sorry, but i guess there is no way to do that. The only way i think is writing your own method. For example:
public static void main(String[] args) {
Example main = new Example("Example");
}
public Example(String title) {
super(title);
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JComponent[] components = new JComponent[3];
components[0] = new JLabel("Hello!");
components[1] = new JLabel("How are you?");
components[2] = new JLabel("I am fine. Thanks");
addComponents(panel, components);
add(panel);
setVisible(true);
}
public void addComponents(JComponent target, JComponent[] components) {
for(JComponent component : components) {
target.add(component);
}
}
Hope I could help.
You could create a method and call it in your init method.
public void addComponentsJ()
{
northPanel.add(btnAdd);
northPanel.add(btnEdit);
northPanel.add(btnDelete);
}
this will allow you to use
addComponentsJ()// to add all the components..
but, this is relatively the same as what you are doing... just relocating the add method calls to another method.
thus allowing you to "add them all in one statement"
Swing does not support the adding of components in one statement... the only way is to relocate calls to another method.

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).

Difference between creating an object within the constructor vs outside of the constructor?

Within my program, I am trying to create a toolbar within a frame. Within the toolbar, I have three buttons that are represented with a picture instead of text.
The problem is that I have found that there is a difference in how the buttons are displayed if I create the JButton objects within the constructor, compared to if I did this outside of the constructor (but still within the JFrame class).
My code when I create the buttons within the constructor :
public class Tool extends JFrame
{
public Tool()
{
JToolbar bar = new JToolBar();
JButton button1 = new JButton(img1);
JButton button2 = new JButton(img2);
JButton button3 = new JButton(img3);
bar.add(button1);
bar.add(button2);
bar.add(button3);
}
}
Then the buttons are added nicely and neatly to the toolbar.
However, if I do this:
public class Tool extends JFrame
{
JButton button1 = new JButton(img1);
JButton button2 = new JButton(img2);
JButton button3 = new JButton(img3);
public Tool()
{
JToolbar bar = new JToolBar();
bar.add(button1);
bar.add(button2);
bar.add(button3);
}
}
Then, the buttons are still added to the toolbar. BUT instead of being formatted nicely, they seem to have a border around them (similar to if you just copied an image off of google and paste it onto a powerpoint presentation, for example, and you get a square border around the image).
Why is this the case? Why does it matter where I create the JButton objects?
Thank you in advance.
Edit (complete CORRECT code):
In the code below, button1 and button2 are created within the constructor, whereas button3 is created outside of the constructor. As you can see, there is a faint white border around the button with the text "Java", compared to the two other buttons.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Tool extends JFrame
{
JButton button3 = new JButton("Java");
public Tool()
{
super("Tool");
setLookAndFeel();
setSize(370, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button1 = new JButton("Help");
JButton button2 = new JButton("SOS");
//build toolbar
JToolBar bar = new JToolBar();
bar.add(button1);
bar.add(button2);
bar.add(button3);
// build text area
JTextArea edit = new JTextArea(8, 40);
JScrollPane scroll = new JScrollPane(edit);
// create frame
BorderLayout border = new BorderLayout();
setLayout(border);
add("North", bar);
add("Center", scroll);
setVisible(true);
}
private void setLookAndFeel()
{
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
}
catch(Exception e)
{
}
}
public static void main(String[] arguments)
{
Tool loot = new Tool();
}
}
In the first case, you just have three local variables declared in the constructor.
In the second case, your Tool class has three fields. You can then refer to those fields in other methods, and they are part of the state of the object.
That's a significant difference in itself, but shouldn't affect the behaviour in itself. However, it also affects the timing of when the JButton instances are created - when they're fields, the initializer is being executed before you call setLookAndFeel and before you call setSize.
After experimenting a bit, it seems that it's the look and feel which is important here. I suggest you change your code to make setLookAndFeel a static method, and then call that from main before you create any GUI components. You'll then get a consistent experience. (I would suggest only catching UnsupportedLookAndFeelException and ReflectiveOperationException, and at least logging any exception, instead of just continuing without any trace of what's wrong, too...)

Several similar panels GUI Java

I'm creating GUI and I don't know how to resolve my problem. What I'd like to do is to create several panels from PanelClass like i did in Main.
I don't know how:
Name buttons in my Panels and gave them some functionality (Like i was trying with button b1)
Add to panel3 additional labels, and buttons.
My main class
public class Main {
JFrame f;
PanelClass panel1, panel2, panel3;
JButton b1, b2;
public Main() {
b1 = new JButton("asasa");
f = new JFrame();
f.setSize(300, 300);
f.setLayout(new GridBagLayout());
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel1 = new PanelClass(b1, b2, panel1);
panel2 = new PanelClass(b1, b2, panel2);
panel3 = new PanelClass(b1, b2, panel3);
f.add(panel1);
f.add(panel2);
f.add(panel3);
}
public static void main(String[] args) {
Main m = new Main();
}
}
My Panel class
public class PanelClass extends JPanel {
public PanelClass(JButton btn, JButton btn1, JPanel p) {
super();
p = new JPanel(new GridBagLayout());
btn = new JButton();
btn1 = new JButton();
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
p.add(btn, c);
c.gridx = 0;
c.gridy = 1;
p.add(btn1, c);
add(p);
}
}
A component can only exist in one visible container at a time (unless it is being used as a flyweight renderer). So putting the same buttons into 3 panels will not work.
The code passes a button(s) in the constructor of PanelClass which is(are) ignored. Instead 2 new button instances are created. Just assign the passed buttons to the ..I was going to say 'class level attributes' when I noted they were not. Entirely remove
btn = new JButton(); and the text passed in the button constructor will appear.
For events, see How to Write an Action Listener.
Try to read the official Swing tutorial. It explains how to add panels, labels, etc.
To edit label names you could use setText(String name) method. To add functionalities to buttons you must implement a listener in each one. Add labels like you do in other panels, I don't see the problem.
To add "events" like click and mouse hovers etc - you must implement the correct "Listener" for the Widget. Go through any good tutorial on Swing and it will tell you everything about it. Widgets on screen are regular objects as well, so they can be added to "Collections", iterated and played around with, like regular objects. Take note of THREAD complexities and warning 'Cross-Thread invocation is Injurious To Your Program'.

Categories