I can't figure out why I'm not able to see my thouchpad that I've created, but it works. Here is the code
package com.mygdx.game;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
public class AnalogStick extends Touchpad {
private static Touchpad.TouchpadStyle touchpadStyle;
private static Skin touchpadSkin;
private static Drawable touchBackground;
private static Drawable touchKnob;
public AnalogStick(float x, float y) {
super(10, getTouchpadStyle());
setBounds(15, 15, 200, 200);
setPosition(x,y);
}
private static Touchpad.TouchpadStyle getTouchpadStyle() {
touchpadSkin = new Skin();
touchpadSkin.add("touchBackground", new Texture("touchBackground.png"));
touchpadSkin.add("touchKnob", new Texture("touchKnob.png"));
touchpadStyle = new Touchpad.TouchpadStyle();
touchBackground = touchpadSkin.getDrawable("touchBackground");
touchKnob = touchpadSkin.getDrawable("touchKnob");
touchpadStyle.background = touchBackground;
touchpadStyle.knob = touchKnob;
return new TouchpadStyle();
}
}
And in my Create class I use this code for adding it into the stage
asMove = new AnalogStick(15,15);
Gdx.input.setInputProcessor(stage);
playerTexture = new Texture(Gdx.files.internal("player.png"));
playerSprite = new Sprite(playerTexture);
stage = new Stage(new ScreenViewport(), batch);
stage.addActor(asMove);
Gdx.input.setInputProcessor(stage);
And in the render method this code
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
There seems to be a problem with your getTouchpadStyle method: it initializes touchpadStyle but instead of returning it, it returns a new and empty style object. In other words, Replace
return new TouchpadStyle();
with
return touchpadStyle;
Related
I have done all the details I have done, and I don't get an error but what I want to do doesn't work.
I tried to check on google, chatgpt, and friends. I was expected to a window with wait for input from the user, and the user writes a task and he enters "submit". Then, a window of DeadLine comes with an import calendar. So, the user chooses a DeadLine and he presses "OK". and then I created a constructor with the selected time and the task (to print the input) therefore, I called to the constructor and its doesn't call. Please help me. ):
The code:
import javax.swing.*;
import com.toedter.calendar.JCalendar;
import java.awt.*;
import java.awt.event.*;
import java.util.Calendar;
import java.util.Date;
public class List extends JFrame {
String todo = "TO DO: ";
ImageIcon icon1;
JButton button;
public static String task;
static JLabel label,label2,label3;
static JLabel titletaskLabel,titletaskLabel2,titletaskLabel3,titletaskLabel4;
static JFrame frame;
public static JTextField text;
static Font myFont = new Font("Ink Free", Font.BOLD, 30);
static Font yourFont = new Font("Ink Free", Font.HANGING_BASELINE, 20);
static JCalendar calendar;
static Date selectedDate;
List() {
frame = new JFrame("List");
icon1 = new ImageIcon("list.png");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 900);
frame.setIconImage(icon1.getImage());
frame.setLayout(null);
label = new JLabel("To Do List: ");
label.setBounds(50, 50, 200, 20);
label2 = new JLabel("Enter a task: ");
label2.setFont(myFont);
label2.setBounds(70, 460, 200, 40);
button = new JButton("Submit");
button.setBounds(470, 500, 80, 50);
button.setBackground(Color.green);
button.addActionListener(new ActionListener1());
text = new JTextField();
text.setBounds(70, 500, 370, 50);
text.setFont(myFont);
frame.add(text);
frame.add(button);
frame.add(label);
frame.add(label2);
frame.setVisible(true);
}
static void addDeadline() {
JDialog dialog = new JDialog(frame, "Choose a Due Date", true);
dialog.setSize(400, 400);
dialog.setLocationRelativeTo(frame);
JPanel calendarPanel = new JPanel();
calendarPanel.setBounds(70, 600, 370, 200);
calendar = new JCalendar();
calendarPanel.add(calendar);
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Get the selected date
Calendar selectedCalendar = calendar.getCalendar();
selectedDate = selectedCalendar.getTime();
task = text.getText();
System.out.println(selectedDate);
dialog.setVisible(false);
tasks(); // add the new task to the frame
}
});
calendarPanel.add(okButton);
dialog.add(calendarPanel);
dialog.setVisible(true);
}
static void tasks() {
titletaskLabel = new JLabel(task + "The DeadLine is: " + selectedDate);
titletaskLabel.setBounds(50, 70, 200, 50);
frame.add(titletaskLabel);
}
static class ActionListener1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
addDeadline();
}
}
}
public class Main extends List{
public static void main(String[] args) {
new List();
}
}
For some reason after adding buttons to my application it has stopped functioning on android. It works as expected on desktop, but when attempting to run on android the app builds successfully, launches, then immediately crashes before it ever loads the scene. I attempted to view the logs via aLogcat, however I see nothing in these logs indicating an issue has occurred.
I have come to the conclusion that this issue has something to do with the uiskin/buttons being added to the stage, as I can add the stage without any actors and the app will still function in android. The files outlined in the uiskin.json file are all located in /android/assets directory as they should be. Is there something I have done incorrectly? Something I have missed?
uiskin.json
{
"com.badlogic.gdx.graphics.g2d.BitmapFont":{
"default_font": {
"file": "book_antiqua.fnt"
}
},
"com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle":{
"default": {
"down": "default-round-down",
"up": "default-round",
"font": "default_font"
}
},
"com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle":{
"default": {
"titleFont": "default_font"
}
}
}
Main class
package com.freedom.thirty;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.Material;
//import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.viewport.FillViewport;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.freedom.thirty.MyCameraInputController;
public class FreedomThirty implements ApplicationListener {
public ScreenViewport vp;
public ScreenViewport stageVp;
public OrthographicCamera cam;
public MyCameraInputController camController;
public ModelBatch modelBatch;
public AssetManager assets;
public Array<ModelInstance> allModelInstances = new Array<ModelInstance>();
public Environment environment;
public boolean loading;
// Model instances that make up the map
public ModelInstance bridge;
public ModelInstance container_001;
public ModelInstance crate_001;
public ModelInstance crate_002;
public ModelInstance crate_003;
public ModelInstance crate_004;
public ModelInstance crate_005;
public ModelInstance grass_area;
public ModelInstance gravel_area;
public ModelInstance rock_wall;
public ModelInstance water;
public ModelInstance player;
public ModelInstance skybox;
public Skin skin;
public Stage stage;
public Table table;
//public FPSLogger fpsLogger = new FPSLogger();
#Override
public void create() {
modelBatch = new ModelBatch();
assets = new AssetManager();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.8f, 0.8f, 0.8f, 1f));
//environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
cam = new OrthographicCamera();
cam.position.set(-4f, 4f, 4f);
cam.lookAt(8f, 0f, -8f);
cam.near = 1f;
cam.far = 2000f;
cam.update();
// Create input controller for default scene camera. This is what allows the user to orbit around the scene
camController = new MyCameraInputController(cam);
// Set the position where the camera will look. This will need to come from json config file in the future
camController.target.set(8f, 0f, -8f);
vp = new ScreenViewport(cam);
vp.setUnitsPerPixel(0.017f);
vp.apply();
stageVp = new ScreenViewport();
stageVp.apply();
stage = new Stage(stageVp);
assets.load("uiskin.json", Skin.class);
assets.load("map_003.g3db", Model.class);
loading = true;
}
private void doneLoading(){ // Assets are now loaded into memory and can be accessed without error
// Load UI skin
skin = assets.get("uiskin.json", Skin.class);
// Define the buttons that will be in the ui table
final TextButton zoomOut = new TextButton("Zoom Out",skin,"default");
final TextButton zoomIn = new TextButton("Zoom In",skin,"default");
// Create UI table actor
table = new Table();
table.setWidth(stage.getWidth());
table.align(Align.center | Align.top);
// In the future determine what the current viewport height/width is, and set these
// to different sizes based on where the viewport falls between. Just like bootstrap's xs,sm,md,lg classes
table.setSize(250f, 250f);
table.setPosition(800f,400f);
zoomOut.setWidth(200);
zoomOut.setHeight(50);
zoomIn.setWidth(200);
zoomIn.setHeight(50);
// Event listeners for ui buttons
zoomOut.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y){
//Gdx.app.log("Zoom Out", "Press successful");
vp.setUnitsPerPixel(vp.getUnitsPerPixel() + 0.001f);
vp.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
stageVp.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
event.stop();
}
});
zoomIn.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y){
//Gdx.app.log("Zoom In", "Press successful");
vp.setUnitsPerPixel(vp.getUnitsPerPixel() - 0.001f);
vp.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
stageVp.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
event.stop();
}
});
// Add buttons to table
table.row().padBottom(30).padTop(30);
table.add(zoomOut);
table.add(zoomIn);
// Add table to stage
stage.addActor(table);
// Create an input multiplexer and add our stage and camController to it, set input processor to our new multiplexer
InputMultiplexer im = new InputMultiplexer(stage, camController);
Gdx.input.setInputProcessor(im);
// Load the 3d map, and character as character happens to be in the map file as of right now
// In the future each map and it's elements will be contained within it's own class, extended from
// map class
Model model = assets.get("map_003.g3db", Model.class);
bridge = new ModelInstance(model, "bridge");
allModelInstances.add(bridge);
container_001 = new ModelInstance(model, "container_001");
allModelInstances.add(container_001);
crate_001 = new ModelInstance(model, "crate_001");
allModelInstances.add(crate_001);
crate_002 = new ModelInstance(model, "crate_002");
allModelInstances.add(crate_002);
crate_003 = new ModelInstance(model, "crate_003");
allModelInstances.add(crate_003);
crate_004 = new ModelInstance(model, "crate_004");
allModelInstances.add(crate_004);
crate_005 = new ModelInstance(model, "crate_005");
allModelInstances.add(crate_005);
grass_area = new ModelInstance(model, "grass_area");
allModelInstances.add(grass_area);
gravel_area = new ModelInstance(model, "gravel_area");
allModelInstances.add(gravel_area);
rock_wall = new ModelInstance(model, "rock_wall");
allModelInstances.add(rock_wall);
water = new ModelInstance(model, "water");
allModelInstances.add(water);
player = new ModelInstance(model, "character");
allModelInstances.add(player);
player.transform.setTranslation(8f,0f,-6f); // Test character movement on the map
loading = false;
}
#Override
public void render() {
if(loading && assets.update()){
doneLoading();
}
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
camController.update();
//Gdx.app.log("Camera Position: ", cam.position.toString());
modelBatch.begin(cam);
modelBatch.render(allModelInstances, environment);
modelBatch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
//fpsLogger.log();
}
#Override
public void dispose() {
modelBatch.dispose();
allModelInstances.clear();
assets.dispose();
}
#Override
public void resize(int width, int height) {
vp.update(width, height);
stageVp.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
What finally corrected this issue was downloading the default uiskin files from the libgdx repository on github. Apparently I missed something when I built them from scratch? The files I used from the repo are:
uiskin.json
uiskin.atlas
default.png
uiskin.png
I think it takes to long to load the uiskin file. Try instead of skin = new Skin(Gdx.files.internal("uiskin.json")); something like that:
AssetManager manager = new AssetManager();
manager.load("uiskin.json", Skin.class);
manager.finishLoading();
skin = manager.get("uiskin.json", Skin.class);
Don't forget to dispose the AssetManager, when before you finish your game.
I've got a slight problem, I'm writing a gps tracking app to track several objects at once. The data comes in over a serial interface, this is coming in fine from what I can tell. The issue is that I need to continually update the JPanel where the map is created and displayed.
public JPanel mapDisplay(){
JPanel mapPanel = new JPanel();
mapPanel.setSize(560, 540);
Coordinate start = new Coordinate (-34.9286, 138.6);
trackMap.addMapMarker(new MapMarkerDot(1Lat, 1Lon));
trackMap.setDisplayPosition(start,8);
System.out.println(1Lat);
mapPanel.add(trackMap);
mapPanel.setVisible(true);
return mapPanel;
}
This is what I have and it's happy to display the point once but won't update. If I print out the 1Lat variable in the serial method it continually prints, however it only does it once here.
A lot of the answers I've found refer to setting markers by arrays, however that won't work in this case as the objects I'm tracking could be anywhere.
Any help would be greatly appreciated :)
Is it possible to use a worker thread and not use an ArrayList? I would run the risk of missing data if I do.
Not necessarily. In a SwingWorker, your implementation of the doInBackground() method can publish() results as they become available. Note in particular that "Results from multiple invocations of publish() are often accumulated for a single invocation of process()." In your process(), simply loop through the List<Coordinate>, update the route and repaint() the map.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import org.openstreetmap.gui.jmapviewer.Coordinate;
import org.openstreetmap.gui.jmapviewer.JMapViewer;
import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
/**
* #see http://stackoverflow.com/a/37193636/230513
*/
public class MapWorkerTest {
private final List<Coordinate> route = new ArrayList<>();
private void display() {
JFrame f = new JFrame("MapWorker");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMapViewer map = new JMapViewer() {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
#Override
public String getToolTipText(MouseEvent e) {
Coordinate c = (Coordinate) getPosition(e.getX(), e.getY());
return c.getLat() + " " + c.getLon();
}
};
map.setToolTipText("");
Coordinate start = new Coordinate(-34.9286, 138.6);
route.add(start);
MapPolygonImpl poly = new MapPolygonImpl(route);
poly.setColor(Color.blue);
map.addMapPolygon(poly);
map.setDisplayPosition(start, 10);
f.add(map);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new MapWorker(map, start).execute();
}
private class MapWorker extends SwingWorker<Void, Coordinate> {
private final JMapViewer map;
private Coordinate last;
public MapWorker(JMapViewer map, Coordinate start) {
this.map = map;
this.last = start;
}
#Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
last = new Coordinate(last.getLat() + 0.0025, last.getLon() + 0.01);
publish(last);
Thread.sleep(1000);
}
return null;
}
#Override
protected void process(List<Coordinate> chunks) {
for (Coordinate c : chunks) {
route.add(c);
}
map.repaint();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new MapWorkerTest()::display);
}
}
Multiple route management left as a exercise.
I'm making a Hangman game and it seems that my code doesn't provide me much freedom with using layouts. I added an image to my JFrame then I added a JPanel to my image which I'm using for all the JLabels and JTextFields but it seems to me that its inefficient because in order to change the layout of my JTextFields or JLabels I have to change the layout of my image which messes up the entire looks of the game. How can I make this code more efficient and give myself more freedom to change the layouts of my JLabels and JTextFields without messing everything up? Thanks for the help in advanced.
/*PACKAGE DECLARATION*/
package Game;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
/************************
* GAME MECHANICS CLASS *
* **********************/
public class GameStructure {
/* INSTANCE DECLARATIONS */
private String []wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday"};
private int []length = new int [64];
private JTextField tf;//text field instance variable (used)
private JLabel jl2;//label instance variable (used)
private JLabel jl3;//label instance (working on)
private String letter;
/*****************
* LENGTH METHOD *
* ***************/
public void length(){
jl3 = new JLabel();
int j = 0;
for(j = 0; j<64; j++) {
length[j] = wordList[j].length();//gets length of words in wordList
}//end for
int l = 0;
String line = "";
//create line first then put into .setText
for(int m = 0; m<length[l]; m++) {
line += "__ ";
l++;
}//end for
jl3.setText(line);
}//end length method
/*****************
* WINDOW METHOD *
* ***************/
public void window() {
LoadImageApp i = new LoadImageApp();//calling image class
JFrame gameFrame = new JFrame();//declaration
JPanel jp = new JPanel();
//JPanel jp2 = new JPanel();//jpanel for blanks
JLabel jl = new JLabel("Enter a Letter:");//prompt with label
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
tf = new JTextField(1);//length of text field by character
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jp.add(jl);//add label to panel
jp.add(tf);//add text field to panel
jp.add(jl2);//add letters used
gameFrame.add(i); //adds background image to window
i.add(jp); // adds panel containing label to background image panel
gameFrame.setTitle("Hangman");//title of frame window
gameFrame.setSize(850, 600);//sets size of frame
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when 'x' button pressed
gameFrame.setIconImage(new ImageIcon("Hangman-Game-grey.png").getImage());//set the frame icon to an image loaded from a file
gameFrame.setLocationRelativeTo(null);//window centered
gameFrame.setResizable(false);//user can not resize window
gameFrame.setVisible(true);//display frame
}//end window method
/*********************
* USER INPUT METHOD *
* *******************/
public void userInput() {
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//when enter key pressed
JTextField tf = (JTextField)e.getSource();
letter = tf.getText();
jl2.setText(jl2.getText() + letter + " ");//sets jlabel text to users entered letter
}//end actionPerformed method
});
}//end userInput method
}//end GameMechanics class
/*PACKAGE DECLARATION*/
package Game;
/***********************
* IMPORT DECLARATIONS *
* *********************/
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
/***************
* IMAGE CLASS *
* *************/
public class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon image;
/***********************
* PAINT IMAGE METHOD *
* *********************/
public void paintComponent (Graphics g) {
//setLayout(new BorderLayout());
super.paintComponent(g);
image = new ImageIcon("hangman.png");//image name & type
image.paintIcon(this, g, 270, 20);
}//end paintComponent method
}//end LoadImageApp class
/*PACKAGE DECLARATION*/
package Game;
/*******************
* GAME MAIN CLASS *
* *****************/
public class GameMain {
/***************
* MAIN METHOD *
* *************/
public static void main (String []args) {
GameStructure game = new GameStructure();//declaration
game.length();
game.window();
game.userInput();
}//end main method
}//end GameMain class
Some suggestions:
Don't override a JPanel's paint(...) method, but rather its paintComponent(Graphics g) method, not unless you need to change how it renders its child components or its borders (you don't). Also by doing this you gain some Swing graphics advantages including automatic double buffering.
Never read in an image into the paint or paintComponent method. These methods are one of the main determinants of how responsive your GUI appears to the user, and so you never want to do file I/O in the method. And also, why have code that inefficiently re-reads the same image in whenever paint or paintComponent is called? Why not simply store the image or ImageIcon in a variable once, and be done with it?
Learn and use the layout managers
JPanels that go over drawing or image rendering JPanels often should be non-opaque - so be sure to call setOpaque(false) on them, and also on some other overlying Swing components.
_________________________
Edit
For example, here is my SSCCE that shows an example of getting an image (here off of the internet) in a class constructor. Also note that my SSCCE will work on any computer connected to the internet since it does not require image files, unlike yours. Also code not related to displaying the GUI has been cut out making the remaining code more pertinent to the problem. Consider doing this next time you post an SSCCE.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
class GameStructure {
private JTextField tf;
private JLabel jl2;
public void window() {
LoadImageApp loadImageApp = new LoadImageApp();
JFrame gameFrame = new JFrame();
JPanel jp = new JPanel();
jp.setOpaque(false); //!!
jp.setBorder(BorderFactory.createTitledBorder("jp"));
JLabel jl = new JLabel("Enter a Letter:");
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));
tf = new JTextField(1);
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));
jp.add(jl);
jp.add(tf);
jp.add(jl2);
gameFrame.add(loadImageApp);
loadImageApp.add(jp);
gameFrame.setTitle("Hangman");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// gameFrame.setIconImage(
// new ImageIcon("Hangman-Game-grey.png").getImage());
gameFrame.setResizable(false);
gameFrame.pack();
gameFrame.setLocationRelativeTo(null);
gameFrame.setVisible(true);
}
}
class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 850;
private static final int PREF_H = 600;
private BufferedImage img;
public LoadImageApp() {
// just used as an example public image
String spec = "https://duke.kenai.com/"
+ "SunRIP/.Midsize/SunRIP.png.png";
URL url;
try {
url = new URL(spec);
img = ImageIO.read(url);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
}
public class GameMain {
public static void main(String[] args) {
GameStructure game = new GameStructure();
game.window();
}
}
I've been working on this for some time, and I'd really appreciate some help right now.
I'm trying to get the JFrame containing the text input fields to close from my actionPerformed method, but I can't seem to get anything to work. JFrame.dispose wont let me access the right Jframe, and setVisible(false) is equally useless, unless I'm doing this completely wrong.
//halp
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
class PersonInput extends JPanel
implements ActionListener {
//Fields for data entry
private JFormattedTextField firstField, lastField, dateField;
public String x[] = new String[3];
public PersonInput() {
//Values for the fields
String first = "First Name";
String last = "Last Name";
String date = "MM/DD/YYYY";
//Create the text fields and set them up.
firstField = new JFormattedTextField();
firstField.setValue(new String(first));
lastField = new JFormattedTextField();
lastField.setValue(new String(last));
dateField = new JFormattedTextField();
dateField.setValue(new String(date));
dateField.setColumns(10);
JButton ok = new JButton("OK");
ok.setVerticalTextPosition(AbstractButton.BOTTOM);
ok.setHorizontalTextPosition(AbstractButton.CENTER);
ok.setActionCommand("ok");
ok.addActionListener(this);
ok.setToolTipText("Confirms user input and continues with the program.");
JPanel buttons = new JPanel(new GridLayout(0,1));
buttons.add(ok);
//Layout the text fields in a panel.
JPanel fieldPane = new JPanel(new GridLayout(0,1));
fieldPane.add(firstField);
fieldPane.add(lastField);
fieldPane.add(dateField);
//Put the panels in this panel, labels on left,
//text fields on right.
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
add(fieldPane, BorderLayout.CENTER);
add(buttons, BorderLayout.LINE_END);
}
public void actionPerformed(ActionEvent e) {
if ("ok".equals(e.getActionCommand()))
{
JFrame frame1 = new JFrame("People Sorter");
x[0] = firstField.getText();
x[1] = lastField.getText();
x[2] = dateField.getText();
JOptionPane.showMessageDialog(frame1, "Person has been added.");
dispPerson();
frame.setVisible(false);
}
}
public void dispPerson()
{
System.out.println(x[0] + x[1] + x[2]);
}
public static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Person Input");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new PersonInput());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
I'm all ears if anyone has any ideas; I've been stressed over this all day. Thanks much for lending me your time!
EDIT: Just for clarification, the frame I'm trying to close is the one instantiated in the createAndShowGUI method.
it seems that the problem is that we are trying to merge both static and non static contents. For a short explanation static contents can be referred without need of creating an instance (object) of that class. Which means that createAndShowGUI can be called:
inside another static method (like main)
From class reference PersonInput.createAndShowGUI()
or from an object, but that method or attribute will be always the same, static attributes are shared.
I can suggest 2 ways to solve your problem.
One is pass the object frame to PersonInput
//halp
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
class PersonInput extends JPanel
implements ActionListener {
//Fields for data entry
private JFormattedTextField firstField, lastField, dateField;
public String x[] = new String[3];
JFrame frame;
public PersonInput(JFrame frame) {
this.frame = frame;
//the rest of your code
}
The other way is to have the frame object outside the method and declare it static.
static JFrame frame = new JFrame("Person Input");;
public static void createAndShowGUI() {
//Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new PersonInput());
//Display the window.
frame.pack();
frame.setVisible(true);
}
Remember that static variable cannot be referenced from a static context