Inconsistent display when a Java Swing program runs - java

I am relatively new to Java(especially swing) and I am using BlueJ IDE for some basic Swing programs.
The problem is that when I run it, the output of the code shows no consistency!
Sometimes it gets displayed properly with all the components , but at other times it only displays upto the green panel but not any components inside it that I have added. The components suddenly appear if I maximize or drag the window and increase it's size in those cases.
I would say only about one in 3 or 4 times it runs correctly. What is happening and how can I prevent it?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Swing16
{
public static void main()
{
JFrame frame1 = new JFrame("TESTING");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
frame1.setSize(1000,700);
frame1.setLocation(200,100);
//frame1.setResizable(false);
frame1.setLayout(null);
JPanel pan1 = new JPanel();
pan1.setBackground(Color.green);
pan1.setBounds(0,0,900,600);
frame1.add(pan1);
pan1.setLayout(null);
JButton east = new JButton("East");
JButton west = new JButton("West");
JButton north = new JButton("North");
JButton south = new JButton("South");
Color cr1 = new Color(0,127,0);
Font ft1 =new Font("impact",Font.BOLD,25);
north.setForeground(Color.white);
north.setBackground(cr1);
south.setForeground(Color.white);
south.setBackground(cr1);
east.setForeground(Color.white);
east.setBackground(Color.blue);
east.setFont(ft1);
east.setToolTipText(" This is the EAST zone");
west.setForeground(Color.white);
west.setBackground(Color.blue);
west.setFont(ft1);
west.setToolTipText(" This is the WEST zone");
JLabel lb1 = new JLabel(" Label 1 ");
JLabel lb2 = new JLabel(" Label 2 ");
lb2.setOpaque(true);
lb2.setForeground(Color.white);
lb2.setBackground(Color.black);
lb2.setFont(ft1);
JTextField tf1 =new JTextField(" TextField1");
tf1.setForeground(Color.white);
tf1.setBackground(Color.black);
tf1.setFont(ft1);
//tf1.selectAll();
JTextField tf2 =new JTextField("TextField 2");
//tf2.getFocus();
JTextArea ta1= new JTextArea("Enter TA",5,30);
ta1.setForeground(Color.white);
ta1.setBackground(Color.black);
//ta1.setFont(ft1);
east.setBounds(400,200,80,100);
pan1.add(east);
west.setBounds(20,200,80,100);
pan1.add(west);
north.setBounds(200,10,100,80);
pan1.add(north);
south.setBounds(200,510,100,80);
pan1.add(south);
lb1.setBounds(0,0,100,50);
pan1.add(lb1);
lb2.setBounds(0,80,100,50);
pan1.add(lb2);
tf1.setBounds(10,350,80,30);
pan1.add(tf1);
tf2.setBounds(10,500,80,30);
pan1.add(tf2);
ta1.setBounds(400,10,100,180);
pan1.add(ta1);
}
}

Three things jump out...
You are not constructing your UI within the context of the Event Dispatching Thread
You are using null layouts
You are calling setVisible(true) on the frame before you've completed building your UI.
Start by making sure that you start you program within the context of the Event Dispatching Thread...
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Construct your UI here...
}
});
}
See Initial Threads for more details...
Not every system is the same. They may have different font metrics, DPI, screen resolutions, graphics pipelines, etc... all which will affect how your UI is rendered. To this end, you should be making use of appropriate layout managers.
Take a look at Laying Out Components Within a Container
And lastly, you should avoid calling setVisible on the frame until you've completed constructing you UI, on some systems, this can present a blank frame

Related

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();
}
}

Displaying a JLabel in front of another JLabel

