Basic GUI screen

The code below gives a background image with a single button which appears as an image. The button calls a function when clicked. To run the code you will need 3 images. Mine are called splash.png and it is 1024 x 768, and two smaller buttons; a default, and a rollover png of the same size.

The first thing to do is create an egg containing the images. I’m using XP so I use the command prompt. cd into the directory containing the images and type:

egg-texture-cards -o mainScreen.egg splash.png new.png newOver.png

This left an egg file in the folder called mainScreen.egg. Note that this egg needs to be in the same folder as the images if you want the images to appear on the geoms created.

The following code loads the egg and provides the basics for a GUI:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
import sys

class Main(DirectObject):
  def __init__(self):
    self.accept("escape", sys.exit)
    self.setupScreen()
  
  #This method is called when the button is clicked  
  def newButtonClicked(self):
    print "Do the stuff you want when the new button is clicked"
    
  #The screen is simply a background image and a single textured button
  def setupScreen(self):
    #All the textures are pulled from the premade egg-texture-card
    self.screenImages=loader.loadModel('./textures/mainScreen.egg')
    #find the splash image to act as background
    self.splash=self.screenImages.find('**/splash')
    #fiddle fiddle with the x and z values till the image fits the window.
    self.splash.setScale(3,1,2)
    #reparent the image to aspect2d
    self.splash.reparentTo(aspect2d)
     
    #The directButton accepts 4 states, normal, click, rollOver, and disabled.
    self.newButton=DirectButton(geom=(self.screenImages.find('**/new'),
                        self.screenImages.find('**/new'),
                        self.screenImages.find('**/newOver'),
                        self.screenImages.find('**/new')))
    #parent the button to the splash screen. Do it here so the fiddles are done respective to the splashscree
    self.newButton.reparentTo(self.splash)
    #Another syntax for setting a direct object's properties. This gets rid of the default bevel around the button
    self.newButton['frameVisibleScale']=(0,0)
    #fiddle fiddle to set the scale (as above)
    self.newButton.setScale(0.15,1,0.04)
    #fiddle fiddle to set the position using the x and z values. 
    #You could also position the background image the same way
    self.newButton.setPos(0.34,0,0.04)
    #Tell the Panda what method to call when the button is clicked 
    self.newButton['command']=self.newButtonClicked
    
    
    
    
                              
     


Main()
run()

Hope this helps.

it would be great if someone could convert it to c++

Here is a C++ coversion that I believe should be equivalent.

#include "pandaFramework.h"
#include "pandaSystem.h"
#include "PGButton.h"
#include "MouseButton.h"


PandaFramework framework;

static void newButtonCallback(const Event *ev, void *data)
{ 	
	nout << "Do the stuff you want when the new button is clicked";	
}

static void ExitProgram(const Event *ev, void *data)
{ 	
	nout << "request to quit";
	//framework.close_all_windows();
	framework.close_framework();	
}

int main(int argc, char ** argv)
{	
	framework.open_framework(argc, argv);	
	framework.set_window_title("Dargon 5");  	
	WindowFramework *window = framework.open_window();   
	// Check whether the window is loaded correctly  
	if (NULL == window) 
	{
		framework.close_framework();
		return 1;
	}
	
	window->enable_keyboard(); // Enable keyboard detection			
		
	framework.define_key("escape","QuitTheProgram",ExitProgram,NULL);

	// ======== This is the equivalent setupScreen method	
	NodePath screenImages = window->load_model(framework.get_models(),"./Textures/mainScreen.egg");
	NodePath splash = screenImages.find("**/splash");
	splash.set_scale(3,1,2);
	splash.reparent_to(window->get_aspect_2d());

	//DirectButton is a py object, so we have to use the underlying PG instead.		
	PointerTo<PGButton> newButton = new PGButton("NewButton");
	newButton->setup(screenImages.find("**/new"),
					 screenImages.find("**/new"),
					 screenImages.find("**/newOver"),
					 screenImages.find("**/new"));

	//Get the initial Style
	PGFrameStyle newButtonStyle = newButton->get_frame_style(0);

	//Set it to no frame
	newButtonStyle.set_type(PGFrameStyle::T_none);

	//And assign the new style to all states
	newButton->set_frame_style(0,newButtonStyle);
	newButton->set_frame_style(1,newButtonStyle);
	newButton->set_frame_style(2,newButtonStyle);
	newButton->set_frame_style(3,newButtonStyle);

	NodePath newButtonNP = window->get_aspect_2d().attach_new_node(newButton);
	newButtonNP.set_scale(0.15,1,0.04);
	newButtonNP.set_pos(0.34,0.0,0.04);
	
	//MouseButton::one() defined in "MouseButton.h"
	framework.define_key(newButton->get_click_event(MouseButton::one()),"Button Clicked",&newButtonCallback,newButton);
		
	//Run it
	framework.main_loop();
	
	
	// Close the framework
	framework.close_framework();		
	return 0;
}