First off I would like to say that I understand I am asking a lot so any help would be appreciated and I thank you for your time. I am extremely grateful.
Anyway I am creating a game for my A2 coursework, most commonly known as Checkers. I have completed my code and everything works as I had planned except that the CheckerBoard itself as well as the checkerpieces do not appear to be showing.
The section of were my board should be present is just a black space. Although my board does not appear to be displaying, all of the actions I perform on it such as clicking certain section produces the planned response, and although I've checked through my code I cannot work out what I've done wrong.
Anyway if anyone could possibly spot my mistake or perhaps give me some advice I would be extremely grateful. Thank you
As I of course can't upload my entire code I will do snippets of where I think the problem might lie or just important sections. Thank you
CheckerBoard content = new CheckerBoard(); // Sets the CheckerBoard values into the content to be used in the next line
application.setContentPane(content); // Container holds the values together, Content pane of the CheckerBoard
application.pack(); // Use preferred size of content to set size of application.
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
application.setLocation( (screensize.width - application.getWidth())/2,
(screensize.height - application.getHeight())/2 );
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); // Sets so that the application can be exited when the application is closed
application.setResizable(false); // This makes it so that the user can't change the application's size.
application.setVisible(true); // Sets it so that the application can actually be seen
The code above is placed within a "public static void main(String[] args)"
Then below that I have:
public CheckerBoard() {
// This is going to be a constructor, this constructor will set the layout manager for the panel to be null, it will then add components to the panel
// and it will set their bounds.
setLayout(null); // So that it will match my requirement specification, I will do the layout myself
setBackground(new Color(0,120,0)); // Dark Green Background colour.
setPreferredSize(new Dimension(350,250)); // The size of the Panel
BoardComplete checkerboardData = new BoardComplete();
add(checkerboardData); // This will create the components and add them to the content pane
add(NewGameButton);
add(ResignButton);
add(MessageDisplay);
// I will now have to produce a method to set the position and size of each component by calling its setBounds() method
checkerboardData.setBounds(20,20,164,164); // Sets the board dimensions
NewGameButton.setBounds(210, 60, 120, 30);
ResignButton.setBounds(210, 120, 120, 30);
MessageDisplay.setBounds(20, 200, 350, 30);
}
And then finally I have a another public class called BoardComplete which contains all the relevant code involving the actionlistners ect. used:
BoardComplete() {
setBackground(Color.BLACK);
addMouseListener(this);
ResignButton = new JButton("Resign");
ResignButton.addActionListener(this);
NewGameButton = new JButton("New Game");
NewGameButton.addActionListener(this);
MessageDisplay = new JLabel("",JLabel.CENTER);
MessageDisplay.setFont(new Font("Serif", Font.BOLD, 14));
MessageDisplay.setForeground(Color.green);
checkerboardData = new DataForCheckers();
MakeaNewGame();
}
I understand that this is a lot to ask but any help would be greatly appreciate and I would be extremely grateful. Thank you.
Edit due to comment: This is the code for my Paint Class:
public void PaintCheckerBoard(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// This will draw a two-pixel black border around the edges of the canvas.
g.setColor(Color.black);
g.drawRect(0,0,getSize().width-1,getSize().height-1);
g.drawRect(1,1,getSize().width-3,getSize().height-3);
// Draw the squares of the checkerboard and the checkers.
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if ( row % 2 == col % 2 )
g.setColor(Color.LIGHT_GRAY);
else
g.setColor(Color.GRAY);
g.fillRect(2 + col*20, 2 + row*20, 20, 20);
switch (checkerboardData.PieceLocation(row,col)) {
case DataForCheckers.RED:
g.setColor(Color.RED);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
break;
case DataForCheckers.BLACK:
g.setColor(Color.BLACK);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
break;
case DataForCheckers.RED_KING:
g.setColor(Color.RED);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
g.setColor(Color.WHITE);
g.drawString("K", 7 + col*20, 16 + row*20);
break;
case DataForCheckers.BLACK_KING:
g.setColor(Color.BLACK);
g.fillOval(4 + col*20, 4 + row*20, 15, 15);
g.setColor(Color.WHITE);
g.drawString("K", 7 + col*20, 16 + row*20);
break;
}
}
}
// If there is a game in progress, highlight the legal moves that the player can make.
// It can be seen that in this process, LegalMoves is never null while a game is in progress
if (CheckerMatchInProgress) {
/* First, draw a 2-pixel cyan border around the pieces that can be moved. */
g.setColor(Color.cyan);
for (int i = 0; i < LegalMoves.length; i++) {
g.drawRect(2 + LegalMoves[i].fromCol*20, 2 + LegalMoves[i].fromRow*20, 19, 19);
g.drawRect(3 + LegalMoves[i].fromCol*20, 3 + LegalMoves[i].fromRow*20, 17, 17);
}
// If a piece is selected to be moved, for example if ChosenRow>=0, then
// draw a 2-pixel white border around that piece, and draw a green border
// around each square that the piece can be legally moved to.
if (ChosenRow >= 0) {
g.setColor(Color.white);
g.drawRect(2 + ChosenColumn*20, 2 + ChosenRow*20, 19, 19);
g.drawRect(3 + ChosenColumn*20, 3 + ChosenRow*20, 17, 17);
g.setColor(Color.green);
for (int i = 0; i < LegalMoves.length; i++) {
if (LegalMoves[i].fromCol == ChosenColumn && LegalMoves[i].fromRow == ChosenRow) {
g.drawRect(2 + LegalMoves[i].toCol*20, 2 + LegalMoves[i].toRow*20, 19, 19);
g.drawRect(3 + LegalMoves[i].toCol*20, 3 + LegalMoves[i].toRow*20, 17, 17);
}
}
}
}
} // end PaintCheckerBoard()
So looking through your code on the other site, your custom paint method never seems to be getting called from anywhere. You're supposed to override the paintComponent method from the Component class (JPanel is a subclass of Component). This paintComponent method will be called whenever swing thinks, or is told to redraw something.
So, add this code to your BoardComplete class:
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
PaintCheckerBoard(g);
}
super.paintComponent will do anything swing would do to paint this component (which at this point is just drawing the background). And then you pass the Graphics object to your own custom paint method, that method will draw your entire game on the Graphics object, and swing will display whatever is drawn on there for you.
So now you have to remember also to call repaint() every time something in your game changes. The repaint() method will just tell swing he should repaint something (note: this tells the awt thread it should repaint the component, so it happens asynchronously from where youre calling repaint()).
If youre still confused, you should probably look up some information or tutorials on how to draw with awt/swing using this method.
Related
So I'm working on a somewhat interactive painting of a chess game. Basically, for now, there are only 2 buttons: next move and previous move. The next move button adds 1 to the int variable moveNum, and the previous move button subtracts 1 from the int variable moveNum. Basically like this:
int moveNum = 0;
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("Next Move"))
{
moveNum++;
Display.instance.repaint();
}
else if(e.getActionCommand().equals("Previous Move"))
{
moveNum--;
Display.instance.repaint();
}
}
I then just have a ton of graphics, one for each value of moveNum. It looks somewhat like this:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLACK);
if (moveNum == 0)
{
g2d.fill(new Rectangle2D.Double(0, 0, 10, 10));//just for simplicity
}
else if (moveNum == 1)
{
g2d.fill(new Rectangle2D.Double(0, 0, 10, 10));
g2d.fill(new Rectangle2D.Double(0, 0, 20, 10)); //again for simplicity
}
else if (moveNum ==2)
{
g2d.fill(new Rectangle2D.Double(0, 0, 10, 10));
g2d.fill(new Rectangle2D.Double(0, 0, 20, 10));
g2d.fill(new Rectangle2D.Double(0, 0, 30, 10)); //simplicity
}
...
}
But the graphics are not changing when I press the buttons. What could I be missing?
Update: I have tried to call Display.instance.repaint() after the moveNum stuff, but now I get no graphics at all. What could be the problem?
Update #2: The paint component is being executed because when I put System.out.println("Test"); to the method, it is being printed. I also now see the infinite recursion problem (not sure how I did not see it before). But even after fixing it, I still don't get the graphics I want. I realized that I can get some graphics when I go full-screen for some reason. But the buttons still don't change the graphics. Using the System.out.println("Test"); method, I found that "Test" is printed once when I run the program, two more times when I go full screen and get graphics, and 12 more times when I press the next button. I'm not really sure what's going on there, are my buttons set up incorrectly?
Final update: I do not have a MRE/SSCE, but I have figured out my problem. I have realized I'm one of the biggest idiots in the universe and my problem was capitalization. My buttons were not working because I capitalized the wrong thing in both of them in the segment e.getActionCommand().equals("Next Move")). Anyways, thanks a ton for your help. I don't think I would have found the infinite recursion problem, so special thanks for helping with that.
Try adding component.repaint() after moveNum++; and after moveNum--;.
When component is the component that you want to update.
Also, remove the repaint() inside paintComponent(Graphics g)
I am programming a platformer game in Java. Everything works fine and there are no bigger problems, except the flickering on the screen when the Canvas is updated.
I'll roughly explain how my game "engine" works:
In my main method, I have a Loop, that is repeating itself 30 times a second:
while (play) {
Date delay_time = new Date();
delay_time.setTime(delay_time.getTime() + (int) (1000*(1.0/FPS)));
// Here is all the game stuff, like the motion of the player,
// function calling, etc.
Graphics g = can.getGraphics();
can.update(g);
while(new Date().before(delay_time)) {
}
}
My FPS variable is a static final int that is currently set to 30.
So i am updating my Canvas 30 time a second.
Play is a boolean, which controls if the game is still playing, or the player died.
Can is an instance of my class MyCanvas.java.
The Code of the paint() method looks like so:
if (Main.play) {
//NOW
//Draw the now Level Caption
//SIZE: 240
g2.setFont(new Font("Bank Gothic", Font.PLAIN, 240));
g2.setColor(new Color(Math.abs(bg.getRed() - 30), Math.abs(bg.getGreen() - 30), Math.abs(bg.getBlue() - 30)));
g2.drawString("LEVEL " + Main.lvl, 80, 80 + 300 - Main.groundY);
//Draw the ground
g2.setColor(haba);
g2.fillRect(0, Main.screenSize.height - Main.groundY, Main.screenSize.width, Main.groundY);
//Draw the level
g2.setColor(haba);
for (int i = 0; i < Main.LVLWIDTH; i++) {
for (int j = 0; j < Main.LVLHEIGHT; j++) {
if (Main.level[i][j] == '1') {
g2.fillRect(i*(Main.BLOCK_X), (j - Main.LVLHEIGHT)*(Main.BLOCK_Y) + Main.screenSize.height - Main.groundY, Main.BLOCK_X, Main.BLOCK_Y);
}
}
//More drawing stuff...
}
So, as you can see, I am updating quite a lot - 30 times a second. This leads to the problem that my game (which is playing in fullscreen mode BTW) flickers all the time. How do solve that problem? Is a Bufferstrategy the right way? And if yes, how should I do it? Can you please explain the Bufferstartegy or provide links that have great tutorials or explanations, which or not to technical and non-beginner friendly? That would be great.
The BufferStrategy class solved my problem. Here is a good link to it, with a well made example of how to use it:
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferStrategy.html
This question already has answers here:
drawing on Jframe
(4 answers)
Closed 8 years ago.
I'm trying to create a little graphical game that has both a text and graphical version. For both versions I used a render() method which draws everything to the board (in this case, would draw it to the JFrame). However, I'm having trouble trying to add the method to the JFrame. I was wondering how to do this and if I can't what else I could do.
// Rows
for (int x = 0; x < this.cells.length; x++) {
// Columns
for (int y = 0; y < this.cells[x].length; y++) {
if (this.cells[x][y].type == Cell.EMPTY) {
g.setColor(Color.black);
g.drawOval(x, y, 10, 10);
} else if (this.cells[x][y].type == Cell.MONSTER) {
g.setColor(Color.red);
Polygon poly = new Polygon();
poly.addPoint(x, y);
poly.addPoint(x - 10, y - 10);
poly.addPoint(x + 10, y + 10);
g.drawPolygon(poly);
}
This is the render method which searches through the array of cells and based on the type of object at its x and y, will draw the according shape. Though, i'm relatively new to the programming world, i'd appreciate all the help I can get!
Don't draw to the frame. Instead, draw to a JPanel.
To do custom painting, #Override the paintComponent(Graphics) method.
be sure to first call super.paintComponent(g); before rendering.
Also #Override the preferred size of the panel to return a dimension that will show the entire drawing.
Implement a Swing Timer for repeating tasks (e.g. to animate)
In the listener, adjust positions or other factors related to rendering, then call repaint();.
Brief description of Program
Hi guys. I got bored this morning and decided to write a graphing program. Eventually i'll be able to run things like Dijksta's Algorithm on this software.
When anything changes on screen, a call to the repaint method of the JPanel where everything is painted to is made. This is the JPanel paint method:
public void paint(Graphics g)
{
for(Node node : graph.getNodes()){
node.paint(g);
}
for(Link link : graph.getLinks()){
link.paint(g);
}
}
It simply cycles through each element in the lists, and paints them.
The paint method for the node class is:
public void paint(Graphics g)
{
g.setColor(color);
g.drawOval(location.x, location.y, 50, 50);
g.setColor(Color.BLACK);
g.drawString(name, location.x + 20, location.y + 20);
}
And for the link it is:
public void paint(Graphics g)
{
Point p1 = node1.getLocation();
Point p2 = node2.getLocation();
// Grab the two nodes from the link.
g.drawLine(p1.x + 20, p1.y + 20, p2.x + 20, p2.y + 20);
// Draw the line between them.
int midPointX = ((p1.x + p2.x) / 2) + (100 / (p2.x - p1.x));
int midPointY = ((p1.y + p2.y) / 2) + 30;
// Compute the mid point of the line and get it closer to the line.
g.setColor(Color.BLACK);
g.drawString(String.valueOf(weight), midPointX, midPointY);
}
The Problem
The issue I am having arises when I use the JOptionPane class. When I select the option to add a new node, and select where to place it, an inputDialog pops up, asking for the node's name.
The nodes are added fine, for this behaviour occurs:
Is this a common problem; an issue with paint or repaint perhaps?
Nonetheless, here is the code that calls the inputDialog:
Function addNode = functionFac.getInstance(state);
String name = "";
while(!name.matches("[A-Za-z]+")) {
name = JOptionPane.showInputDialog("Please enter the name of the node.", null);
}
addNode.execute(stage, new NodeMessage(arg0.getPoint(), name));
PS: Function is an interface type that I have written.
"Swing programs should override paintComponent() instead of overriding paint()."—Painting in AWT and Swing: The Paint Methods.
"If you do not honor the opaque property you will likely see visual artifacts."—JComponent
See also this Q&A that examines a related issue.
I've created a custom swing component. I can see it (the grid from the paint method is drawn), but the buttons that are added (verified by println) aren't shown. What am I doing wrong?
Background information: I'm trying to build a tree of visible objects like the Flash/AS3 display list.
public class MapPanel extends JComponent { // or extends JPanel, same effect
private static final long serialVersionUID = 4844990579260312742L;
public MapPanel(ShapeMap map) {
setBackground(Color.LIGHT_GRAY);
setPreferredSize(new Dimension(1000,1000));
setLayout(null);
for (Layer l : map.getLayers()) {
// LayerView layerView = new LayerView(l);
// add(layerView);
System.out.println(l);
JButton test = new JButton(l.getName());
add(test);
validate();
}
}
#Override
protected void paintComponent(Graphics g) {
// necessary?
super.paintComponent(g);
// background
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
// grid
g.setColor(Color.GRAY);
for (double x = 0; x < getWidth(); x += 10) {
g.drawLine((int)x, 0, (int)x, getHeight());
}
for (double y = 0; y < getHeight(); y += 10) {
g.drawLine(0, (int)y, getWidth(), (int)y);
}
}
}
Setting null as the layout manager and then adding buttons will not have any effect. A layout manager is responsible for computing the bounds of the children components, and setting layout manager to null effectively leaves all your buttons with bounds = (0,0,0,0).
Try calling test.setBounds(10, 10, 50, 20) as a quick test to see if the buttons appear. If they do, they will be shown at exactly the same spot. From there you can either install a custom layout manager that gives each button the required bounds, or use one of the core / third party layout managers.
It would be easier for us to diagnose your problem if you gave us a SSCCE. As it stands, we may not have enough information to fix your problem.
I can see it (the grid from the paint
method is drawn),
I don't know what that means, there is no paint() method in the posted code. (But I suppose it is easy enough to assume that you meant paintComponent(g))
However, it looks like the problem is that you are uisng a "null layout". The children will not paint unless you manually set the size and location of the children.
You should probably read a quick tutorial on LayoutManagers. It may make things easier for you when drawing components.