Why is it not showing my label? - java

I am new to swing, can anyone help me out with this...
It is not showing my "label" , instead it shows me only components which are in the "panel" class.
One more question, can anyone clarify me about LayoutManagers ?
Can 2 or more LayoutManagers be used in a frame ? like for the frame i will be using FlowLayout and i have a JPanel added to the frame for which i will be using BoxLayout ... is it possible in the first place ??
import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
public class JForm1 extends JFrame
{
public JForm1()
{
init();
}
public static void main(String[] args)
{
JForm1 form = new JForm1();
}
public void init()
{
JFrame frame = new JFrame("My Form 1");
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BoxLayout(this,BoxLayout.PAGE_AXIS));
JLabel label = new JLabel("Enter your Name : ");
panel MyPanel = new panel();
frame.getContentPane().add(label);
frame.getContentPane().add(MyPanel);
frame.setVisible(true);
}
}
class panel extends JPanel implements ActionListener
{
JButton submitButton;
JTextField text;
panel()
{
this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
}
public void paintComponent(Graphics g)
{
text = new JTextField("Enter Name here");
text.setSize(100,25);
submitButton = new JButton("Submit");
submitButton.setSize(50,90);
submitButton.setBounds(200, 0, 80, 80);
submitButton.addActionListener(this);
this.add(text);
this.add(submitButton);
}
public void actionPerformed(ActionEvent event)
{
if(event.getSource()==submitButton)
{
System.out.println("The Entered Name is : "+text.getText());
}
}
}

What is this ?:
public void paintComponent(Graphics g)
{
text = new JTextField("Enter Name here");
text.setSize(100,25);
submitButton = new JButton("Submit");
submitButton.setSize(50,90);
submitButton.setBounds(200, 0, 80, 80);
submitButton.addActionListener(this);
this.add(text);
this.add(submitButton);
}
This code has nothing to do in paintComponent. paintComponent is about "painting a component", ie, paint a rectangle, draw a line, fill an oval, etc... This is absolutely not the place where to add your components. Instead, call that code in your constructor.
Additionally, if you are using LayoutManager's (which you should), calling setSize/setBounds/setLocation is useless (dimply remove those calls).
A few more things:
If you override paintComponent, make sure to invoke the super-method
Don't extends JFrame if not needed (here it is clearly not needed)
Follow Java naming conventions (class names should start with an UpperCase letter, variables and methods with a lowerCase letter)
All Swing-related code must be called on the EDT. Start your UI within a SwingUtilities.invokeLater() block.

Try by changing layout to FlowLayout for mypanel.
mypanel.setLayout(new FlowLayout());

Related

Why doesn't the image paint over my JPanel?

I have been struggling with this for some time. At first, I only used ActionListener, then I added the paintComponent, but I have no idea what to put there. I read some tutorials and used their code as an example, but it still doesn't work. Right now, the end result is the same as it was without PaintComponent.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Scream extends JPanel {
private JButton button = new JButton("OK");
private Color screenColor;
private JPanel panel = new JPanel();
private JFrame frame;
private Dimension screenSize;
private ImageIcon image;
private JLabel label = new JLabel(image);
private int x;
private int y;
private boolean mouseClicked;
public Scream() {
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e ) {
if (e.getSource() == button) {
mouseClicked = true;
frame.getContentPane().add(label);
frame.setSize(image.getIconWidth(), image.getIconHeight());
panel.repaint();
}
}
});
frame = new JFrame ("Existential angst");
screenColor = new Color(150, 100, 0);
panel.setBackground( screenColor );
frame.add(button, BorderLayout.PAGE_END);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1300, 700);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
image.paintComponent(this, g, 1300, 700);
}
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Scream scream = new Scream();
}
});
}
}
If you are trying to dynamically add an image to a panel then you need to add the label to the panel. There is no need for any custom painting.
The basic code for adding components to a visible GUI is:
panel.add(...);
panel.revalidate();
panel.repaint();
Also, don't attempt to set the size of the frame to the size of the image. A frame contains a titlebar and borders. Instead you can use frame.pack();
I noticed a couple of issues:
image is never initialized to anything so it is null, effectively making the label empty. I assume maybe your example was just incomplete?
Once I initialized the image to something, your example still did not work. Turns out adding label without specifying any constraint basically does nothing (I assume since adding a component to a border layout without a constraint puts it in the center where panel already is). When I added the label to BorderLayout.NORTH, everything worked (though resizing the frame to the size of the image makes it only partially visible since the frame includes the OK button)

Weird Swing Glitch?

