This site requires JavaScript, please enable it in your browser!
Greenfoot back
Kartoffelbrot
Kartoffelbrot wrote ...

2013/8/23

(Buggy) JLabels

1
2
Kartoffelbrot Kartoffelbrot

2013/8/23

#
I programmed a "World". It is made of JLabels in a JFrame. The Labels are saved in class called Field. The Fields are saved in a two dimensional array in the world (the JFrame). That way you can get every JLabel to set Text on it. Everything worked very well. I have made a class named Entity which is equal to Actor (not so far, but I think what you mean). I put one Entity in the world. The Entities have images of two dimensional character arrays, but ther is only one so far, which looks like this: ABC DEF GHI The images are a class called charImage (like GreenfootImage). The main method of the world looks like this:
public static void main(String[] args){
        World w = new World();
        w.randomizeImage();
        w.addObject(new Entity(), 10, 10);
        while(!w.STOP){
            w.run();
            help.warte(200);
        }
        System.exit(0);
    }
The run method of the world calls the run methods of all entities in the world. As you can see I've put one entity to 10/10 (the JLabels are scaled 10x10 px). The run method of Entity is this one:
public void run(){
        setLocation(getX()+1, getY());
        if(getX()>getWorld().getWidth()-2)
            getWorld().stop();
    }
So the entity moves to the right end and then the whole execution stops. I started it and everything worked. My abcdefg (scaled in a block) has moved slowly to the right and then it has ended. But then it didn't work anymore. That means, that you can't see anything. The JFrame opened, but there was only the default grey. After waiting I noticed, that the entity moves still because the programm ended after the expected time. Then I checked nearly all methods by commenting if clauses or method calls. First I thought it would be a failure in my draw method, which draws the entity into the world, but actually I hadn't changed anything since it has worked very well. After checking I came to the conclusion that the mistake is, that the JLabels don't display their text anymore. Thinking there is a bug in Java might be arrogant, but as I erased the placing of the entity in main and the run and only said to one JLabel, that it should display "H", but it didn't. Thanks to all, who have read this and thanks to all, who are able to help me. If you want I can post more of the code. It isn't much so far.
Gevater_Tod4711 Gevater_Tod4711

2013/8/24

#
Buggy JLabels sound a bit strange. Probably you draw the image on the label and overdraw it with another image or you have a reference to a wrong label (are you using multi-buffering?). But to know what exactly is wrong you should add some parts of the code. That would make it easyer to help you.
Kartoffelbrot Kartoffelbrot

2013/8/24

#
Actually I don't draw images, it's only text. But in the case I overwrite it, there should be some text I think, but it isn't. Actually I don't know what multi-buffering is, maybe I use it. This is the code of the world:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.Color;
public class World extends JFrame
{
    private Field[][] field;
    private int pxWidth, pxHeight;
    private int width, height;
    private int cellSize;
    private boolean STOP;

    private Liste entitiesInWorld;

    public World(){
        super("Welt");

        int border = 20;//value of border of the world to left and right in JFrame
        width=50;
        height=30;
        cellSize = 15;
        pxWidth = cellSize*width;
        pxHeight = cellSize*height;

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        int frameWidth = pxWidth+(2*border); 
        int frameHeight = pxHeight+(4*border);//2x border didn't worked really, dont know why
        setSize(frameWidth, frameHeight);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        setResizable(false);
        Container cp = getContentPane();
        cp.setLayout(null);
        //cp.setBackground(Color.BLACK);
        field = new Field[width][height];
//placing the JLabels in a square and saving them into field
        for(int j = 0; j < height; j++){//y
            for(int i = 0; i < width;  i++){//x
                JLabel a = new JLabel();
                a.setBounds((i*cellSize)+border,(j*cellSize)+border,cellSize,cellSize);
                cp.add(a);
                field[i][j] = new Field(a);
            }  
        }

        entitiesInWorld = new Liste();
        STOP = false;

        setVisible(true);
    }

    public void run(){//*act*-method
        for(int j = 0; j < entitiesInWorld.getLength(); j++){
            Entity e = (Entity) entitiesInWorld.get(j);
            e.run();
        }
    }

    public Liste getObjects(){
        return entitiesInWorld;
    }

    public void addObject(Entity e, int x, int y){
        entitiesInWorld.add(e);
        e.setX(x);
        e.setY(y);
        e.setWorld(this);
    }

    public void removeObject(Entity e){
        entitiesInWorld.remove(e);
        e.deDrawMe();
        e.setWorld(null);
    }

    public Field getField(int x, int y){
        if(x>=0&&y>=0&&x<width&&y<height)
            return field[x][y];
        else return null;
    }

    public void randomizeImage(){//was for fun isnt' used I think
        for(int j = 0; j < height; j++)//y
            for(int i = 0; i < width;  i++)//x
                if(field[i][j]!=null)
                    field[i][j].setText(""+(char)(10+help.random(1000)));
    }

    public void stop(){STOP = true;}

