I'm a complete beginner in Java programming and I'm interested to learn more about its concepts.
Recently, I've been given an exercise which instructs me to display two versions of a picture. The picture to be displayed is provided in the form of a data file of 40,000 digits that are arranged in rows (although there is no marker between rows) and it starts from the top of the picture. So the first digit represents the top left corner of the picture and the last is the bottom right.
Basically, what the exercise wants me to construct a program that plots a dot in one of two colours for each digit. If the digit is in the range 0 to 3 the output should be one colour and for digits in the range 4 to 9 the dot should be in the other colour.
I understand I have to use arrays and also loops to perform this. I'm familiar with the fillEllipse, drawEllipse, drawRectangle and fillRectangle but this exercise is nothing I've attempted before.
Any hints on how to make this work? Your help would be greatly appreciated.
As a hint, rather than a complete solution, I would suggest looking into creating a java.awt.image.BufferedImage, and then set the colors of the individual pixels using the setRGB() method. You would then display this image using drawImage() on your Graphics object.
All what you need is how to read the digits from the file and put it into two dimension array
check this tutorial for how to read a file
Then you have to draw each pixel on a fram or a Panel
check this Java basic graphics tutorial
I hope this could help!
use Scanner to read the data like :
Scanner sc = new Scanner(new File("path_to_your_digits_file"));
int[][] digits= new int [200][200];
String line;
while(sc.hasNext()){//this means there is still a line to go
line = sc.nextLine();
//split the line and fill the array . or read char by char ,
// i dont know how your file looks like, it's just some simple string manipulation here
}
int x;
BufferedImage img = new BufferedImage(200,200,BufferedImage.TYPR_INT_RGB);
for(int i=0;i<200;i++){
for(int j=0;i<200;j++){
if(digits[i][j]>0 && digits[i][j]<=3){
x=//some color code;
}else{
x=//some other color code;
} //not sure about this loop , again idk the structure of your file;
img.setRGB(i,j,x);
}
}
JLabel lbl = new JLabel();
lbl.setSize(200,200);
ImageIcon ico=new ImageIcon(img);
lbl.setIcone(ico);
lbl.setVisible(true);
JFrame frame = new Jframe();
frame.setSize(500,500);
frame.add(lbl);
frame.setVisible(true);
Related
I made me a pixel based sprite class for a simple game in java and swing, and I don't want to let some sprites go through other sprites. So I wrote two loops that are supposed to add the pixels of every other sprite to the "material" array of the level. Material should not be passable. With the level it does work. There the sprite can't pass through its material. But with other sprites it doesn't. It can go through them. And that's the bug I actually want to fix. It seems that the sprites' pixel arrays aren't appended.
Any help is greatly appreciated !
Code :
int applied_pixels=lvl.material.length;
Sprite[] others=new Sprite[] {other sprites};
/*EDIT : others[i].frameborders[others[i].frame].all is the point array of the sprites' pixels
others[i].frame is the frame of the sprite object, because they contain an array of BufferedImages. Frame is the one that should be taken*/
Level lvl=the level; //Containing a couple of point arrays of pixels of some types, for example containing the material array of pixels
int apply_pixels=0; //How many pixels are needed ?
for (int i=0; i < others.length; i++) {
if (others[i] != null) { //Isn't the sprite null
apply_pixels=apply_pixels+others[i].frameborders[others[i].frame].all.length; //How many points does it has to add ?
}
}
level=lvl.clone(); //Copy level to be able to later append points to the material array
level.material=new Point[apply_pixels];
System.arraycopy(lvl.material,0,level.material,0,lvl.material.length); //Copy old material array points
int appending_position=0;
appending_position=lvl.material.length; //Which destination position to append the points at ?
for (int i=0; i < others.length; i++) {
if (others[i] != null) { //Isn't the sprite null
System.arraycopy(others[i].frameborders[others[i].frame].all,0,level.material,appending_position,others[i].frameborders[others[i].frame].all.length); //Copy the points from the sprite to the material array
appending_position=appending_position+others[i].frameborders[others[i].frame].all.length; //Position to append at is now plus the length of appended points
}
}
I see two possible problems with your code as posted.
The first is that level.material=new Point[apply_pixels]; only allocates elements for the new pixels. It should probably read level.material=new Point[lvl.material.length + apply_pixels];. Alternatively, you can initialize apply_pixels as int apply_pixel = lvl.material.length instead of to zero.
The second problem is that you never show us how lvl replaces the original level. Presumably the code you posted is part of a method somewhere and level is an input that is passed in, but is accessed through a field by other parts of the program. Unless the modified lvl is correctly returned and replaces the original, the code here will have no effect. However, this is only speculation because OP refuses to post the relevant code.
I'm new to swing and I've been trying some new things. I'd like to create and place JLabels on a JPanel, but as many as I want, using a loop. I'm trying to make a snake game, btw.
/*Up here I set the number of parts (JLabels) I want and instantiate my ArrayList
to store them later.*/
snakeBodyParts = 3;
snakeBody = new ArrayList<>();
/*This is the part I'm struggling with. First, bodyPartIndex is going to go from 0
to my desired number of parts. On each time it's going to store an int for the X position
of the JLabel and an int for the Y position. That way I'm going to get
JLabels on a horizontal line, each time an unit farther away.*/
for (int bodyPartIndex = 0; bodyPartIndex < snakeBodyParts; bodyPartIndex++) {
snakePositionsX[bodyPartIndex] = 50 - (bodyPartIndex * UNIT_SIZE);
snakePositionsY[bodyPartIndex] = 50;
/*Then, I add a JLabel to my list, and get it back to my "bodyPart" JLabel.*/
snakeBody.add(new JLabel());
bodyPart = snakeBody.get(bodyPartIndex);
/*Here I set the location on my "bodyPart" JLabel, using the coordinates I created before,
and set its icon (it's out of the loop)*/
bodyPart.setLocation(snakePositionsX[bodyPartIndex], snakePositionsY[bodyPartIndex]);
bodyPart.setIcon(imgIconBodyPart);
/*And finally I replace the old bodyPart with the recently modified one, I then add it to my JPanel (this.add) */
snakeBody.set(bodyPartIndex, bodyPart);
this.add(bodyPart, new org.netbeans.lib.awtextra.AbsoluteConstraints(snakePositionsX[bodyPartIndex], snakePositionsY[bodyPartIndex], UNIT_SIZE, UNIT_SIZE));
}
I'm pretty sure I've done a lot of things wrong, I'm still trying to understand what I'm doing, but the end result is a blank screen, can anyone help me? I really need to know how to do this.
This question already has answers here:
Newline in JLabel
(6 answers)
Is there a "word wrap" property for JLabel?
(7 answers)
Closed 9 years ago.
This may seem like a stupid question but I'm unable to do it; I use a scanner to read a file then using a while loop I input the text into a string which I then put onto a JLabel. However, the text is displayed in one very long horizontal line, how to I make it so that all the text appear normally like paragraphs as in the original text file?
The code:
class howToPlay implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
JFrame htp = new JFrame();
htp.setSize(300, 100);
htp.setLocationRelativeTo(null);
Scanner fileStream = null;
try {
fileStream = new Scanner(new File("text/howtoplay.txt"));
} catch (FileNotFoundException e1) {
System.out.println("File not found");
e1.printStackTrace();
}
String file = "";
while(fileStream.hasNextLine())file += fileStream.nextLine();
JLabel howToPlay = new JLabel(file);
htp.add(howToPlay);
htp.setVisible(true);
}
}
This is the text in the file, which is rules of how to play a game:
The Object of the Game is to move your pieces until they are all in one connected group. Diagonals are considered to be connected. However, there are certain rules that need be followed:
-White moves first
-Each turn, the player to move moves one of his pieces, in a straight line, exactly as many squares as there are pieces of -either color
anywhere along the line of movement. (These are the Lines of Action).
-You may jump over your own pieces.
-You may not jump over your opponents pieces, but you can capture them by landing on them.
-If one player is reduced by captures to a single piece, that is a win for the captured player.
-If a move simultaneously creates a win for both the player moving and the opponent, the player moving wins. There are actually quite a few
Unusual endgames which are at least theoretically possible.
Any help is appreciated.
Maybe try out this :)
Looks weird, but work fine for me.
You can use HTML formatting: prefix .setText() with:
<html>
and you will be able to use HTML code in your JLabel. Example:
label.setText("<html>First line<br>Second line");
I have a certain text, that i want to annotate for the user. Unfortunately i don't even see where to begin. My algorithm gives as output a range on a string. What i am going for is something like this:
I would need two ways to marker the Characters ( Blue line, red line), maybe also to invert the character (Give a character a different background), or make them fat. What is especially difficult is aligning the Pictures (here designated by two black dots) with the characters. Since the characters should be in Courier New, i could know where to put the offset, but i cannot seem to do it.
Lastly i would have to apply a break after X characters and begin a new line, just like in the picture. I have not found any example how to approach this with java yet. With python i could use ImageDraw, but i am out of the water with java.
is it possible to show this in a canvas on the screen and export this as svg or pdf? I dont know any libraries that could do this. So i would be happy to receive some suggestions/examples also along this way.
The key is to deal with the FontMetrics API. The best you can do is looking at this reference doc.
Here is a sample code demonstrating this usage. It draws red and blue lines around an "Hello world" text according a range of chars.
The text is inside a JLabel, but you can adapt the paint method on any component (but you will have to call graphics.drawChars to paint the text.)
(the code is not very nice, but it demonstrates the usage of FontMetrics)
package com.example.swing;
import javax.swing.*;
import java.awt.*;
public class DemoFontMetrics {
public static void main(String[] args){
JFrame frame = new JFrame();
DecoratedLabel label = new DecoratedLabel("hello world !",new int[]{2,4}, new int[]{6,9});
JPanel textContainer = new JPanel(new FlowLayout());
textContainer.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
textContainer.add(label);
frame.getContentPane().add(textContainer);
frame.pack();
frame.setVisible(true);
}
private static class DecoratedLabel extends JLabel{
int startBlue;
int endBlue;
int startRed;
int endRed;
private DecoratedLabel(String text, int[] blueRange, int[] redRange) {
super(text);
startBlue = blueRange[0];
endBlue = blueRange[1];
startRed = redRange[0];
endRed = redRange[1];
}
#Override
public void paint(Graphics g) {
super.paint(g); //draw text
//set line with : 3
Stroke stroke = new BasicStroke(3f);
((Graphics2D)g).setStroke(stroke);
FontMetrics fm = g.getFontMetrics();
int h = fm.getHeight();
//compute blue line coordonate
fm.stringWidth(getText().substring(0,startBlue));
int x1 = fm.stringWidth(getText().substring(0, startBlue));
int x2 = fm.stringWidth(getText().substring(0, endBlue));
g.setColor(Color.BLUE);
g.drawLine(x1,0,x2,0);// draw blue line
//compute red line coordonates
int x3 = fm.stringWidth(getText().substring(0,startRed));
int x4 = fm.stringWidth(getText().substring(0, endRed));
g.setColor(Color.RED);
g.drawLine(x3,h-1,x4,h-1); // draw redline
}
}
}
If the text is displayed via JTextPane you can conveniently define a custom HighlightPainter, that draws lines above or under the text.
Then you can add highlights to the text pane programmatically by calling:
textPane.getHighlighter().addHighlight(startPos, endPos,
myLineHighlightPainter);
Images may as well easily be added to the pane, by:
textPane.setIcon(myImageIcon);
You can create svg directly for example: http://xmlgraphics.apache.org/batik/ it's an xml based vector graphics format.
EDIT: You can display svg in java, you can create pdf's with it from java. You can publish it in the web (simply as svg).
So i was wondering I'm new to java but I know my way around it but I wanted to make a 2d tile game.
Now I heard that you can do this with a 2d Array to make the map.
But how do you make the map appear on the screen, JFrame, as pictures?
So an example of the array/map here:
1111111111
1011011001
1001100011
0000100011
0000000000
2222222222
0 = blueSky.png
1 = cloud.png
2 = grass.png
Thanks!
EDIT 2
So i have now this:
import javax.swing.*;
import java.awt.*;
public class Game extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
ImageIcon sky = new ImageIcon ("/Users/pro/Desktop/sky.png");
JPanel grid = new JPanel();
grid.setLayout(new GridLayout(25, 25));
for (int i = 0; i < 25; i++) {
for (int n = 0; n < 25; n++) {
grid.add(new JLabel(sky));
}
}
JFrame frame = new JFrame("Map");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setPreferredSize(new Dimension(640, 400));
frame.add(grid);
frame.pack();
frame.setVisible(true);
}
}
this prints some tiles with the sky picture but how do i make the bottom row an other picture?
I'd consider the 2D array as the non-GUI model, that the data itself would likely be held in some data file, perhaps a text file, that there would be methods for reading the data in to be held by a 2D array of perhaps ints, perhaps custom Cell classes (again, still all non-GUI). Then the GUI would have to interpret the model and display the data in some logical way. This could perhaps be done by creating a 2D grid of JLabels held by a JPAnel that uses GridLayout, and then use ImageIcons to hold the images, and set the icon of each JLabel based on the state of the model.
Edit 1
So possible classes used include:
TileType: an enum that associates the tile concept with the numbers held by the data file
TileCell: non-GUI class, holds a TileType field, also may hold a List of items that can be found on the cell (if the game needs this). May have information about its neighbors.
TileCellGrid: non-GUI class holding a 2D grid of TileCells.
GridDataIO: utility class to read in and write out grid data to a file.
GameGrid: GUI class that would hold a GridLayout using JPanel that holds JLabels whose ImageIcons display the images you list in your OP.
Edit 2
regarding your question:
Alright how can i set the right picture for everyLabel ?
I would use an observer/observable pattern and add a listener to the model. Whenever the model changes it should thus notify the GUI or view. Then the view would request the data array, would iterate through it and would change the image icons that need changing as it loops through the array.
I suggest you use JLabels with icons and lay them out using GridLayout.
Related question / answer with sample code and screen shot:
Tiled images in swing