I don't understand this, I'm currently making a main menu for a game i'm making but for some reason when I hover over a JButton, it flashes up on the top left side of the JFrame. I don't have any mouseAction methods or anything, is it the gif i'm using? I'm not sure...
Here is a screengrab of the error
Here is my code :
import javax.swing.*;
import java.awt.*;
public class MainMenu {
JFrame frame = new JFrame("Frasergatchi");
public void display(){
frame.setSize(400,400);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
}
public void addComponents(){
JButton play = new JButton("Play");
JButton instructions = new JButton("Instructions");
JButton exit = new JButton("Exit");
JPanel panel = new JPanel();
paintMenu paintMenu = new paintMenu();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.add(panel);
play.setAlignmentX(Component.CENTER_ALIGNMENT);
instructions.setAlignmentX(Component.CENTER_ALIGNMENT);
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(paintMenu);
panel.add(play);
panel.add(instructions);
panel.add(exit);
}
public class paintMenu extends JPanel{
public void paintComponent(Graphics graphics){
Image dog = new ImageIcon(getClass().getResource("DogMenuImage.gif")).getImage();
graphics.drawImage(dog,170,240,this);
}
}
}
The first statement in the paintComponent() method should always be:
super.paintComponent(g);
to make sure the background gets cleared.
Also:
Don't do I/O in a painting method. Painting methods are for painting only. Read the image in the constructor of your class and same the image in an instance variable.
Class names SHOULD start with an upper case character. Think of all the classes in the JDK and follow the standards.
There is no need to create a custom class to paint the image. Just use a JLabel with an Icon.

Adding JPanel to another JPanel in a different class

I'm trying to add a JPanel to another JPanel from another class. The program does not longer throw an error and all methods have been run, but the new panel just has a black screen. A basic version of the program looks as follows:
package ninjadragon;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class NinjaDragon extends JFrame implements ActionListener{
public JPanel panelMain;
public JPanel panelTurnBase;
public static void main(String[] args) {
NinjaDragon();
}
public static void NinjaDragon() {
NinjaDragon frame;
frame = new NinjaDragon();
frame.CreateMenuScreen();
JFrame.setDefaultLookAndFeelDecorated(true);
frame.setSize(750, 750);
frame.show();
frame.setResizable(false);
frame.pack();
}
private void CreateMenuScreen() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container window = getContentPane();
panelMain =new JPanel();
panelMain.setPreferredSize(new Dimension(750,750));
panelMain.setBackground(Color.BLACK);
panelMain.setLayout (new FlowLayout());
window.add(panelMain);
PanelTop();
PanelButtons();
PanelIcon();
}
#Override
public void actionPerformed(ActionEvent event) {
Object eventSource = event.getSource();
if (eventSource == buttonStart) {
panelMain.removeAll();
TurnBase TB = new TurnBase();
TB.CreateTurnBase();
}
}
The other class looks something like this:
public void CreateTurnBase() {
panelMain=new JPanel();
panelTurnBase =new JPanel();
setLayout(new FlowLayout());
setPreferredSize(new Dimension(750,750));
setBackground(Color.BLUE);
panelTurnBase.setLayout (new FlowLayout());
panelMain.add(panelTurnBase);
System.out.println("1");
PanelTurnBaseTop();
PanelGameScreen();
PanelTurnBaseBottom();
repaint();
revalidate();
buttonAttack = new JButton("Attack");
buttonAttack.addActionListener(this);
panelTurnBase.add(buttonAttack);
System.out.println("2");
}
The reason the panel has "just a black screen" is because you dont add anything to it, and you tell it to have a black screen.
i.e
panel.setBackground(Color.BLACK);
You never actually do anything to that first panel inside of any of those methods, which I can assume based on your representation of your second "class" (it's a method). Hence why it stays black.
You say:
panelMain=new JPanel();
panelTurnBase =new JPanel();
You're creating new JPanels every time and just call them panelMain and they just sit inside of that method, never leaving. You either need to return a JPanel or give it a JPanel as an argument.
The program is doing exactly what you tell it to do.
Also, do not compare Objects like this:
eventSource == buttonStart
You should use:
eventSource.equals(buttonStart);

Java JApplet with/without validate()

I have this piece of code and read that validate can refer to laying out a container's subcomponents. "Layout-related changes, such as setting the bounds of a component, or adding a component to the container, invalidate the container automatically." (source: javadoc).
However, I see no difference whatsoever between keeping validate() or removing it from this little piece of code.
Can you show me a convincing example where you can see distinct behaviour in two cases (with or without validate) to prove a point? Any other comments/advice appreciated.
public class Sw1
extends JApplet
{
JLabel lbl;
public void init()
{
lbl = new JLabel ("a label");
JPanel pan = (JPanel) getContentPane ();
pan.add(lbl);
validate();
}
}
Here is the program after I intended the push of a button to add a label. It renders an exception when I push the button:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class Sw_test
extends JApplet
implements ActionListener
{
JLabel lbl;
JButton bt ;
JPanel pan ;
JLabel l;
public void init()
{
lbl = new JLabel ("label 1");
bt = new JButton ("go ahead, press me");
bt.addActionListener(this);
JPanel pan = (JPanel) getContentPane ();
pan.setLayout(new FlowLayout());
pan.add(lbl);
pan.add(bt);
validate();
}
public void actionPerformed(ActionEvent ev)
{
l = new JLabel("new label");
pan.add(l);
}
}
You would need to call it if you add a component to a panel after it has been initialized and made visible.
Try adding a button to your applet, and on the click of the button, add a new label to the applet.
i will quote the API:
The validate method is used to cause a container to lay out its subcomponents again. It should be invoked when this container's subcomponents are modified (added to or removed from the container, or layout-related information changed) after the container has been displayed.
so as you see, it is important if you modify your layout, AFTER it has been initialized.
That is the reason why you donĀ“t see any difference
btw: here is your example :
public class TestFrame extends JFrame{
private JButton b = new JButton();
public TestFrame() {
this.setLayout(new GridLayout(5,5));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
TestFrame.this.add(new JLabel("whatever"));
//try it with and without
//validate();
}
});
this.setSize(300, 300);
this.setVisible(true);
}
public static void main(String[] args) {
new TestFrame();
}
}

