pi_squared
pi_squared

Reputation: 101

Why is JFrame not adding a component properly

I'm having an error when trying to add a component to a JFrame.

This is the first class:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class FrameG extends JFrame
{

private static final String MOVE_UP = "move up";
public static int frameID = 1;
private static JFrame window = new JFrame();
private static openWin frame = new frame01();
public static void main(String[] args) {
    window.setSize(1500,900);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);
    window.setResizable(true);
    frame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), MOVE_UP);
    frame.getActionMap().put(MOVE_UP, new movement());
    mainloop();
}
private static void mainloop()
{
    window.removeAll();
    switch(frameID)
    {
        case 1:
            frame = new frame01();
            frame.setLayout(new FlowLayout());
            System.out.println(frame);
            window.add(frame);
            break;
        default:
            break;
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(FrameG.class.getName()).log(Level.SEVERE, null, ex);
    }
    mainloop();
}
}
class movement extends AbstractAction
{
@Override
public void actionPerformed(ActionEvent e) {
    System.out.println("hi");
}
}

and the second class (it extends a class with an abstract paint method that extends JComponent):

import java.awt.Graphics;
import java.awt.*;
import javax.swing.JComponent;
import java.awt.geom.*;
public class frame01 extends openWin{
@Override
public void paint(Graphics g) {
    Graphics2D pic = (Graphics2D) g;
    pic.setBackground(Color.BLACK);
}
}

The error may be the invalid part, but i'm not sure what it is:

frameg.frame01[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=]

Upvotes: 0

Views: 363

Answers (3)

user5073753
user5073753

Reputation:

Never use a Thread and it's start and stops as a timer. Use javax.swing.Timer instead. Also you've created a recursive function to implement an infinite loop which is very wired and prone to fail. Swing has it's own thread and when you mix it up with another threads unconsciously it transform your code to a monster we are all afraid of.

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347204

You code shows a distinct lack of understanding into how Swing works

This...

private static void mainloop()
{
    window.removeAll();
    switch(frameID)
    {
        case 1:
            frame = new frame01();
            frame.setLayout(new FlowLayout());
            System.out.println(frame);
            window.add(frame);
            break;
        default:
            break;
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(FrameG.class.getName()).log(Level.SEVERE, null, ex);
    }
    mainloop();
}

Is a bad idea of two reasons, the first been that it will eventually generate a StackOverflowException, the second been that it violates the single thread rules of Swing.

Normally, a while-loop would generally be better, but as you're dealing with Swing based components you should consider using either a Swing Timer or SwingWorker, depending on what you are hoping to achieve.

Constantly adding and remove components also seems like a weird idea, but there's no context to the question to know what it is you're hoping to achieve. Having said that, as a general rule, if you want to switch between views a CardLayout is generally considered the preferred solution

This...

public class frame01 extends openWin{
    @Override
    public void paint(Graphics g) {
        Graphics2D pic = (Graphics2D) g;
        pic.setBackground(Color.BLACK);
    }
}

is simply doing nothing, other then breaking the paint chain, which could cause no end of weird paint artefacts to be generated. All you code does if temporarily changes the background color of the Graphics context, but since you don't paint anything with it, it's effectively meaningless

As a general rule, it's recommended to override the paintComponent method of Swing components (and call super.paintComponent before you do any custom painting).

I would highly recommend that you take a look at:

Upvotes: 3

Dima Maligin
Dima Maligin

Reputation: 1482

Your code has lots of problems. The line private static openWin frame = new frame01(); seems fishy as I said in my comment. But its not the worst part:

THIS:

private static void mainloop()
{
    window.removeAll();
    switch(frameID)
    {
        case 1:
            frame = new frame01();
            frame.setLayout(new FlowLayout());
            System.out.println(frame);
            window.add(frame);
            break;
        default:
            break;
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(FrameG.class.getName()).log(Level.SEVERE, null, ex);
    }
    mainloop();
}

Is BAD! And it probably breaks since you are constantly creating a new frame01() and adding it to your window.

Also DO NOT override paint but paintComponent. Another thing I dont get is why override it in a separate class and not in openWin itself.

Another thing, DO NOT SLEEP THE MAIN THREAD, if you really must then run your own and put IT to sleep.

What is the purpose of this code? I'm trying to understand it so I can help you redesign it.

PS: not really an answer, just a bit longer than a comment.

Upvotes: 2

Related Questions