    public int getWidth(){return width;}

    public int getHeight(){return height;}

    public static void main(String[] args){
        World w = new World();
        w.addObject(new Entity(), 10, 10);
        while(!w.STOP){
            w.run();
            help.warte(200);
        }
        System.exit(0);
    }
And this is the code of entity:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.Color;
public class Entity
{
    private boolean inWorld;
    private int x, y;
    private World world;
    private charImage img;

    public Entity(){
        inWorld = false;
        world = null;
        img = new charImage(new char[][]{{'A','B','C'},{'D','E','F'},{'G','H','I'}});
    }

    //only for the world
    public void setWorld(World w){
        world=w;
        if(world==null)
            inWorld=false;
        else
            inWorld=true;
    }
    //

    public int getWidth(){return img.getWidth();}

    public int getHeight(){return img.getHeight();}

    public void run(){//*act*-method
        setLocation(getX()+1, getY());
        if(getX()>getWorld().getWidth()-2)
            getWorld().stop();
    }

    public void setLocation(int x, int y){
        deDrawMe();
        setX(x);
        setY(y);
        drawMe();
    }

    public void setX(int x){this.x = x;}

    public void setY(int y){this.y = y;}

    public int getX(){return x;}

    public int getY(){return y;}

    public World getWorld(){return world;}

    public void drawMe(){
        if(inWorld){
            int widthAdd = 0;//if the image width is even it has to be drawn one cell more to right
            int heightAdd = 0;//same for height
            if(help.istGerade(getWidth()))//istGerade==isEven
                widthAdd = 1;
            if(help.istGerade(getHeight()))
                heightAdd = 1;
            for(int y = getY()-getHeight()/2; y <= getY()+getHeight()/2+heightAdd; y++){
                for(int x = getX()-getWidth()/2; x <= getX()+getWidth()/2+widthAdd; x++){
                    Field draw = getWorld().getField(x,y);
                    if(draw!=null)
                        draw.setText(img.getImagePart(x-getX()+getWidth()/2,y-getY()+getHeight()/2)+"");
                }
            }
        }
    }

    public void deDrawMe(){//same as drawMe only sets text to ""
        if(inWorld){
            int widthAdd = 0;
            int heightAdd = 0;
            if(help.istGerade(getWidth()))
                widthAdd = 1;
            if(help.istGerade(getHeight()))
                heightAdd = 1;
            for(int y = getY()-getHeight()/2; y <= getY()+getHeight()/2+heightAdd; y++){
                for(int x = getX()-getWidth()/2; x <= getX()+getWidth()/2+widthAdd; x++){
                    Field draw = getWorld().getField(x,y);
                    if(draw!=null)
                        draw.setText("");
                }
            }
        }
    }
}
And this is Field :) :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.Color;
public class Field
{
    private JLabel me;
    
    public Field(JLabel jlabel){
        me = jlabel;
    }
    
    public void setText(String text){
        me.setText(text);
    }
}
aaand this is charImage:
public class charImage
{
    private int width;
    private int height;
    private char[][] img;
    public charImage(int width, int height){
        if(height<=0)
            throw new IllegalArgumentException("Height can't be <=0");
        if(width<=0)
            throw new IllegalArgumentException("Width can't be <=0");
        this.width = width;
        this.height = height;
        img = new char[width][height];
    }

    public charImage(char[][] image){
        height = image.length;
        if(height<=0)
            throw new IllegalArgumentException("Height can't be <=0");
        width = image[0].length;
        if(width<=0)
            throw new IllegalArgumentException("Width can't be <=0");
        img = image;
    }

    private void printImage(){//was for test
        for(int y = 0; y < height; y++){
            for(int x = 0; x < width; x++)
                System.out.print(img[y][x]+"");
            System.out.println();
        }
    }
    
    public char getImagePart(int x, int y){//starts with 0,0 -> left upper corner
        return img[y][x];
    }
    
    public int getWidth(){return width;}
    