Game(){
JFrame frame = new JFrame("Display Image");
JPanel panel = (JPanel)frame.getContentPane();
frame.setSize(1000,625);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel();
label.setIcon(new ImageIcon("C:/Users/Ragnar/Desktop/GameBoard.png"));
panel.add(label);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
So i have this constructor ,and i want to add some new JLabels with Images,but i want them to be displayed on top of first image which is the image of the first jLabel label.Can anyone guide me how to achieve this please?I tryed to add them as usually but they are displayed behind the label.
If you have a background image and you want to display the JLabel on top of the background image, you can use a JPanel to hold the background image, then add your JLabel.
Usually if you try to let 2 JLabel overlap each other it won't succeed due to the default layout manager used by the container (such as FlowLayout in JPanel or BorderLayout in JFrame).
If you really want to let them over lap, you will have to set the layout as null. But they may introduce new problems as you lose control over the appearance of your components.
Hence, in cases like this I would usually go for custom painting and draw the images you want in any particular order you are interested in.
For example: How to create a background and foreground image which overlaps?
If you are working with eclipse, and you have installed the windowbuilder plugin you can use the graphical editing view.
Within this view use the contextual menu to order the elements.
What worked for me was, when adding the components with the method add(component), adding them in order from front to back. In the following example I add a lot of components to a JFrame, and the last one to be added is the wallpaper, so it stays at the background.
import java.awt.Image;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class LogIn extends JFrame implements ActionListener{
public static JFrame operador;`enter code here`
private JLabel logo, foot, mensaje, wallpaper;
private JTextField fldUser;
private JPasswordField fldPass;
private JButton entrar;
private int ancho =400, largo= 530;
public static String user="", pass="", name;
public LogIn() {
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(ancho,largo);
setResizable(false);
setTitle("Acceso al sitema");
setLocationRelativeTo(null);
setIconImage(getIconImage());
fldUser = new JTextField();
fldUser.setHorizontalAlignment(JTextField.CENTER);
fldUser.setBounds(125,320,150,25);
fldUser.setBackground(new Color(50,50,255));
fldUser.setForeground(Color.WHITE);
fldUser.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
add(fldUser);
fldPass = new JPasswordField();
fldPass.setHorizontalAlignment(JTextField.CENTER);
fldPass.setBounds(125,360,150,25);
fldPass.setBackground(new Color(50,50,255));
fldPass.setForeground(Color.WHITE);
fldPass.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
add(fldPass);
mensaje= new JLabel();
mensaje.setBounds(0,390,ancho,15);
mensaje.setForeground(Color.RED);
mensaje.setHorizontalAlignment(SwingConstants.CENTER);
add(mensaje);
entrar =new JButton("Entrar");
entrar.setBounds(125,410,150,40);
entrar.setForeground(new Color(50,50,255));
//entrar.setBorder(new SoftBevelBorder(BevelBorder.RAISED));
entrar.addActionListener(this);
add(entrar);
logo = new JLabel();
logo.setBounds(50,0,300,300);
ImageIcon imgLogo= new ImageIcon("src/images/DS.png");
Icon iconoLogo = new ImageIcon(imgLogo.getImage().getScaledInstance(logo.getWidth(),logo.getHeight(), Image.SCALE_DEFAULT));
logo.setIcon(iconoLogo);
foot = new JLabel("Desarrollado por Gabriel Santos");
foot.setBounds((ancho-200)/2,largo-60,200,30);
//When JLabels overlap, the ones that come to the front are the first to be added to the window.
add(foot);
add(logo);
wallpaper = new JLabel();
wallpaper.setBounds(0,0,window.getWidth(),window.getHeight());
ImageIcon img = new ImageIcon("src/images/wallpaperPrincipal.jpg");
Icon icono = new ImageIcon(img.getImage().getScaledInstance(this.getWidth(),this.getHeight(), Image.SCALE_DEFAULT));
wallpaper.setIcon(icono);
add(wallpaper);
setVisible(true);
}
}

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

Visualization issue of a simple GUI in Java

I did a very simple GUI in Java but when I run the program, the GUI acts wierd!
As soon as I run the application: the GUI shows like this:
Once I simply minimize it and get it back up, it shows fine, like this:
This is the very simple code:
public class Prova2 {
public static void main(String[] args) {
JFrame frame = new JFrame("A Simple GUI");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(650, 120);
frame.setLocation(430, 100);
JPanel panel = new JPanel();
frame.add(panel);
JLabel lbl = new JLabel("Select one of the possible choices and click OK");;
lbl.setVisible(true);
panel.add(lbl);
String[] choices = { "CHOICE 1","CHOICE 2", "CHOICE 3","CHOICE 4","CHOICE 5","CHOICE 6"};
JComboBox<String> cb = new JComboBox<String>(choices);
cb.setVisible(true);
panel.add(cb);
JButton btn = new JButton("OK");
panel.add(btn);
}
}
What am I missing in order to show the GUI fine (with all its element displayed) as soon as I run the application?
It's annoying having to necessarily minimize or resize the window in order to show the GUI properly!
I tested your code and the problem is you are setting the visibility on true before you create the items inside your JFrame. So just cut the frame.setVisible(true); and paste it as the last line of the constructor.
also I see you aren't using a layout manager which is heavy recommended. Check this for information.
Use layout manager
Follow a main Swing Toolkit principle: all UI should be manipulated and started on EDT thread ( UI thread ). Here is a very good explanation http://www.pushing-pixels.org/2007/12/06/unwritten-rule-of-working-with-swings-edt.html

GUI shows elements only after dragging window

frame_ref = new Frame("Login");
mainPanel_ref = new Panel();
buttonPanel_ref = new Panel();
grid_ref = new GridLayout(4,2);
frame_ref.setSize(300,120);
frame_ref.setVisible(true);
email_ref = new TextField();
password_ref = new JPasswordField();
mainPanel_ref.setLayout(grid_ref);
mainPanel_ref.add(new Label("E-Mail"));
mainPanel_ref.add(email_ref);
mainPanel_ref.add(new Label("Passwort"));
mainPanel_ref.add(password_ref);
mainPanel_ref.add(submitLogin_ref);
mainPanel_ref.add(fehlerMeldung_ref);
frame_ref.add(mainPanel_ref);
I set up a view in Java like above. The window is complete empty, but after I drag and drop its size, all the elements appear. Does somebody know how to fix this?
Call frame_ref.setVisible(true); after frame_ref.add(mainPanel_ref);.
What happens here is: You show frame by calling frame_ref.setVisible(true); and then add elements in it. So you get an empty frame. Afterwards when you drag or resize it gets repainted and you can see elements.
Call pack() on the JFrame after the components have been added. Doing so will cause the frame to assume the smallest size it needs to display the components. Finally call (setLocation()(4) &) setVisible(true).
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class FrameTest {
public void init() {
frame_ref = new JFrame("Login");
frame_ref.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel_ref = new JPanel(new GridLayout(4,2,6,3));
mainPanel_ref.setBorder(new EmptyBorder(5,5,5,5));
email_ref = new JTextField();
password_ref = new JPasswordField();
mainPanel_ref.add(new JLabel("E-Mail"));
mainPanel_ref.add(email_ref);
mainPanel_ref.add(new JLabel("Passwort"));
mainPanel_ref.add(password_ref);
mainPanel_ref.add(new JLabel(""));
mainPanel_ref.add(new JLabel(""));
mainPanel_ref.add(submitLogin_ref);
mainPanel_ref.add(fehlerMeldung_ref);
frame_ref.add(mainPanel_ref);
//frame_ref.setSize(300,120);
frame_ref.pack();
frame_ref.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FrameTest().init();
}
});
}
private JFrame frame_ref;
private JPanel mainPanel_ref;
private JTextField email_ref;
private JPasswordField password_ref;
private JButton submitLogin_ref = new JButton("Submit Login");
private JButton fehlerMeldung_ref = new JButton("Fehler Meldung");
}
Other tips:
Don't mix Swing with AWT. At least, not the components, or not before targeting Java 7+.
A log-in component is often better suited to putting in a JDialog or JOptionPane rather than a JFrame.
This might be better suited to a nested layout, or some other layout than GridLayout
setLocation() might be swapped out for:
If the log-in has a 'parent' component, setLocationRelativeTo(Component).
If the log-in is the first screen visible, setLocationByPlatform(true) (1.6+).
Check the source closely for other tips.
For better help sooner, post an SSCCE.

Categories