Java inheritance or GUI gone wrong

despite some tips, I'm still getting this one wrong. I end up with one basic window and another one with extra features, but without the basic ones from the previous window. Instead, I would like one new window combining the basic and new features. Here is the code I've got: (also which approach would you advise?)
package windows;
import java.awt.*;
import javax.swing.*;
public abstract class WindowTemplate extends JFrame {
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
public WindowTemplate () {
JFrame myFrame = new JFrame("My first window");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myFrame.setSize(550, 450);
myFrame.setLocationRelativeTo(null);
// JLabel emptyLabel = new JLabel("");
// emptyLabel.setPreferredSize(new Dimension(550, 450));
// myFrame.getContentPane().setLayout(new CardLayout());
// myFrame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
// myFrame.pack();
}
}
now the one that is meant to be "extended":
package windows;
import java.awt.*;
import javax.swing.*;
public class a_Welcome extends WindowTemplate {
public a_Welcome() {
JPanel area = new JPanel();
JLabel text = new JLabel("One line another line and another line"); // , JLabel.CENTER);
// text.setBounds(80, 400, 400, 50);
add(area);
// area.setLayout(null);
area.add(text, new CardLayout());
// area.add(text); // , BorderLayout.CENTER);
Font font = new Font("SansSerif", Font.BOLD, 30);
text.setFont(font);
text.setForeground(Color.green);
area.setBackground(Color.darkGray);
area.setSize(550, 450);
}
}
// timer-after 5 seconds-go to the next window (countdown in the bottom right corner)
and the main:
package windows;
public class Launcher {
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
// WindowTemplate.createWindow();
// a_Welcome.createWindow();
a_Welcome window = new a_Welcome();
window.setVisible(true);
}
});
}
}
-- Alternatively --
public class WindowTemplate extends JFrame {
// Constructor
public WindowTemplate() {
init();
}
public void init() {
// add basic components
JFrame myFrame = new JFrame("My first window");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myFrame.setSize(550, 450);
myFrame.setLocationRelativeTo(null);
}
}
and
public class a_Welcome extends WindowTemplate {
public a_Welcome() {
super();
}
#Override
public void init() {
super.init(); // important so you get the base stuff
// add other components
JPanel area = new JPanel();
JLabel text = new JLabel("One line another line and another line");
add(area);
area.add(text, new CardLayout());
Font font = new Font("SansSerif", Font.BOLD, 30);
text.setFont(font);
text.setForeground(Color.green);
area.setBackground(Color.darkGray);
area.setSize(550, 450);
}
}
Sorry for lots of code and thanks for your help!
I'm not quite sure what your problem is, but your WindowTemplate basically is a JFrame, so you don't want to create a new JFrame in your constructor but rather "apply" those method to this instead of myFrame.
Try something like this:
public WindowTemplate()
{
super("My first window");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // "this" is optional
setVisible(true);
setSize(550, 450);
setLocationRelativeTo(null);
}
and
public a_Welcome()
{
super(); // this is implicit, because a_Welcome extends WindowTemplate, which has got a constructor without parameters
//[add more stuff here]
}
When you're creating a new a_Welcome, its constructor will call the super constructor, which is WindowTemplate which will in turn call the JFrame constructor
First, although you extend JFrame, you create a new JFrame and use it in each constructor. It should be looking like that:
public WindowTemplate () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setPreferredSize(new Dimension(550, 450));
this.pack();
this.setVisible(true);
Now, if you do it like that, you can add JComponents in each constructor / init method. Instead, you create two separate JFrames, one in each constructor.
I would recommend to avoid too deep hierarchy in case of swing components, since you will face many unexpected layout issues, what works for one, doesn't work for the other, when more components are added.
I think in your second example, in WindowTemplate, you're creating another JFrame when you think you're initializing the this JFrame.
Instead of
JFrame myFrame = new JFrame("My first window");
you probably want
super("My first window");
and then replace any myFrame references thereafter with this
If I read your code correctly, WindowTemplate is a JFrame. And within WindowTemplate's constructor you instantiate another JFrame? This does not make much sense. Instead of creating and configuring myFrame, you should configure this
public WindowTemplate () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
...
}
as you are doing it in the subclass, where you are calling this.add(area)

Categories