    public int getHeight(){return height;}
}
Liste is a self written List class, but has nearly the same methods and if the fail should be there it would be really strange (I didn't changed something since it has worked in List). I think the help methods are self explaining. Thanks for every help and to all, who work themselves through this code. If you want I can post all the code, so that you can make a BlueJ file out of it, like I have it, so It would be easier to finde the mistake perhaps.
Gevater_Tod4711 Gevater_Tod4711

2013/8/24

#
I don't see the problem in this code. Can you send me the BlueJ file so I can test some things? My E-Mail address is Gevater_Tod4711@gmx.de.
Kartoffelbrot Kartoffelbrot

2013/8/24

#
No problem, Thanks for that.
Gevater_Tod4711 Gevater_Tod4711

2013/8/24

#
I think the bugg you found is not a bugg in the JLabel class but in BlueJ. I have no idea why this occours but when I start the project and add some text to the labels there just is no text. Instead there is an image of everything in the background of the frame. When you try moving your world window somewhere else (e.g. over the classes of your project) and then click on the BlueJ window and again on the world window there again is everything copied from the background. Looks very strange to me. But when I execute the programm using eclipse everything is working fine. So I haven't got any idea why the hell this problem concerning the windows occours but it seems to be a bugg in BlueJ and not in your code. Maybe you can try to use a different programm. I would advice you to use eclipse (the Juno verion with a WindowBuilder). There everything works.
Kartoffelbrot Kartoffelbrot

2013/8/24

#
Ok thank you very much.
Kartoffelbrot Kartoffelbrot

2013/8/24

#
Do you know any other editors, that have the comfort of blueJ? I don't need all these functions of eclipse and it overburdens me. (Ich schaffs nicht mal mein Projekt zu öffnen :/ .)
Gevater_Tod4711 Gevater_Tod4711

2013/8/24

#
Sorry I don't know any other java editors that have the comfort of BlueJ. But you should realy try to use eclipse because when you know some of the funktions and if you are familiar with the funktions you want to use it's realy a great programm. (Um deine Projekte zu öffnen musst du unter eclipse erst ein neues java project erstellen, dann deine classen neu erstellen (evtl. auch packages) und dann den code kopieren. In eclipse kannst du nicht einfach die .java dateien mit copy paste einfügen und das wars. Alles was du mit eclipse machen willst musst du leider auch in eclipse erstellen.)
davmac davmac

2013/8/26

#
I think the bugg you found is not a bugg in the JLabel class but in BlueJ.
Sorry to say but I doubt this. There is a pretty significant bug with the Kartoffelbrot's code which is that it uses Swing methods but not on the Swing Event Dispatch Thread. It's not following the required Swing rules for threading, see http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
Kartoffelbrot Kartoffelbrot

2013/8/26

#
Thank you. I just put it into Netbeans it didn't worked there, too. Thanks for that link, too.
Kartoffelbrot Kartoffelbrot

2013/8/27

#
I've read it and watched some german tutorials, and it was interesting, but I don't really now what's my fault here. It was my aim to create a countinuing Simulation like in greenfoot, so that doesn't goes through the main method and then you can't do amything else.
davmac davmac

2013/8/27

#
The fault is that you're doing stuff with Swing from the wrong thread. Eg:
public static void main(String[] args){  
        World w = new World();  
This code runs on the initial thread (which is not the EDT). But World is a subclass of JFrame, a Swing class. You can only use Swing classes from the EDT. There's a discussion of this right on the second page of the tutorial in the link I posted, did you read it?
Kartoffelbrot Kartoffelbrot

2013/9/6

#
I was one week in Paris, that's why I am answering such late. I've read it. Maybe I didn't understood everything, but I think, that I got the main message. I am using Swing because of the Java-Editor, which is an editor that has tools to create a GUI very simple. So it is like in my first lessons with greenfoot. I like it, but I am doing it without knowing, what I am exactly doing.
Kartoffelbrot Kartoffelbrot

2013/9/6

#
I watched some german tutorials and I think I know now what you meant. I didn't know that a run method already exists. I only named it that way. This is my code now (I cutted it):
import Das_Game.Entity;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.Color;
public class World extends JFrame implements Runnable
{
    private Thread imageThread;
    
    private Field[][] field;
    private int pxWidth, pxHeight;
    private int width, height;
    private int cellSize;

    private Liste entitiesInWorld;

    public World(){
        super("Welt");

        int border = 20;
        width=50;
        height=30;
        cellSize = 15;
        pxWidth = cellSize*width;
        pxHeight = cellSize*height;

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        int frameWidth = pxWidth+(2*border); 
        int frameHeight = pxHeight+(4*border);
        setSize(frameWidth, frameHeight);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        setResizable(false);
        Container cp = getContentPane();
        cp.setLayout(null);
        //cp.setBackground(Color.BLACK);
        //meins
        field = new Field[width][height];
        for(int j = 0; j < height; j++){//y
            for(int i = 0; i < width;  i++){//x
                JLabel a = new JLabel();
                a.setBounds((i*cellSize)+border,(j*cellSize)+border,cellSize,cellSize);
                cp.add(a);
                field[i][j] = new Field(a);
            }  
        }

        entitiesInWorld = new Liste();
        
        setVisible(true);
        
        imageThread = new Thread(this);
        imageThread.start();
    }

    public void act(){
        randomizeImage();
        System.out.println("done");
    }

public void run(){
        while(this.isVisible()){
            act();
            for(int j = 0; j < entitiesInWorld.getLength(); j++){
                Entity e = (Entity) entitiesInWorld.get(j);
                e.act();
            }
            help.warte(50);
        }
    }

public static void main(String[] args){
        EventQueue.invokeLater(new Runnable(){
            public void run(){
                new World();
            }
        })
    }
The method ranomizeImage you can find in the code I posted before. Now I get the outprints of done, but the JLabels don't show any text :( . Thanks for your help so far. I don't get everything I've written there, but I will learn more about it.
There are more replies on the next page.
1
2