I'm currently working on a Sudoku Project and I'm very close to completion but I'm having an issue with a part of my code (Sorry the variable names are in French) where the line and column index of a 2D array have been exchanged somehow and I can't seem to find where this comes from. Here is the Array declaration:
int[][]sdkGrid = {
{5,3,0,0,7,0,0,0,0},
{6,0,0,1,9,5,0,0,0},
{0,9,8,0,0,0,0,6,0},
{8,0,0,0,6,0,0,0,3},
{4,0,0,8,0,3,0,0,1},
{7,0,0,0,2,0,0,0,6},
{0,6,0,0,0,0,2,8,0},
{0,0,0,4,1,9,0,0,5},
{0,0,0,0,8,0,0,7,9}};
And here is the code where the two index are being swapped somehow:
The problem is I have no idea where the two index are being swapped.
public class FenetreGrille extends JFrame implements ActionListener{
public final int [][] NOMBRES_DEBUT;
public int [][] GRILLE_MODIF = new int[9][9];
public int [][] GRILLE_FINALE = new int[9][9];
public final int TAILLE = 9; //Mettre maj sur taille etc car ce sont des constantes
public final int TAILLECASE;
public final int COTEGRILLE ;
public Grille1 Sdk;
public JPanel Container1;
public JPanel Container2;
public JPanel containermain;
public JTextField [][] cases= new JTextField [9][9];
public JLabel FOND_ECRAN;
public JButton test = new JButton("test");
public FenetreGrille(int [][] NOMBRES_DEBUT){
this.TAILLECASE = 60;
this.NOMBRES_DEBUT = NOMBRES_DEBUT;
this.GRILLE_MODIF = NOMBRES_DEBUT;
Sdk = new Grille1(NOMBRES_DEBUT);
COTEGRILLE = TAILLE * TAILLECASE;
//this.setUndecorated(true); //Remove Title Bar AND EXIT BUTTON SO ADD ONE!!!!!
this.setAlwaysOnTop(true); //This is always on top
this.setResizable(false);
Toolkit tk = Toolkit.getDefaultToolkit();
int xsize = (int) tk.getScreenSize().getWidth();
int ysize = (int) tk.getScreenSize().getHeight();
this.setSize(xsize, ysize);
Container1 = new JPanel(); //Initialisation de la grille de Sudoku
Container1.setLayout(null);
Container1.setBounds((this.getWidth()/2)-(9*TAILLECASE/2),(this.getHeight()/2)-(9*TAILLECASE/2),COTEGRILLE,COTEGRILLE);
Container1.setBackground(Color.white);
for(int li = 0; li<TAILLE; li++){ // remplissage de la grille
for (int col = 0; col<TAILLE; col++){
cases[li][col] = new JTextField(Integer.toString(NOMBRES_DEBUT[li][col]));
cases[li][col].setBounds(li*TAILLECASE,col*TAILLECASE,TAILLECASE,TAILLECASE);
cases[li][col].setHorizontalAlignment(JTextField.CENTER);
cases[li][col].getDocument().addDocumentListener(new Ecouteur());
cases[li][col].getDocument().putProperty ("owner", cases[li][col]);
Container1.add(cases[li][col]);
if( li == 2 || li == 5){
if(col == 2 || col == 5){
Border border = BorderFactory.createMatteBorder(1,1,4,4,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}else{
Border border = BorderFactory.createMatteBorder(1,1,1,4,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}
}else if (col == 2 || col == 5){
Border border = BorderFactory.createMatteBorder(1,1,4,1,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}else{
Border border = BorderFactory.createMatteBorder(1,1,1,1,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}
if(NOMBRES_DEBUT[li][col] == 0){
cases[li][col].setText("");
cases[li][col].setBackground(new Color(204,204,204));
}else{
cases[li][col].setEditable( false);
}
}
}
int xButton = 200;
int yButton = (int) ((xButton*3)/4);
ImageIcon woodTemp = new ImageIcon("C:\\Users\\Maxime\\Documents\\Perso\\Post-Bac\\INSA\\Projet Info\\unfinished-bamboo-flooring-ufc214.jpg");
Image newImg = woodTemp.getImage();
ImageIcon woodButton = new ImageIcon(newImg.getScaledInstance(xButton, yButton, Image.SCALE_SMOOTH));
/*
test.setIcon(woodButton);
test.setBorder(null);
test.setMaximumSize(new Dimension(xButton, yButton));
test.setOpaque(false);
test.setContentAreaFilled(false);
test.setBorderPainted(false);
*/
test.setBounds((xsize/4)-100, (ysize/4)-75, xButton, yButton);
test.addActionListener(this);
containermain = new JPanel();
containermain.setBounds(0,0, xsize, ysize);
containermain.setOpaque(false);
containermain.setLayout(null);
FOND_ECRAN = new JLabel ();
FOND_ECRAN.setBounds(0, 0, 1920, 1080);
containermain.add(FOND_ECRAN);
containermain.add(test);
int x = FOND_ECRAN.getWidth();
ImageIcon temp = new ImageIcon("C:\\Users\\Maxime\\Documents\\Perso\\Post-Bac\\INSA\\Projet Info\\nature-1520704451453-7117.jpg");
Image img = temp.getImage();
Image dimg = img.getScaledInstance(FOND_ECRAN.getWidth(), FOND_ECRAN.getHeight(), Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(dimg);
FOND_ECRAN.setIcon(imageIcon);
setContentPane(containermain);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
JMenuItem item = new JMenuItem("Exit");
item.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.add(item);
this.setJMenuBar(menuBar);
containermain.add(Container1);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class Ecouteur implements DocumentListener{
public void changedUpdate(DocumentEvent e){
action(e);
}
public void insertUpdate(DocumentEvent e) {
action(e);
}
public void removeUpdate(DocumentEvent e){
//action(e);
}
public void action (DocumentEvent e){
for(int i = 0; i<TAILLE; i++){
for (int j = 0; j<TAILLE; j++){
if(e.getDocument().getProperty("owner") == cases[i][j]){
String s = cases[i][j].getText(); //Enlever tous les i,j, n et leur donner un nom
int n = Integer.parseInt(s); // Remplace la string s en un nombre
if(n < 1 || n > 9){
JOptionPane.showMessageDialog(containermain, " entrez un nombre entre 1 et 9");
}else{
cases[i][j].setBackground(Color.white);
GRILLE_MODIF[i][j] = n;
affichage(GRILLE_MODIF);
}
}
}
}
//Verification if the grid is complete
}
}
public void append ( String s){}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b) {
this.dispose();
}else if(e.getSource() == test) {
SudokuBackTrack sbt = new SudokuBackTrack(NOMBRES_DEBUT);
GRILLE_FINALE = sbt.grille;
for(int i = 0; i < TAILLE; i++) {
for(int j = 0; j < TAILLE; j++) {
cases[i][j].setText(Integer.toString(GRILLE_FINALE[i][j]));
}
}
}
}
public void affichage(int[][] t) {
for (int i=0; i<9; i++){
for (int j=0; j<9; j++){
System.out.print(t[i][j]+" ");
}
System.out.println();
}
System.out.println();
}
}
I think your offending line is:
cases[li][col].setBounds(li*TAILLECASE,col*TAILLECASE,TAILLECASE,TAILLECASE);
To fix, change it to:
cases[li][col].setBounds(col*TAILLECASE,li*TAILLECASE,TAILLECASE,TAILLECASE);
setBounds parameters are setBounds(x, y, width, height).
li (the vertical line index) should correspond to y, and col should correspond to the x coordinate.
One coding practice I use when managing arrays like this in GUIs is to explicitly name my iteration variables x and y, so that I do not get confused.
Related
I'm making a chess program for a school project using swing. this is my first time using swing however I've had a lot of experience with tkinter in python which feels similar. I've gotten the pieces loaded onto board and can load in FEN strings.
The basic board when loaded in
Now I've been trying to move on to allowing the player to capture other pieces. currently I'm not worried about the rules of how pieces can move and I'm just trying to allow them to capture anything.
A little bit of extra knowledge that may be useful is that I have two 2d arrays for the board. one contains a 2d array of 64 buttons (one for each square). the other contains a 2d int array and contains the numerical value of each piece in each square.
the following code is my code for attempting to capture pieces. My thinking behind this implementation is to first find when we select a piece that we want to move. when we click on this piece we store it in selected and set isSelecting equal to true. then the next piece we click on we should capture. The way I've been trying to tackle this is by finding the square we want to capture and changing the piece icon to the icon of the piece we stored in selected. then setting the selected pieces icon to a empty icon. then doing the same for the int array.
public boolean isSelecting;
public JButton selected;
public int[] findSpot(JButton but){
for (int i = 0 ; i < board.length; i++)
for (int j = 0 ; j < board.length; j++)
{
if ( board[i][j] == but)
{
return new int[]{i,j};
}
}
return new int[]{-1,-1};
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(1);
System.out.println(isSelecting);
if (!isSelecting) {
System.out.println(2);
selected = (JButton) e.getSource();
System.out.println(e.getSource());
} else {
System.out.println(3);
int[] temp = findSpot(selected);
ImageIcon i = new ImageIcon(pieceFiles.get(intBoard[temp[0]][temp[1]]));
Image img = i.getImage() ;
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
i = new ImageIcon( newimg );
((JButton) e.getSource()).setIcon(i);
int[]temp2 = findSpot(((JButton) e.getSource()));
intBoard[temp[0]][temp[1]] = intBoard[temp2[0]][temp2[1]];
selected.setIcon(new ImageIcon());
intBoard[temp[0]][temp[1]] = none;
selected = null;
}
isSelecting = !isSelecting;
}
This code, however, isn't working and I can't figure out why. The specific problem is the isSelecting variable on becomes false when you click the same piece twice. Clicking two separate pieces does nothing however clicking the same piece twice removes said piece.
The output after clicking the first three pawns
The output after clicking those three pawns for a second time
I'm going to leave my full code here. I'm not sure if I should since it's long but I hope it can give you a better scope of the project.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Hashtable;
import javax.swing.*;
public class Chess implements MouseListener {
static int none = 0;
static int king = 1;
static int pawn = 2;
static int knight = 3;
static int bishop = 4;
static int rook = 5;
static int queen = 6;
static int black = 8;
static int white = 16;
public boolean isSelecting;
public JButton selected;
static JButton[][] board = new JButton[8][8];
static int[][] intBoard = new int[8][8];
static JFrame frame = new JFrame("Big Willy's Chess");
static Hashtable<Integer, String> pieceFiles = new Hashtable<>();
public static void cTable() {
String folder = "C:\\Users\\bookr\\IdeaProjects\\CSA\\src\\pieces";
pieceFiles.put(king + black, folder + "\\Chess_kdt60.png");
pieceFiles.put(king + white, folder + "\\Chess_klt60.png");
pieceFiles.put(pawn + black, folder + "\\Chess_pdt60.png");
pieceFiles.put(pawn + white, folder + "\\Chess_plt60.png");
pieceFiles.put(knight + black, folder + "\\Chess_ndt60.png");
pieceFiles.put(knight + white, folder + "\\Chess_nlt60.png");
pieceFiles.put(bishop + black, folder + "\\Chess_bdt60.png");
pieceFiles.put(bishop + white, folder + "\\Chess_blt60.png");
pieceFiles.put(rook + black, folder + "\\Chess_rdt60.png");
pieceFiles.put(rook + white, folder + "\\Chess_rlt60.png");
pieceFiles.put(queen + black, folder + "\\Chess_qdt60.png");
pieceFiles.put(queen + white, folder + "\\Chess_qlt60.png");
}
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e) {
return false;
}
}
public static void loadFenPos(String fen){
Hashtable<String, Integer> pieceNumbs = new Hashtable<>();
pieceNumbs.put("k", king);
pieceNumbs.put("p", pawn);
pieceNumbs.put("n", knight);
pieceNumbs.put("b", bishop);
pieceNumbs.put("r", rook);
pieceNumbs.put("q", queen);
int rank = 0;
int file = 0;
for (String symbol:fen.split("")) {
if (symbol.equals("/")) {
file = 0;
rank++;
}
else {
if (!isNumeric(symbol)) {
int pieceColor = Character.isUpperCase(symbol.charAt(0)) ? white : black;
int pieceType = pieceNumbs.get(symbol.toLowerCase());
ImageIcon i = new ImageIcon(pieceFiles.get(pieceType+pieceColor));
Image img = i.getImage();
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH);
i = new ImageIcon(newimg);
intBoard[rank][file] = pieceType+pieceColor;
board[rank][file].setIcon(i);
file++;
} else {
file += Integer.parseInt(symbol);
}
}
}
}
public void start (){
cTable();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(8, 8));
Color lightSquareColor = new Color(240, 240, 240);
Color darkSquareColor = new Color(128, 128, 128);
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
JButton button = new JButton();
button.setOpaque(true);
button.setBorderPainted(false);
button.setFocusPainted(false);
if ((row + col) % 2 == 0) {
button.setBackground(lightSquareColor);
} else {
button.setBackground(darkSquareColor);
}
button.addMouseListener(new Chess());
panel.add(button);
board[row][col] = button;
}
}
// ImageIcon i = new ImageIcon("C:\\Users\\bookr\\IdeaProjects\\CSA\\src\\pawn.png");
//
//
// Image img = i.getImage() ;
// Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
// i = new ImageIcon( newimg );
// board[6][7].setIcon(i);
loadFenPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(600, 600);
frame.setVisible(true);
}
public static void main(String[] args) {
Chess game = new Chess();
game.start();
}
public int[] findSpot(JButton but) {
for (int i = 0 ; i < board.length; i++)
for(int j = 0 ; j < board.length; j++)
{
if ( board[i][j] == but)
{
return new int[]{i,j};
}
}
return new int[]{-1,-1};
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(1);
System.out.println(isSelecting);
if (!isSelecting) {
System.out.println(2);
selected = (JButton) e.getSource();
} else {
System.out.println(3);
int[] temp = findSpot(selected);
ImageIcon i = new ImageIcon(pieceFiles.get(intBoard[temp[0]][temp[1]]));
Image img = i.getImage() ;
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
i = new ImageIcon( newimg );
((JButton) e.getSource()).setIcon(i);
int[]temp2 = findSpot(((JButton) e.getSource()));
intBoard[temp[0]][temp[1]] = intBoard[temp2[0]][temp2[1]];
selected.setIcon(new ImageIcon());
intBoard[temp[0]][temp[1]] = none;
selected = null;
}
isSelecting = !isSelecting;
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
I've tried messing changing around the isSelecting variable, how I assign the selected variable, and how I update the 2d arrays.
I am adding JLabel objects to a JPanel. Each label has a different tool tip text that I use to identify each label afterwards, the problem is that the tool tip is always showing on hover and I need it to always be hidden.
Each label has a different image icon that's why I can't use the label text.
I can't find any documentation on the label API for some function like .hidetooltip.
Edit
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
To hide the tool tip text to null
myComponent.setToolTipText(null);
This is described in the API for this method: "param - the string to display; if the text is null, the tool tip is turned off for this component"
EDIT: In response to your actual issue that you describe in one of your comments, there are a variety of ways association information with a JLabel. You could a) extend the class and keep instance variables defining the grid values b) use a Map key'd with the JLabel and value'd with the row/col c) use the Name of the JLabel
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
One way to achieve this is to store a BufferedImage[][] to check images against. E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
public final class ImageArray {
int r = 8;
int c = 8;
// The images in the chess board, used to check which
// image was chosen for this place on the board.
final private BufferedImage[][] chessBoardImages = new BufferedImage[r][c];
private final int rowSprite = 2;
private final int colSprite = 6;
// Holds the tile sheet images
private final BufferedImage[] chessPieceImages =
new BufferedImage[colSprite * rowSprite];
private JComponent ui = null;
private final BufferedImage chessSpriteSheet;
ImageArray(BufferedImage chessSpriteSheet) {
this.chessSpriteSheet = chessSpriteSheet;
initUI();
}
private int getImageIndex(Image img) {
for (int i = 0; i < chessPieceImages.length; i++) {
if (chessPieceImages[i].equals(img)) {
return i;
}
}
return -1;
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
int w = chessSpriteSheet.getWidth();
int h = chessSpriteSheet.getHeight() / rowSprite;
int wStep = chessSpriteSheet.getWidth() / colSprite;
int hStep = chessSpriteSheet.getHeight() / rowSprite;
for (int x = 0; x < colSprite; x++) {
for (int y = 0; y < rowSprite; y++) {
chessPieceImages[x + (y * colSprite)]
= chessSpriteSheet.getSubimage(
x * wStep, y * hStep, wStep, h);
}
}
JPanel grid = new JPanel(new GridLayout(r, c));
ui.add(grid, BorderLayout.CENTER);
Random rand = new Random();
for (int x = 0; x < r; x++) {
boolean oddRow = x % 2 == 0;
for (int y = 0; y < c; y++) {
boolean oddCol = y % 2 == 0;
BufferedImage img = chessPieceImages[
rand.nextInt(colSprite * rowSprite)];
JLabel l = new JLabel(new ImageIcon(img));
chessBoardImages[x][y] = img;
l.setOpaque(true);
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
l.setBackground(Color.WHITE);
} else {
l.setBackground(Color.LIGHT_GRAY);
}
grid.add(l);
}
}
JLabel htmlLabel = new JLabel(getHtml());
htmlLabel.setHorizontalTextPosition(SwingConstants.CENTER);
htmlLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
ui.add(htmlLabel,
BorderLayout.LINE_END);
}
private String getHtml() {
String style = "<style type='text/css'>"
+ "body {"
+ "font-size: 36px;"
+ "}"
+ ".white {"
+ "background-color: #FFFFFF;"
+ "}"
+ ".black {"
+ "background-color: #BBBBBB;"
+ "}"
+ "</style>";
String pre = "<html><head>%1s</head><body><table border=1 cellspacing=0>";
StringBuilder sb = new StringBuilder(String.format(pre, style));
for (int y = 0; y < r; y++) {
sb.append("<tr>");
for (int x = 0; x < c; x++) {
Image img = chessBoardImages[y][x];
final int index = getImageIndex(img);
// hack to convert index to unicode codepoint..
int unicodeOffset = ((index/colSprite)*colSprite)==0 ? colSprite : -colSprite;
int unicodeIndexOffset;
switch (index) {
case 3:
unicodeIndexOffset = 4;
break;
case 4:
unicodeIndexOffset = 3;
break;
case 9:
unicodeIndexOffset = 10;
break;
case 10:
unicodeIndexOffset = 9;
break;
default:
unicodeIndexOffset = index;
}
int unicode = 9812 + unicodeIndexOffset + unicodeOffset;
// end: hack to convert index to unicode index..
String cssClass;
boolean oddCol = x%2==1;
boolean oddRow = y%2==1;
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
cssClass = "white";
} else {
cssClass = "black";
}
sb.append(String.format(
"<td class='%1s'>&#%2s;</td>", cssClass, unicode));
}
sb.append("</tr>");
}
sb.append("</table></body></html>");
return sb.toString();
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) throws Exception {
String urlString = "http://i.stack.imgur.com/memI0.png";
final BufferedImage img = ImageIO.read(new URL(urlString));
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ImageArray o = new ImageArray(img);
JFrame f = new JFrame("Image Array");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
You should consider storing the information elsewhere. One way would be to make a class deriving from JLabel with the purpose of storing the line and column information. Then use instances of this subclass rather than use JLabel instances. They will render as a regular JLabel would, but you can retrieve the line and column information in a way that does not pop up that information in a tooltip.
I couldn't find any other solutions to my problem because I'm unsure of how to describe it in few enough words.
When I assign activeList, which is a field of currentActiveList a randomly generated Rectangle in the ActiveList class it receives the value just fine.
public class ActiveList {
Rectangle[] activeList = new Rectangle[10];
public ActiveList() {
for(int i = 0; i < activeList.length; i++)
activeList[i] = null;
}
public void addToList(Rectangle x) {
for(int i = 0; i < this.activeList.length; i++) {
if(this.activeList[i] == null) {
this.activeList[i] = x;
i = this.activeList.length+1;
}
else
this.activeList[activeList.length-1] = x;
}
}
public Rectangle[] getActiveList() {
return this.activeList;
}
public int getLength() {
//System.out.print(this.activeList.length);
return this.activeList.length;
}
public void deleteFromList(int x) {
this.activeList[x] = null;
}
public Rectangle getFromList(int x) {
Rectangle retVal = this.activeList[x];
//System.out.println("Returning getFromList(int x): " +retVal);
return retVal;
}
public void genRandomRectangle() {
Random randomNumberGenerator = new Random();
double[] pointVal = new double[4];
double randomInt = randomNumberGenerator.nextInt(400-10);
pointVal[0] = randomInt;
randomInt = randomNumberGenerator.nextInt(400-10);
pointVal[1] = randomInt;
randomInt = randomNumberGenerator.nextInt((int) (400-pointVal[0]));
if(randomInt < 5) {
randomInt = randomInt+pointVal[0]+5;
}
else
pointVal[2] = randomInt+pointVal[0];
randomInt = randomNumberGenerator.nextInt((int) (400-pointVal[1]));
if(randomInt < 5) {
randomInt = randomInt+pointVal[1]+5;
}
else
pointVal[3] = randomInt+pointVal[1];
Rectangle newRandom = new Rectangle(pointVal[0], pointVal[1], pointVal[2], pointVal[3]);
//System.out.println(pointVal[0]);
//System.out.println(pointVal[1]);
//System.out.println(pointVal[2]);
//System.out.println(pointVal[3]);
System.out.println("New Random: " +newRandom);
addToList(newRandom);
}
}
However, when I try to use those values in my main class GraphicGen, the currentActiveList returns null values for all of its indexes.
public class GraphicGen extends JPanel {
ActiveList currentActiveList = new ActiveList();
public static int gridSpaceX = 400;
public static int gridSpaceY = 400;
static JFrame mainFrame = new JFrame();
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//int w = getWidth();
//int h = getHeight();
// Draw ordinate.
//g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
// Draw abcissa.
//g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
//double xInc = (double)(w - 2*PAD)/(data.length-1);
//double scale = (double)(h - 2*PAD)/maxValue();
// Mark data points.
//g2.setPaint(Color.red);
double[] coords = new double[4];
//g2.fill(new Ellipse2D.Double(coords[0], coords[1], 4, 4));
//g2.fill(new Ellipse2D.Double(coords[2], coords[3], 4, 4));
//g2.fill(new Ellipse2D.Double(100, 100, 4, 4));
System.out.println("Graphic Gen Active List Obj: " +currentActiveList);
System.out.println("Ya drew a new Main GUI!");
System.out.println("currentActiveList.getActiveList(): " +currentActiveList.getActiveList());
for(int i = 0; i < currentActiveList.getLength(); i++) {
//System.out.println("currentActiveList.getFromList(i): "+currentActiveList.getFromList(i));
//System.out.println("Graphic Gen Active List Obj: " +currentActiveList);
//System.out.println(activeList.getFromList(i).getTopLeftX());
if(currentActiveList.getFromList(i) != null) {
coords[0] = currentActiveList.getFromList(i).getTopLeftX();
System.out.println(coords[0]);
coords[1] = currentActiveList.getFromList(i).getTopLeftY();
System.out.println(coords[1]);
coords[2] = currentActiveList.getFromList(i).getBottomRightX();
System.out.println(coords[2]);
coords[3] = currentActiveList.getFromList(i).getBottomRightY();
System.out.println(coords[3]);
g2.draw(new Line2D.Double(coords[0], coords[1], coords[2], coords[1]));
g2.draw(new Line2D.Double(coords[0], coords[1], coords[0], coords[3]));
g2.draw(new Line2D.Double(coords[2], coords[1], coords[2], coords[3]));
g2.draw(new Line2D.Double(coords[0], coords[3], coords[2], coords[3]));
}
}
/*double x = 50;
double y = 50;
g2.fill(new Ellipse2D.Double(x, y, 4, 4));*/
/*for(int i = 0; i < data.length; i++) {
double x = PAD + i*xInc;
double y = h - PAD - scale*data[i];
g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));
}*/
}
/*private int maxValue() {
int max = data[0];
for(int i = 0; i < data.length; i++) {
if(data[i] > max)
max = data[i];
}
return max;
}*/
public void callRepaintOnMain() {
mainFrame.repaint();
}
public void callGenRandom() {
currentActiveList.genRandomRectangle();
}
public static void main(String[] args) {
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new GraphicGen());
mainFrame.setSize(gridSpaceX, gridSpaceY);
ButtonPrompt buttonPrompter = new ButtonPrompt();
mainFrame.setLocation(200,200);
mainFrame.setVisible(true);
}
}
The random generator method is called by the action listener.
public class ButtonPrompt extends GraphicGen {
ActionListener actionListenerRandom = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//currentActiveList.genRandomRectangle();
callGenRandom();
callRepaintOnMain();
}
};
JButton randomBtn = new JButton("Add Random Rectangle");
JButton inputCoordinates = new JButton("Input Rectangle Coordinates");
public ButtonPrompt() {
JFrame f = new JFrame("Add Rectangles");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BoxLayout boxLayout = new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS);
f.setLayout(boxLayout);
randomBtn.addActionListener(actionListenerRandom);
f.setSize(200, 200);
f.setLocation(600, 200);
f.setVisible(true);
f.add(randomBtn);
f.add(inputCoordinates);
f.pack();
}
}
Is this a scoping or referencing problem? I'm really at a loss here.
Here:
public static void main(String[] args) {
...
mainFrame.add(new GraphicGen());
...
ButtonPrompt buttonPrompter = new ButtonPrompt();
}
ButtonPrompt extends GraphicGen, which is a JPanel. In ButtonPrompt's constructor, you created a JFrame and added two JButtons to it.
So when your app starts, there will be two JFrames on the screen, one is mainFrame which contains a GraphicGen, the other is buttonPrompter which contains two buttons.
When you click on the button, the actionPerformed() is called and it's actually calling the callGenRandom() of the buttonPrompter -- if the random generation logic is correct, the generated Rectangles are added to buttonPrompter. But you didn't add this buttonPrompter to any one of the JFrames, you won't see it.
What you may want:
ButtonPrompt doesn't extend GraphicGen, instead, give ButtonPrompt a reference of the GraphicGen you added to the mainFrame.
public class ButtonPrompt extends GraphicGen {
JButton randomBtn = new JButton("Add Random Rectangle");
JButton inputCoordinates = new JButton("Input Rectangle Coordinates");
final GraphicGen gg;
public ButtonPrompt(GraphicGen gg) {
this.gg = gg;
......
ActionListener actionListenerRandom = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
gg.callGenRandom();
gg.callRepaintOnMain();
}
};
randomBtn.addActionListener(actionListenerRandom);
......
}
}
and in your main():
public static void main(String[] args) {
...
GraphicGen gg = new GraphicGen();
mainFrame.add(gg);
...
ButtonPrompt buttonPrompter = new ButtonPrompt(gg);
}
What's more, the code has other problems.
For example, GraphicGen is a JPanel, main class and it has a field of a JFrame which actually contains the GraphicGen instance when app runs -- this looks bad. I don't know much of Swing... Is it a must to call the containing JFrame's repaint() instead of just calling the JPanel's repaint(), if it has?
Your actual problem is quite unclear, but just reading the first two methods is enough to find what, I suppose, is a bug:
public ActiveList() {
for(int i = 0; i < activeList.length; i++)
activeList[i] = null;
}
the above code is completely useless. The default value of an element of an array of objects is null. So the loop assigns null to a variable wich is already null.
public void addToList(Rectangle x) {
for(int i = 0; i < this.activeList.length; i++) {
if(this.activeList[i] == null) {
this.activeList[i] = x;
i = this.activeList.length+1;
}
else
this.activeList[activeList.length-1] = x;
}
}
If your list only contains null, the rectangle will be stored at index 0, and the loop will stop. For all the susequent calls to this method, the loop will find that the element at index 0 is not null, and will thus store x at the last index of the array, and then at the first non-null index.
I don't know exactly what you're trying to achieve, and what the actual problem is, but you should probably forget about implementing your own list based on an array, and use an ArrayList instead.
I've got a form with gridLayout which contains 15 JButtons and one JLabel. Every button has an action and when it's fired It should show clicked!, perform some operation and show in console its position.
But it shows position in console only once - when I press any button first time. After that only clicked text appears in console.
What's the problem?
public class PuzzleUI extends JFrame {
private static final long serialVersionUID = 1L;
private int gap = 2;
private Puzzle puzzle;
private JComponent[][] itemGrid;
private JPanel controls;
public PuzzleUI(String title, int puzzles, int empty_cell) {
super(title);
puzzle = new Puzzle(puzzles, empty_cell);
itemGrid = new JComponent[puzzle.getRowSize()][puzzle.getRowSize()];
controls = new JPanel();
controls.setLayout(new GridLayout(puzzle.getRowSize(), puzzle
.getRowSize(), gap, gap));
init(this.getContentPane());
}
public void init(final Container pane) {
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object ob = e.getSource();
boolean finished = false;
if (ob instanceof JButton) {
System.out.println("Clicked!");
int cnt = 0;
label: for (int i = 0; i < itemGrid.length; i++)
for (int j = 0; j < itemGrid[i].length; j++) {
if (itemGrid[i][j] == (JButton) ob) {
System.out.println(i + "-" + j); // appeared only once
finished = puzzle.swap(cnt);
break label;
}
cnt++;
}
PuzzleUI.this.init(PuzzleUI.this.getContentPane());
PuzzleUI.this.controls.repaint();
if (finished == true)
JOptionPane.showMessageDialog(
PuzzleUI.this,
"FINISHED WITH MOVE: "
+ PuzzleUI.this.puzzle.getMoves());
}
}
};
int cnt = 0;
for (int i = 0; i < itemGrid.length; i++)
for (int j = 0; j < itemGrid[i].length; j++) {
int value = puzzle.getListItem(cnt);
if (value == puzzle.getEmptyFlag())
itemGrid[i][j] = new JLabel("");
else {
JButton jb = new JButton(String.valueOf(value));
jb.addActionListener(al);
itemGrid[i][j] = jb;
}
controls.add(itemGrid[i][j]);
cnt++;
}
pane.add(controls);
}
}
So Im trying to write simple editor. I want to color gray all chars witch are between " characters. Fragment which does it is:
class MainPanel extends JPanel {
private int WIDTH = 800;
private int HEIGHT = 500;
private JTextPane codePane = new JTextPane(); //Pole, w które wpisywany jest kod
private JLabel codeLabel = new JLabel("JNotepad");
private StyledDocument doc = codePane.getStyledDocument();
private final String[] keywords; //Słowa kluczowe
private final Map<String, String> shortcuts = new HashMap<>(); //syso -> System.out.println() itp.
MainPanel() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setLayout(new BorderLayout());
//Dodanie głównego pola w polu przewijanym
JScrollPane scroll = new JScrollPane(codePane);
add(scroll, BorderLayout.CENTER);
add(codeLabel, BorderLayout.SOUTH);
codePane.addKeyListener(new KeyHandler());
codePane.setFont(new Font("Monospaced", Font.PLAIN, 15));
//Załadowanie słów kluczowych
Scanner in = new Scanner(getClass().getResourceAsStream("res/keywords.txt"));
List<String> words = new LinkedList<>();
while (in.hasNext()) {
words.add(in.nextLine());
}
keywords = words.toArray(new String[words.size()]);
in.close();
}
private class KeyHandler extends KeyAdapter {
#Override
public void keyReleased(KeyEvent ev) {
highlight();
}
private void highlight() {
String code = codePane.getText();
//Zmiana koloru słów kluczowych
String[] words = code.replaceAll("\\(|\\)|\\{|\\}|\\[|\\]", " ").split("\\s");
int lastIndex = 0;
for (int a = 0; a < words.length; a++) {
SimpleAttributeSet set = new SimpleAttributeSet();
if (Arrays.asList(keywords).contains(words[a])) {
StyleConstants.setForeground(set, Color.BLUE);
}
doc.setCharacterAttributes(lastIndex, lastIndex + words[a].length(), set, true);
//Zwiekszenie ostatniego indexu
lastIndex += words[a].length() + 1; //+1 bo jeszcze spacja
}
}
}
}
When " occurs it paints characters gray, but it paints all characters after first " sign. What's wrong with this code? EDIT: Here you are, this is the full code.
Second argument in setCharacterAttributes() method is a length, not end index. It was your problem.
boolean isString = false;
char[] text = code.toCharArray();
for (int i = 0; i < text.length; i++) {
if (text[i] == '\"') {
isString = !isString;
if(!isString) {
document.setCharacterAttributes(i, 1, attributes, true);
}
}
if (isString) {
document.setCharacterAttributes(i, 1, attributes, true);
}
}
Original question was shorter with only with few lines of code but mKorbel has right:
... in this case (it's a) job for DocumentFilter, never to use KeyListener for JTextComponent.
You should check that, it could help: How to Write a Document Listener
Because the condition is true.if (string) will be true.String will be given true once it equals("\"")) .So it carry on's for the next string.
In if (string){.....} block, in the end make string=false