Sorry about my English, and my ignorance in programming, its because I'm new at this , and I'm having problem with Buttons and JFrame, please help me ;)
I'll post the print of the problem, and the codes of my the two classes I have so far, Game and Menu, hope you guys can solve it, I want the buttons to paint inside the gray panel.
Thanks.
Print of my Problem
Print
(GAME CLASS)
package br.com.lexo.dagame;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import br.com.lexo.dagame.menu.Menu;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
private static int width = 300;
private static int height = width / 16 * 9;
private static int scale = 3;
private static String title = "Da Game";
private Thread thread;
public JFrame janela;
private Menu menu;
private boolean running = false;
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
janela = new JFrame();
menu = new Menu(janela, this);
}
private synchronized void start() {
if (running) return;
running = true;
thread = new Thread(this, "Thread_01");
thread.start();
}
private synchronized void stop() {
if (!running) return;
running = false;
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public void update() {
}
public void run() {
while (running){
render();
update();
}
stop();
}
public static void main(String[] args) {
Game game = new Game();
game.janela.add(game);
game.janela.setTitle(title);
game.janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.janela.pack();
game.janela.setLocationRelativeTo(null);
game.janela.setResizable(false);
game.janela.setVisible(true);
game.start();
}
}
(MENU CLASS)
package br.com.lexo.dagame.menu;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import br.com.lexo.dagame.Game;
public class Menu extends Canvas {
private static final long serialVersionUID = 1L;
public boolean inMenu = false;
JButton startGame = new JButton("Começar Jogo");
JButton exitGame = new JButton("Sair do Jogo");
JButton howToPlay = new JButton("Como Jogar");
private Game game;
public Menu(JFrame janela, Game game){
this.inMenu = true;
this.game = game;
game.janela.setLayout(new GridBagLayout());
game.janela.add(startGame);
game.janela.add(exitGame);
game.janela.add(howToPlay);
howToPlay.setEnabled(false);
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
}
I don't know what are you trying to accomplish but you are not adding the components correctly:
Look at:
game.janela.setLayout(new GridBagLayout());
game.janela.add(startGame);
game.janela.add(exitGame);
game.janela.add(howToPlay);
This is incorrect, the add method has two arguments, like this: container.add(component, constraints); your error is not specifying the constraints. The constraints contains all the details to know where in the panel you want to add that component.
For each LayoutManager the Object constraints is diferent. For the GridBagLayout the constraints is a GridBagConstraints object.
However GridBagLayout is a the most difficult layout to use and you don't really need it. I recommend you to look at this visual guide pick a layout and learn it properly. The tutorial for each LayoutManager explains what do you need to put in the constraints parameter.
The call container.add(component) exists because sometimes the LayoutManager does not need extra information (like the BoxLayout), in the other cases it just uses the "default" constraints for the LayoutManager in use, which may not be what you need.
For example the line in your main:
game.janela.add(game);
Is correct, but what it actually does is calling game.janela.add(game, defaultConstraints); where defaultConstraints is the default constraints value for the LayoutManager of the JFrame janela. Because you didn't explicitely specify a layout for the frame it is using the default layout for JFrames: BorderLayout, and the default constraints for the BorderLayout is the constant BorderLayout.CENTER.
So what that line actually does is:
game.janela.add(game, BorderLayout.CENTER);
Which incidentally is what you wanted to do.
To summarize:
Most calls to add must have two parameters: the component and the constraints. Each LayoutManager uses different constraints. You must be aware of what means to not specify the constraints for your LayoutManager. Do not start learning about how to properly use LayoutMangers with the GridBagLayout it's much more complex.
A quick way to somehow paint components to a graphics object is calling the paint method of component class. So in your render method:
g.fillRect(0, 0, getWidth(), getHeight());
menu.startGame.paint(g);
...
But as you'll soon see that everything is painted on the top left as components are laid out as said in the other answer and to get everything working to how you want them to work is a bit more complicated.
Now the following advice is based on my limited knowledge and was quickly put together so there are probably better ways.
About the menu class:
You are extending java.awt.Canvas when I think it would be best to extend a container like javax.swing.JPanel as you want it (I assume) to hold those 3 buttons.
Next would be to set the appropriate layout for this application, which would be null. So instead of:
game.janela.setLayout(new GridBagLayout());
it would now be:
setLayout(null);
This is because you want components (which are those buttons) to be paint on top of another component which is the Game class that extends Canvas and null allows you to do that.
Because the layout is now null, you must specify the bounds of the components which are the x and y coordinates alone with the width and the height otherwise everything will just be 0, 0, 0, 0 and nothing would show up.
So in the Game's constructor
setBounds(0, 0, width * scale, height * scale);
and janela.setPreferredSize(size); instead of setPreferredSize(size);
Back in the Menu class you will have to set the bounds of the buttons like so:
Dimensions sgSize = startGame.getPreferredSize();
startGame.setBounds(50, 50, sgSize.width, sgSize.height);
I am using preferred size to get the optimal width and height of the button that was set in the buttons UI (I think).
and add them to the Menu which is now a JPanel instead of adding them to the JFrame(janela). (add(startGame);) Also, don't forget to add the game to the menu panel.
and it should work like so:
(http://i.imgur.com/7cAopvC.png) (image)
Alternatively you could make your own widget toolkit or custom layout, but I wouldn't recommend that. I had this same problem last year but ended up moving to OpenGL but anyway, I hope this has helped :)
Related
I am learning java abstract window toolkit and i am stuck in this code.When i interchange the commented line, the output changes.Any Explanation for both the cases will be appreciated.
import java.awt.*;
public class guibutton
{
public guibutton()
{
Frame f = new Frame("Panel Example");
Panel panel = new Panel();
panel.setBounds(40,80,200,200);
panel.setBackground(Color.gray);
f.add(panel);
f.setVisible(true); ////////////////this line
f.setLayout(null); /////////////////this line
f.setResizable(true);
f.setSize(400,400);
}
public static void main(String args[])
{
new guibutton();
}
}
This line:
f.setVisible(true);
renders your GUI in its current state, one where the JFrame's default BorderLayout is in force. Note that BorderLayout ignores the setBounds(...) method.
This line:
f.setLayout(null);
removes the JFrame contentPane's BorderLayout, and so your GUI is rendered without the layout, changing the positioning of the added JPanel -- the setBounds(...) method call here is respected.
If you call this after the GUI has been rendered, it won't have an effect, unless you do something that triggers the layout managers to re-layout the components, such as re-size the GUI.
Myself, I wouldn't use AWT but would use Swing, I'd draw the rectangle within the paintComponent method of a JPanel, using a Rectangle object. This way, I could monitor the mouse in relation to the rectangle, and change its state. For instance, try out this program, and see what happens to the rectangle when the mouse hovers over it:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class GuiButton2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int RECT_X = 40;
private static final int RECT_Y = 80;
private static final int RECT_W = 200;
private static final Color DEFAULT_RECT_COLOR = Color.GRAY;
private static final Color HOVER_RECT_COLOR = Color.PINK;
private Rectangle rectangle = new Rectangle(RECT_X, RECT_Y, RECT_W, RECT_W);
private boolean hover = false;
public GuiButton2() {
setPreferredSize(new Dimension(PREF_W, PREF_H));
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
// hover true if mouse is hovering over the rectangle
hover = rectangle.contains(e.getPoint());
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// if hover true -- use hover color, otherwise use default color
Color c = hover ? HOVER_RECT_COLOR : DEFAULT_RECT_COLOR;
g2.setColor(c);
g2.fill(rectangle); // draw rectangle
}
private static void createAndShowGui() {
GuiButton2 mainPanel = new GuiButton2();
JFrame frame = new JFrame("GUI Button");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Side note 1:
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Side note 2:
You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
I'm new at working with JFrames. So I dont really know how to draw/paint/display everything in a JFrame. Im working on a memory game. Currently im working at the first form, this form must display a background image, a welcome text, a dropdown list with the amount of cards for the memory game and a button which should start the game. I succesfully displayed the background image and the welcome text. After adding the JButton and combobox my form got messed up (I only see a blue background). I have no idea what im doing wrong, also I dont know how I can place the button and dropdown on the right x and y position. I want to place the dropdown box under the welcome text and the button to the right of the dropdownbox.
This is my code:
Main:
package Memory;
public class Main {
public static Memory memory;
public static void main(String[] args) {
memory = new Memory();
}
}
Renderer:
package Memory;
import javax.swing.*;
import java.awt.*;
public class Renderer extends JPanel {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Memory.backImage = new ImageIcon("Memory/memoryGame.jpg");
Main.memory.repaint(g);
}
}
Memory:
package Memory;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.*;
import javax.imageio.*;
import java.awt.FlowLayout;
public class Memory implements ActionListener {
public String[] amountOfCards = {"8","16","32"};
private JButton startButton;
public Renderer renderer;
public static ImageIcon backImage;
public boolean screen1;
public static final int WORLD_WIDTH=1250, WORLD_HEIGHT=800;
public Memory() {
JComboBox comboBox = new JComboBox(amountOfCards);
comboBox.setSelectedIndex(1);
startButton = new JButton("Start game");
JFrame jframe = new JFrame();
Timer timer = new Timer(20,this);
renderer = new Renderer();
jframe.add(renderer);
jframe.setTitle("Memory game");
jframe.setSize(WORLD_WIDTH,WORLD_HEIGHT);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);jframe.add(startButton);
jframe.add(comboBox);
jframe.setVisible(true);
screen1=true;
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
renderer.repaint();
}
public void repaint(Graphics g) {
//welcome screen
if(screen1) {
BufferedImage scaledImage = getScaledImage();
g.drawImage(scaledImage, 0, 0, null);
g.setColor(new Color(150, 196, 100));
g.setFont(new Font("TimesRoman", Font.PLAIN, 75));
g.drawString("MEMORY GAME", WORLD_WIDTH / 2 - 275, 100);
g.setFont(new Font("TimesRoman", Font.PLAIN, 25));
g.drawString("Please select the amount of cards u want to play with and start the game!", WORLD_WIDTH / 2 -400, 200);
}
}
public BufferedImage getScaledImage() {
BufferedImage image = new BufferedImage(WORLD_WIDTH,WORLD_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) image.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(backImage.getImage(), 0, 0,WORLD_WIDTH,WORLD_HEIGHT, null);
return image;
}
}
Alright, multiple errors in a first view of your code
public static Memory memory; : That line, having static and being a public member of class will harm you a lot! Why? Because your memory variable is the same for all the instances you create, because it's a "Class variable" not an "instance variable", and being public is going against the convention and security reasons. For reference see: What does the 'static' keyword do in a class? and Why use getters and setters?
From the above point, static is not a "magic cross method / class" word that allows you to use variables through classes or with main and other methods... and thus this line public static ImageIcon backImage; and this one: Memory.backImage = new ImageIcon("Memory/memoryGame.jpg"); shouldn't exist. And the same for this one: Main.memory.repaint(g);
That being said, you should NEVER NEVER NEVER EVER!!! override repaint() method, all of that code should be into the paintComponent(...) mehtod!
Also it is wise to treat images as embedded resources, because, once you export your program as a JAR file, they will become embedded resources, it's better to treat them like if they already were, here you can find information about how to change your program accordingly.
Try and set your ImageIcon BackImage from public static, to public. Also, try and write the jframe.setVisible(true); command after timer.start()
note that setting your JFrame to visible, before completing every initialisation, might lead to unwanted behaviour of your program.
To set the position of your button on the screen, after adding your JButton to your JFrame, you can use: startButton.setLocation(x,y);
After you play a little bit with the coordinates of your window, you'll get the spot you want for your JButton. Keep in mind that (0,0) is usually the upper left corner of your JFrame.
Be careful when using static variables in your program. There seems to be no reason in setting your Memory class, your width and height variables as static.
For more information regarding this, check out this post: Why are static variables considered evil?
I've been working with JGraph for a while and it appears there is a painting issue when you set label clipping to true:
The following boiled-down example shows the problem in a living application that you can mess with:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;
/** it's an app! */
public class GraphApp extends JFrame {
private mxGraph graph;
private mxGraphComponent graphComponent;
private boolean labelsClipped = false;
/** #return the splitpane */
public JSplitPane getSplitpane() {
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
graph = new mxGraph();
graph.getModel().beginUpdate();
graph.removeCells(graph.getChildCells(graph.getDefaultParent(), true, true));
for (int i = 0; i < 10; i++)
graph.insertVertex(null, null, "very_very_long_vertex_" + i, 10 * i, 10 * i, 100, 50);
graph.getModel().endUpdate();
graph.setLabelsClipped(labelsClipped);
graphComponent = new mxGraphComponent(graph);
JTextArea area = new JTextArea("There's overpaint below this text."); //$NON-NLS-1$
splitPane.add(graphComponent, JSplitPane.LEFT);
splitPane.add(area, JSplitPane.RIGHT);
splitPane.setDividerLocation(70);
return splitPane;
}
private JButton getButton() {
JButton button = new JButton(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
labelsClipped = !labelsClipped;
graph.setLabelsClipped(labelsClipped);
GraphApp.this.repaint();
}
});
button.setText("Swap setLabelsClipped");
return button;
}
private JPanel getPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(getSplitpane(), BorderLayout.CENTER);
panel.add(getButton(), BorderLayout.SOUTH);
return panel;
}
public static void main(String[] args) {
GraphApp app = new GraphApp();
app.add(app.getPanel());
app.setPreferredSize(new Dimension(300, 100));
app.setVisible(true);
app.pack();
}
}
It's also interesting to note, that overpaint only happens within the confines of the vertex. Here are the names with clipping off:
And with clipping on:
I'm looking into the JGraphx source now to see where the problem lies. Has anyone worked around this before? Obviously setting graph.setLabelsClipped(false) works around it, but I'd rather not have my vertex labels spill out over the bounds of my vertices.
I found where the issue lies.
From com.mxgraph.view.mxGraph, if you add this little bit of painting code, you can see that the clip is incorrectly getting set to a rectangle that can be, as evidenced in my example, outside of the actual graph component.
if (clippedCanvas instanceof mxGraphics2DCanvas)
{
System.out.println("setting new clip");
Graphics g = ((mxGraphics2DCanvas) clippedCanvas).getGraphics();
clip = g.getClip();
g.setClip(newClip);
((mxGraphics2DCanvas) clippedCanvas).paintRectangle(((mxGraphics2DCanvas) clippedCanvas).getGraphics().getClipBounds(), Color.GREEN, Color.WHITE);
}
If we paint the clipping area that the label is working with, we can see where the problem lies.
Realistically, we should only be painting the intersection of the original canvas, and the new clipping rectangle. This image shows what the clipping rectangle was before being trampled by the new one:
The fix for this is a simple one:
if (clippedCanvas instanceof mxGraphics2DCanvas)
{
Graphics g = ((mxGraphics2DCanvas) clippedCanvas).getGraphics();
clip = g.getClip();
if (clip instanceof Rectangle)
{
g.setClip(newClip.intersection((Rectangle) clip));
}
else
{
g.setClip(newClip);
}
}
I'd be interested to hear if the original code did the clip setting as it did intentionally. I kind of doubt it.
My fix also defaults to their implementation in the case that someone does something wacky with their clip shapes, just as a sort of CYA. Probably not needed as clipping isn't guaranteed to work with anything other than rectangles:
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Graphics.html#setClip(java.awt.Shape)
It appears that the code lives here on github, so hopefully I can get the fix pushed there:
https://github.com/jgraph/jgraphx
If I have a JPanel object that I can't modify, is there a way I can modify the paintComponent method of it without using injection?
One approach I was thinking of was getting the JPanel's Graphics object, passing it to paintComponent(), performing operations on this Graphics object, and finally painting that in my custom JPanel. The problem with this, is I need to be able to do this every time the original JPanel's paintComponent() is called.
I don't need to replace what's in paintComponent(), I just need to add on to it.
For example:
JFrame frame = null;
for (Frame f : JFrame.getFrames()) {
if (((JFrame) f).getTitle().equals("Title")) {
JPanel panel = null;
// ... Cycle through all components and get the one that's a JPanel
// I want to use ColorConvertOp to make panel greyscale
}
}
One approach would be to use the Decorator Pattern to wrap the existing class. Your decorator can then implement paintComponent to first delegate to the original component and after that paint on top of it. For this approach you need to actually gain control over the creation of the components, or you need to replace them after the component hierarchy has been created (using getComponents() of the parent container to find the components to be altered).
I think one possibility is to use a GlassPane and position it exactly over your JPanel (maybe let it follow the panel using listeners if the panel changes its location). Then you can simply draw your stuff in the glasspane and it will be overlayed.
Of course this is not really elegant... But I don't see any possibility to change the paintComponents behaviour of an already existing instance without injection. (Proof me wrong, Java geeks of this world! :P)
I guess this would complete #Durandal's answer:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestPanels {
private static final boolean GRAY_SCALE = true;
protected void initUI() {
final JFrame frame = new JFrame(TestPanels.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel unmodifiablePanel = new JPanel(new GridBagLayout());
JLabel label = new JLabel("Some unmodifiable test label");
unmodifiablePanel.add(label);
unmodifiablePanel.setBackground(Color.GREEN);
JPanel wrappingPanel = new JPanel(new BorderLayout()) {
private ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
private BufferedImage image;
#Override
public void paint(Graphics g) {
if (!GRAY_SCALE) {
super.paint(g);
return;
}
BufferedImage bi = getImage();
if (bi != null) {
Graphics big = bi.createGraphics();
super.paint(big);
big.dispose();
bi = op.filter(bi, null);
g.drawImage(bi, 0, 0, null);
}
}
protected BufferedImage getImage() {
if (image == null) {
if (getWidth() > 0 && getHeight() > 0) {
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
}
} else if (image.getWidth() != getWidth() || image.getHeight() != image.getHeight()) {
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
}
return image;
}
};
wrappingPanel.add(unmodifiablePanel);
frame.add(wrappingPanel);
frame.setSize(200, 200);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestPanels().initUI();
}
});
}
}
You can turn the GRAY_SCALE flag to false, to see how it renders normally.
If you had the ability to modify the construction of your class, you could extend that class and then call super.paintComponent(g) in your extended class. Example:
public class NewPanel extends OldPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
// Insert additional painting here
}
}
In this case you will need a new class in order to build onto the existing class's painting.
What this does is execute everything that was done in the parent class's painting, and give you the option to do more (which seems to be what you're looking for).
EDIT
BUT... given that you don't have access to this, your options get more limited. If the panel uses a null layout manager, you could add a child jpanel who paints over the parent (a layout manager would restrict the amount of area the child could paint over though). This is a long shot.
You can also use reflection to but about the only option you've got (besides byte code injection). This seems about equally ugly as byte code injection - here's a decent overview of what you'd be looking to do: Java reflection: How do I override or generate methods at runtime?
My personal preference is to decompile the class, modify it the way you want, recompile it and insert it back into the original jar. This will probably void some warrenties, licenses and get you in other trouble... but at least it's maintainable.
Before I start know this: I am extremely new to Java and programming. How would I properly draw the "grass.jpg" to the screen?
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import java.util.Random;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Game extends Canvas {
private static int Height = 300, Width = 600; //25x50
private Random generator = new Random();
private String[][] TerrainList = new String[12][12];
public void GameSetup() {
JFrame container = new JFrame("CARSSémon");
// get hold the content of the frame and set up the resolution of the game
JPanel panel = (JPanel) container.getContentPane();
panel.setPreferredSize(new Dimension(Width,Height));
//panel.setLayout(null);
//setBounds(0,0,800,600);
//panel.add(this);
// finally make the window visible
container.pack();
container.setResizable(false);
container.setVisible(true);
container.setLocationRelativeTo(null); //Centers screen
container.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
PrepareTerrain();
PreparePlayer();
}
public void PrepareTerrain() {
for (int a=0; a<=11; a++){
for (int b=0; b<=11; b++){
TerrainList[a][b]="grass"; //Sets defult terrain of grass
}
}
int BushLocationx = generator.nextInt(12);
int BushLocationy = generator.nextInt(12);
BushCheck(BushLocationx,BushLocationy); //Checks to see if it can make bushs at the location
}
#Override
public void paint(Graphics g) {
super.paint(g);
// Draw an Image object
Image grass = new ImageIcon("grass.jpg").getImage();
Image bushes = Toolkit.getDefaultToolkit().getImage("bushes.jpg");
g.setColor(Color.BLACK);
g.drawImage(grass, 0, 0, null);
g.drawImage(grass, 0, 50, null);
g.drawImage(grass, 50, 0, null);
g.drawImage(grass, 200, 200, null);
}
public void DrawTerrain() {
for (int r=0; r<=11; r++){
for (int c=0; c<=11; c++){
}
}
}
private void BushCheck(int x, int y){
}
public void PreparePlayer() {
}
public static void main(String[] args) {
Game G =new Game();
G.GameSetup();
}
}
Now I obviously realize that this program has basically nothing implemented but I figured what's the point of starting to implement things if I could never even display any pictures?
My problem is that I can not figure out why the .jpgs aren't being displayed. Shouldn't the paint(); method be called when the JFrame and JPanel are created? The code is pretty messy, but I figured it would be best to include all of it.
In case this matters, this is eventually going to be a Pokemon like game, where the the run window is made up of many 16x16 pixel squares, that a player could move around on. Before starting any of that I wanted to experiment with outputting some images at random places. I've been reading similar questions and looking at examples, I just read a section of Java text on graphics but could only find information on loading images, not displaying through paint. If anyone could help by even pointing me in the right way, it would be greatly appreciated.
(I realize that I will most likely completely need to restart, and are going about things completely wrong but anything you could do would help.)
I just read a huge section of Java text on graphics but could only find information on loading images, not displaying through paint.
For a Pokemon style game, I don't think using JLabel for each icon/image would provide any benefit. Instead:
Create a BufferedImage of the desired size of the game area.
Get Image instances for each of the smaller icons that you might need to paint (characters, elements in the terrain etc.) & paint them to the Graphics instance of the main BufferedImage1.
To display the main 'game' image there are two good options:
Add the main image to a JLabel and add it to a JPanel, call label.repaint().
Paint the game image directly to the Graphics instance supplied to the paintComponent() method of a JComponent.
For the last part, I would recommend option 1.
1. E.G.
public void gameRenderLoop() {
Graphics2D g2 = gameImage.createGraphics();
g2.drawImage(playerImage, 22, 35, this);
...
g2.dispose();
}
Examples of dealing with BufferedImage & Graphics
Very simple example of painting an image.
More complicated example dealing with text & clips.
A slightly different tack (extending a JLabel) showing image painting with transparency.
Don't reinvent the wheel. Use a JLabel with an ImageIcon to paint your image for you. Just add it to a JPanel and you're all set.