This thread was started in Click Here, and I created this thread in hopes of making it easier to find.

I have been working on a program that creates several controls dynamically in a LayeredPane.The code to add all the controls to the Pane has gotten really long. Is there a way to create a seperate class that creates and adds the controls to the Pane, call it from the MyLayer method. I still have a lot of code to put in and I would like to keep the code in the main form as simple as possible. I will continue researching the issue, but any assitance is appreciated.

Recommended Answers

All 16 Replies

(This is a copy of my replies to the earlier thead - repeated here for simplicity)

That's a common problem with Swing (or any other powerful GUI toolset), and there isn't any good solution. An IDE with code folding helps when you are editing the code.
You can certainly put it all in a method in the same class, but if you use a different class then you have to worry about accessing all the variables for the different components in the GUI. If that's not too serious a problem then you can create a subclass of JPanel (or layered pane etc) that implements all the content, and in your main form just add a new one of those.

When I'm doing this for real I usually create a JPanel subclass containing all the contents, then provide a public interface in terms of the logic rather than the presentation, thus keeping all the actual JComponents private. Eg: Its a roulette application - I may have stuff like

class RouletteTable extends JPanel {
    public RouletteTable() {...
    public void showBet(int amount, Place p) {
       // enum Place is a number, colour. odd/even etc
       // may display piles of chips in the right place tec
       ...
    public int spinWheel() {
       // animated, retunrns final result

Note that this does very complicated and beautiful graphics, but it knows nothing about the processes of a game of roulette... it just displays what it's told to display.

Now I can program the logic and flow of a game, and use RouletteTable without knowing anything about its graphics...

    RouletteTable rt = new RouletteTable();
    frame.add(rt);
    ...
    playOneGame() {
       rt.showBet(100, ROUGE);
       int number = rt.spinWheel();
       if (number ... // who won, who lost?
       rt.clearBets();
       ...

By separating the responsibilities in this way I can work on the long and tedious graphics code in isolation, then I can completely forget about that while I get on with programming the game.

==

Don't be afraid to create new classes to organise your code.
Eg: You may have a game with a highly graphical display of the game in progress, plus a number of buttons that the user uses to start/play/end the game. I would think of having classes like:
GameDisplay extends JPanel - the graphical display (see previous post)
ButtonPanel - the buttons and their action listeners
GameLogic - the current state of the game and an implementation of its rules
GameMaster - has the main method, creates a GameLogic and a JFrame with a GameDisplay and a ButtonPanel.

Any time you can separate out a coherent chunk of code that has limited interaction with the rest of the program, you should consider separating and packaging it in a separate class/java file. Remmeber also that programs grow - what starts as a small class will grow to medium, and what starts as a big class will become unmanagable

MyBJTest// This is a package folder.
MyBJTestCreator.java// This is a class in the folder.
MyTableTest.java// This is another class in the folder.

MyBJTestCreator is where I want to call all the classes from. I'm trying to run the MyTableTest class from the MyBJTest Class. The MyTableTest class has the LayeredPane with all the controls and their settings. I want to load this Pane into the MyBJTestCreator or at least make the pane visible so I can click on buttons which I hope to add action listeners from another class.

It sounds like your layered pane should be a class in its own right - ie extend JLayeredPane and add all the controls to it in its constructor. Then the creator class can invoke a new instance of that and add it to the JFrame.
Don't be aftraid of having too many classes!

Will I need a class for each control or can i create my layered pane in one an add the controls in another. This thing has around 30+ controls.

Create a subclass of JLayeredPane. In the constructor for your class, add all the controls you want.

Below is my JLayeredPane class:

public class MyLayerTest extends JLayeredPane {

    public JLabel back;
    public JLayeredPane Pane;

    public JLayeredPane MyPane(){

    ImageIcon backGround = createImageIcon("/Images/Blackjack Table.jpg");

        //Create and set up the layered pane.
        Pane = new JLayeredPane();
        Pane.setPreferredSize(new Dimension(800, 600));

        //Create the JLabel for the background image and add the image.
        back = new JLabel(backGround);
        back.setBounds(0, 0, 800, 600);
        Pane.add(back, new Integer(0));

        return Pane;                

    }

    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = MyBJTestCreator.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }
}

This is my Constructor class,

public class MyBJTestCreator extends JPanel {



static Random rand = new Random();

//Creates connection
static String host = "jdbc:mysql://localhost:3306/henderson_games";
static String uName = "root";
static String uPass = "nbuser";
static Connection con; //Creates connection
static Statement stmt; //Creates object to hold our statement
static Statement Clean;
static ResultSet rs; //Creates object to hold the results of our statement

private String user;//User's user name
private String BuyIn;//User's Buyin amount

public Integer NumCards;//Number of cards to be played with
public Integer seat;//Seat user has choosen
public Integer pcard = 0;//The index of the current card to be dealt to the player
public Integer hand = 0;//The index of the current hand being played
public Integer dcard = 0;//The index of the current card to be dealt to the dealer
public Integer cardsPlayed = 0;//Tracks the numer cards that have been dealt
public Boolean played = false;//Tracks whether this is the inital start of the game
public JLabel[] cardToRemove = new JLabel[105];//Used to store all the cards dealt each round

public Integer handsPlayed = 0;//Tracks how many hands have been played for a single deck game
public Integer cardsToPlay = 0;//Tracks how many cards are left in the deck

private String userBet = ("txtBet[" + seat + "]");


public MyBJTestCreator() {

    MyLayerTest Pane = new MyLayerTest();
    add(Pane);

}

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {

    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

private static void createAndShowGUI() {

    //Create and set up the window.
    JFrame frame = new JFrame("My Layered Pane Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    JComponent ContentPane = new MyBJTestCreator() ;
    ContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(ContentPane);

// ShuffleDeck();
//Display the window.
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}

protected static ImageIcon createImageIcon(String path) {
    java.net.URL imgURL = MyBJTestCreator.class.getResource(path);
    if (imgURL != null) {
        return new ImageIcon(imgURL);
    } else {
        System.err.println("Couldn't find file: " + path);
        return null;
    }
}

where I want to load my pane and then the controls and then the action listners for the various controls and then the actions to be performed when an action is needed.
I plan to have to have all this in separate classes, but I can't get past this point.
The code runs without error but just loads a tiny screen. When I run in debug mode it opens:

public class MyLayerTest extends JLayeredPane {

then goes back to:

MyLayerTest Pane = new MyLayerTest();
        add(Pane);

Fails to run the method in MyLayerTest.

I understand the adding of the controls to the constuctor of the JLayeredPane. This my be an easier approach than my plan of adding them later, also may decide to add the listeners to the controls at creation.

Yes, add the listeners to the controls when you add the controls, in your layered pane class constructor.
But...
don't try to do too much in those listeners. Don't put the game logic here. Implement the logic in some other class, and in the listeners just get the event then call the appropriate method(s) in the game logic class. Ie keep a clean separation between logic and GUI.

I'm think you missed my post where I needed some help. 2 pos back. Having issues loading the class.

I thought you maust have fixed that by now!
Is the un-executed method the myPane() method? That's not executed because you have written no code to call it. The content of that method looks like it should be the no-args constructor, in which it would be called when you new the class instance.

ps I wouldn't advise setContentPane for this purpose. Just add your layered pane to the JFrame. Then you can add other panels with buttons or toolbars etc later.

Yes, that is the issue. I have added "Pane.MyPane();" and that executes the method but it's not returning the Pane. What am I doing wrong?

You seem to have got this all twisted up, and I don't know why. I'd just make it a constructor:

public MyLayerTest(){
  ImageIcon backGround = createImageIcon("/Images/Blackjack Table.jpg");
  setPreferredSize(new Dimension(800, 600));
  //Create the JLabel for the background image and add the image.
  back = new JLabel(backGround);
  back.setBounds(0, 0, 800, 600);
  add(back, new Integer(0));
}

then in createAndShowGUI()

JComponent lp = new MyLayerTest();
frame.add(lp);

(but first I'd rename "MyLayerTest" to something that helps the code make sense like "BlackjackTable", as in

JComponent blackjackTable = new BlackjackTable();
frame.add(blackjackTable);

I've been looking and researching for a while on this matter trying to figure it out on my own. I may have jumbled serveral things together from all the things I've been reading just trying to get this pane to load. There are no clear examples that I have found on anything yet. I will try the (Hopefuly)solution you have suggested. Thanks for your help thus far.

THIS IS CRAZYNESS!!! I finally got the Panel to load and now I can press forward with the next task. I removed the "extends JPanel" form the creator class and added the code you recomended. That seemed to fix the issue.
Also renamed everything to make sense, I think.

THANK YOU!!

Now that I have this powerful tool in my toolbox I can now move forward with a cleaner and easier to use program. I now have MULTIPLE CLASSES(All are working as expected) and making great progress in my program Thank you so much for all of your help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.