JPanel refreshes everytime the JFrame is resized - java

Whenever I move my window on the display; the images and text constantly refresh.
Because some content is generated randomly and then drawn, it regenerates and redraws the randomly generated parts on each refresh.
How can I make them only refresh when I want them too?
In this case, when monsterHealth reaches 0.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.*;
public class RPGClicker {
static int attackLevel = 1;
static int defenceLevel = 1;
static int hitpointsLevel = 1;
static int xp = 0;
static int gold = 0;
static int dps = 0;
static int clickDamage = attackLevel;
static int health = hitpointsLevel * 100;
static int healthRecovery = 1;
static int room = 1;
public static void main(String[] args) n{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mainGameScene();
}
});
}
public static void mainGameScene() {
JFrame window;
mainGamePanel mainGameInstance;
window = new JFrame("RPGClicker: An Unknown Quest!");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new BorderLayout());
window.setResizable(false);
mainGameInstance = new mainGamePanel();
window.add(mainGameInstance, BorderLayout.CENTER);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.util.*;
class mainGamePanel extends JPanel {
BufferedImage background, user;
public Dimension getPreferredSize() {
return new Dimension(1280, 720);
}
public void paintComponent(Graphics pencil) {
super.paintComponent(pencil);
background = ImageLoader.loadImage("rec/alpha/background0.png");
user = ImageLoader.loadImage("rec/alpha/user.png");
pencil.drawImage(background, 0, 0, null);
pencil.drawImage(user, 100, 450, null);
Monster monster = new Monster();
pencil.drawImage(monster.monsterSprite, 900, 50, null);
pencil.drawString(monster.monsterName, 900, 60);
}
public mainGamePanel() {
}
}
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.util.*;
public class Monster {
static final double BASE_MONSTER_HEALTH = 10;
static double monsterHealth = Math.pow(RPGClicker.room, 2) * BASE_MONSTER_HEALTH;
static double monsterDamage = RPGClicker.room + 1 - RPGClicker.defenceLevel;
BufferedImage monsterSprite;
String monsterName;
Random rand = new Random();
public Monster() {
String monster[] = {"Ork", "Mermaid", "Goblin"};
String monsterType = monster[rand.nextInt(monster.length)];
monsterSprite = ImageLoader.loadImage("rec/alpha/monster/" + monsterType + ".png");
String[] firstName = {"Oliver", "George", "Harry"};
String connection1 = " the ";
String[] secondName = {"Powerful ", "Unstoppable ", "Almighty "};
String connection2 = " of ";
String[] thirdName = {"Death", "America", "Pride"};
monsterName = firstName[rand.nextInt(firstName.length)] + connection1 + secondName[rand.nextInt(secondName.length)] + monsterType + connection2 + thirdName[rand.nextInt(thirdName.length)];
}
}

You're making your painting method do too much. Please understand that:
A painting method (e.g., paintComponent) is for painting and painting only.
Do not read in image files or do any other file I/O within these methods as this will critically slow down rendering, making your GUI seem poorly responsive. Why keep re-reading in images anyway when they only need to be and should be read in once.
Do not put in any program logic, such as Monster creation, within these methods since you do not have full control over when or even if a painting method is fired. Put the logic and object creation elsewhere.

Related

How to draw a spiderchart above a existing JfreeChart

I have one a jfree chart which I can generate everytime I run the code.
Now i want to override few more spider graphs on the same chart. please help me how to do that
Above this i need to add one more spider chart using jfree.
Here is my code for doing this chart.
package com.rectrix.exide.pdfbox;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.*;
public class DemoChart extends ApplicationFrame {
public DemoChart(String s)
{
super(s);
JPanel jpanel = createDemoPanel();
jpanel.setPreferredSize(new Dimension(500, 270));
setContentPane(jpanel);
}
private static CategoryDataset createDataset()
{
String s1 = "First";
String s2 = "Second";
String s3 = "Third";
String s4 = "Forth";
String s5 = "Fivth";
String s6 = "Sixth";
String s7 = "Seventh";
String s8 = "Eighth";
String s9 = "Ninth";
String s10 = "Tenth";
DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
int count = 5;
int value = 0;
//String keyRow="s";
for (int i=1;i<=10;i++){
value = i*4;
Comparable colKey = 0;
String keyRow = "s"+i;
for(int j=1;j<=count;j++){
colKey = j;
defaultcategorydataset.addValue(value, keyRow, colKey);
}
}
return defaultcategorydataset;
}
public static JFreeChart createChart1(CategoryDataset categorydataset,double d) {
SpiderWebPlot plot = new SpiderWebPlot(categorydataset);
Color bckColor1 = Color.decode("#4282CE"); //Light blue
Paint p = new GradientPaint(0, 1, bckColor1, 0, 1, bckColor1);
plot.setSeriesPaint(p);
JFreeChart chart = new JFreeChart("", plot);
return chart;
}
public static JPanel createDemoPanel()
{
JFreeChart jfreechart = createChart1(createDataset(), 10D);
return new ChartPanel(jfreechart);
}
public static void main(String args[])
{
DemoChart spiderwebchartdemo1 = new DemoChart("JFreeChart: SpiderWebChartDemo1.java");
spiderwebchartdemo1.pack();
RefineryUtilities.centerFrameOnScreen(spiderwebchartdemo1);
spiderwebchartdemo1.setVisible(true);
}
}
Please help me as soon as possible i need to send this build by tomorrow
Thank u in advance for helping and taking efforts to see this.
I want to override few more spider graphs on the same chart.
It may help to examine how a spider web plot is used to display multivariate data. The simplified example below compares just two OBSERVATIONS, each having five VARIABLES named A .. E, with random values in the range 1 .. 3. By chance, the values for variable B coincide; the rest differ. You can adjust the value of OBSERVATIONS to see the effect, but the result becomes progressively more muddled as the number of observations grows. You may want to alter series visibility, as suggested here, or consider these alternatives.
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
/** #see https://stackoverflow.com/a/32885067/230513 */
public class SpiderChart extends ApplicationFrame {
private static final int OBSERVATIONS = 2;
private static final int VARIABLES = 5;
private static final Random r = new Random();
public SpiderChart(String s) {
super(s);
add(createDemoPanel());
}
private static CategoryDataset createDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 1; i <= OBSERVATIONS; i++) {
String rowKey = "Observation " + i;
for (int j = 1; j <= VARIABLES; j++) {
Comparable colKey = Character.valueOf((char)(j+64));
dataset.addValue(r.nextInt(3) + 1, rowKey, colKey);
}
}
return dataset;
}
public static JFreeChart createChart(CategoryDataset dataset) {
SpiderWebPlot plot = new SpiderWebPlot(dataset);
JFreeChart chart = new JFreeChart("Test", plot);
return chart;
}
public static JPanel createDemoPanel() {
JFreeChart jfreechart = createChart(createDataset());
return new ChartPanel(jfreechart);
}
public static void main(String args[]) {
EventQueue.invokeLater(() -> {
SpiderChart demo = new SpiderChart("SpiderWebChart");
demo.pack();
demo.setDefaultCloseOperation(EXIT_ON_CLOSE);
demo.setVisible(true);
});
}
}

What does it mean when my compiler tells me I'm using unsafe or unchecked operations?

My program compiles fine, but my console spits out the following:
----jGRASP exec: javac -g CreditGraphics.java
Note: CreditGraphics.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
----jGRASP: operation complete.
First, what makes an operation unsafe? And how can a process be "unchecked"? What does "Recompile with -Xlint" mean? I'm using jGrasp and I'm not sure if that's a button or some sort of command? I want to see the details. It doesn't specify what is unsafe or unchecked, but here's my code anyway:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.util.Scanner;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.event.*;
import javax.mail.internet.*;
import javax.activation.*;
import java.util.Properties;
import javax.mail.Header;
import java.util.Enumeration;
import java.util.Properties;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.JApplet;
import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.URLName;
import java.beans.*;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.*;
import java.util.Scanner;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import javax.swing.Timer;
public class CreditGraphics {
//first screen variables
public String cardNum;
public JFrame frame;
public JPanel panel;
public JLabel label;
public JTextField text;
public String cardType = "";
public String carddigits;
public boolean cardValid;
public int length;
public String[] cardTypes;
public JComboBox cardTypesDD;
public static ArrayList<Integer> holdDigits = new ArrayList<Integer>();
public static ArrayList<String> holdDigitsChar = new ArrayList<String>();
public static int[] checkDigits;
public static int checkSum = 0;
//second screen variables in verifyScreen;
public JFrame vframe;
public JPanel vpanel;
public JLabel titlelabel;
public GridBagConstraints grid;
public JLabel namelabel;
public JTextField namefield;
public CreditGraphics() {
frame = new JFrame("MES Banking App");
panel = new JPanel();
label = new JLabel();
cardTypes = new String[4];
cardTypes[0] = "Visa";
cardTypes[1] = "American Express";
cardTypes[2] = "Master Card";
cardTypes[3] = "";
cardTypesDD = new JComboBox(cardTypes);
cardTypesDD.setSelectedIndex(3);
text = new JTextField(16);
panel.add(label);
panel.add(cardTypesDD);
panel.add(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
label.setText("<html>Please enter your credit card <br> 'Master Card' 'Visa' or 'American Express'</html>");
text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//after CC type is entered, prompt user to enter digits
carddigits = text.getText();//gets credit card number from jtextfield
length = carddigits.length();//sets length of card
validateCard(); //uses credit card number and length to determine if it matches up to brand
//below returns if card is valid
if (cardValid == true) {
label.setText("Card brand is valid");
}
waits(1);
text.setText("");
waits(1);
checkDigits();
}
});
cardTypesDD.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
//where program really starts
while (cardTypesDD.getSelectedIndex() == 3) {
label.setText("First, please select a card type from DD list");
}
cardType = (String) cardTypesDD.getSelectedItem();
System.out.println(cardType);
if (!cardType.equals("")) {
label.setText("Thank you, now please enter your card #");
}
//now go to the jtextfield actionlistener
}});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
new CreditGraphics();
}});
}
public void verifyScreen() {
//destroy old frame
frame.dispose();
//create new frame essentially same as last frame
vframe = new JFrame("MES Banking App");
vpanel = new JPanel();
titlelabel = new JLabel("Verification Page");
namelabel = new JLabel("Name: ");
namefield = new JTextField(20);
//title section
vpanel.setLayout(new GridBagLayout());
grid = new GridBagConstraints();
grid.fill = GridBagConstraints.PAGE_START;
grid.weightx = 0;
grid.gridx = 0;
grid.gridy = 0;
vpanel.add(titlelabel, grid);
//name section
grid.gridy = 1;
grid.insets = new Insets(10, 0, 0, 0);
vpanel.add(namelabel, grid);
grid.gridx = 1;
grid.insets = new Insets(10, 10, 0, 0);
vpanel.add(namefield, grid);
vframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
vframe.getContentPane().add(vpanel);
vframe.pack();
vframe.setVisible(true);
}
public static void waits(int k) {
long time0, time1;
time0 = System.currentTimeMillis();
do {
time1 = System.currentTimeMillis();
} while ((time1 - time0) < k * 1000);
}
public void validateCard() {
//check brand
cardValid = false;
if ((cardType.equals("Visa") && carddigits.substring(0, 1).equals("4")) && (length == 13 || length == 16)) {
label.setText("Thank you, next step");
cardValid = true;
}
if ((cardType.equals("Master Card")) && (carddigits.substring(0, 2).equals("51") || carddigits.substring(0, 2).equals("52") || carddigits.substring(0, 2).equals("53") || carddigits.substring(0, 2).equals("54") || carddigits.substring(0, 2).equals("55")) && (length == 16)) {
label.setText("Thank you, next step");
cardValid = true;
}
if ((cardType.equals("American Express") && carddigits.substring(0, 2).equals("37") && length == 15)) {
label.setText("Thank you, next step");
cardValid = true;
}
if (cardValid != true) {
System.out.println("ERROR");
label.setText("ERROR");
waits(2);
System.exit(0);
}
//end check
}
public void checkDigits() {
label.setText("Checking digits using Luhn's algorithm...");
waits(2);
//check digits
checkDigits = new int[length];
for (int i = 0; i < length; i++) {
checkDigits[i] = Integer.parseInt(carddigits.substring(i, i + 1));
//successfully puts digits into array
}
for (int e = length - 2; e >= 0; e -= 2) {
checkDigits[e] = 2 * checkDigits[e];
}
for (int d = 0; d < length; d++) {
holdDigitsChar.add(String.valueOf(checkDigits[d]));
}
for (int v = 0; v < length; v++) {
if (holdDigitsChar.get(v).length() == 2) {
holdDigits.add(Integer.parseInt(holdDigitsChar.get(v).substring(0, 1)));
holdDigits.add(Integer.parseInt(holdDigitsChar.get(v).substring(1, 2)));
} else {
holdDigits.add(Integer.parseInt(holdDigitsChar.get(v)));
}
}
for (int c = 0; c < holdDigits.size(); c++) {
checkSum += holdDigits.get(c);
}
System.out.println("Check sum:" + checkSum);
if (checkSum % 10 == 0) {
label.setText("Numbers check out, thank you");
waits(2);
verifyScreen();
} else {
System.out.println("ERROR");
System.exit(0);
}
}
}
This usually comes up if you're using collections or some other genericized object without generic parameters. For example:
List l = new ArrayList();
vs.
List<String> l = new ArrayList<>(); //or new ArrayList<String>(); in Java < 7
What this means is that the Java compiler cannot guarantee that you are using those collections in a type-safe way. For example, you should shove a String and an Integer into the ArrayList in the first scenario. At some point when you pull it out, there is a distinct possibility that you may attempt to cast the Integer instance into a String, which would result in a ClassCastException. You could, of course, be really, really, careful and not do this, but the compiler is simply alerting you to the fact that there is no way to guarantee what is inside that list.
To get rid of this warning, use the second method of instantiation. If you are sure that you can get away with this (in some instances it is possible because you can be sure what the collection will contain) you can use the #SuppressWarnings("unchecked") annotation.

Unable to find the coordinates of the pressed buttons

only problem is that whenever i set initial value for the x and y to be greater than 10,it gives bad result.Please help.It works fine for the values less than 10 for x and y.
i have also debugged it and find out whenever the button is pressed after the 10th index it behaves like setting the variable i to 1.i am unable to fix this issue as i am new in java.so i really need help in this.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.JFrame;
class butMaddFrame extends JFrame implements ActionListener
{
int x=12;
int y=12;
JButton[][] buttons = new JButton[x][y];
JPanel mPanel = new JPanel();
JPanel bPanel = new JPanel();
JPanel cPanel = new JPanel();
JTextArea scoreKeeper = new JTextArea();
Container c = getContentPane();
int[][] intArray = new int[x][y];
public butMaddFrame()
{
butGen();
score2();
//cPanel.add(scoreKeeper);
bPanel.setLayout(new GridLayout(x,y));
mPanel.setLayout(new BorderLayout());
mPanel.add(bPanel, BorderLayout.CENTER);
// mPanel.add(cPanel, BorderLayout.LINE_END);
c.add(mPanel);
setTitle("ButtonMaddness");
setSize(1000,400);
setLocation(200,200);
setVisible(true);
}
private void butGen()
{
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
{
buttons[i][j] = new JButton(String.valueOf(i)+"x"+String.valueOf(j));
buttons[i][j].setActionCommand("button" +i +"_" +j);
buttons[i][j].addActionListener(this);
bPanel.add(buttons[i][j]);
}
}
private void score()
{
// String string = "";
// for(int i=0;i<x;i++)
// {
// for(int j=0;j<y;j++)
// string += i+"x"+j+" => " +String.valueOf(intArray[i][j]) +"\t";
// string+= "\n";
// }
// scoreKeeper.setText(string);
}
private void score2()
{
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
buttons[i][j].setText(String.valueOf(intArray[i][j]));
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().contains("button"))
{
int i = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll ("_", "").charAt(0)));
int j = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll ("_", "").charAt(1)));
intArray[i][j]++;
// buttons[i][j].setVisible(false);
buttons[i][j].setBackground(Color.black);
System.out.println(e.getActionCommand() +" " +i +" " +j);
}
// score2();
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class buttonMaddness {
public static void main(String[] args)
{
butMaddFrame myFrame = new butMaddFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Your problem is here:
replaceAll("_", "").charAt(0)
because some of your buttons have things like 11_9 for
example. So you get just the first 1 of the number 11.
Just change your actionPerformed method
to this and your bug will be fixed.
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().contains("button")) {
String str = e.getActionCommand().replaceAll("button", "");
System.out.println(str);
String[] v = str.split("_");
int i = Integer.parseInt(v[0]);
int j = Integer.parseInt(v[1]);
/*
int i = Integer.parseInt(Character.toString(e.getActionCommand()
.replaceAll("button", "").replaceAll("_", "").charAt(0)));
int j = Integer.parseInt(Character.toString(e.getActionCommand()
.replaceAll("button", "").replaceAll("_", "").charAt(1)));
*/
intArray[i][j]++;
// buttons[i][j].setVisible(false);
buttons[i][j].setBackground(Color.black);
System.out.println(e.getActionCommand() + " " + i + " " + j);
}
// score2();
}

JPanel in puzzle game not updating

I have a simple puzzle game. There is an image consisting of 16 tiles (randomly placed). Images are stored in an array and when game is launched they're added to main JPanel.
Game works in this way : Each image has atributes 'place' and 'number'. 'Place' is the current place on grid (either correct or not) and 'number' is the desired place for the image. When a user clicks image their 'place' and 'number' attributes are checked. If they match nothing happens. If not game checks if any image is currently in memory. If there is none, then this image's 'place' and 'number' are stored. If there is some image in memory, then the currently clicked image's 'plac'e is checked with stored image's 'number'. When they match - their places are exchanged. This part works properly. But now, I'm calling addComponent method on my JPanel with updated images and simply nothing happens. Shouldn't the new images be added to JPanel replacing the old ones ?
package Bonus;
import javax.swing.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.*;
class Puzzle extends JPanel implements ActionListener {
private int selected_nr=-1;
private int selected_pl=-1;
private boolean memory=false;
private static Img[] images;
public Puzzle(){
JFrame f = new JFrame("Smile");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.setSize(252,252);
f.setVisible(true);
setLayout(new GridLayout(4, 4));
images = new Img[16];
int[] buttons = new int[16];
for(int i=0; i<16; i++){
buttons[i] = i;
}
int rand;
int temp;
Random random;
random = new Random(System.currentTimeMillis());
for (int i = 0; i < buttons.length; i++) {
rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length;
temp = buttons[i];
buttons[i] = buttons[rand];
buttons[rand] = temp;
}
for (int i = 0; i < 16; i++) {
images[i] = new Img(i, buttons[i]);
}
addComponents(images);
}
public void addComponents(Img[] im){
this.removeAll();
for(int i=0; i<16; i++){
im[i].addActionListener(this);
im[i].setPreferredSize(new Dimension(53,53));
add(im[i]);
}
this.validate();
}
public void actionPerformed(ActionEvent e) {
Img b = (Img)(e.getSource());
int num = b.getNumber();
int pl = b.getPlace();
if(!(b.rightPlace())){
if(memory){
if(pl == selected_nr){
images[pl].setPlace(selected_pl);
images[selected_pl].setPlace(selected_nr);
selected_nr = -1;
selected_pl = -1;
memory = false;
addComponents(images);
}
else{
System.out.println("Try other image");
}
}
else{
memory = true;
selected_nr = num;
selected_pl = pl;
}
}
else{
System.out.println("OK !");
}
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Puzzle();
}
});
}
}
class Img extends JButton {
int number;
int place;
ImageIcon img;
public Img(int p, int n){
number = n;
place = p;
img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER);
setIcon(img);
}
public boolean rightPlace(){
boolean correct=false;
if(number == place){
correct = true;
}
return correct;
}
public void setPlace(int i){
place = i;
}
public int getNumber(){
return number;
}
public int getPlace(){
return place;
}
}
EDIT: Changed the code to use the answers, but still no luck. addComponents() gets updated images[] but doesn't revalidate them.
Rather than relying on precut image files, here's an example of slicing an existing image and shuffling the resulting pieces. It combines the helpful (+1) suggestions of both #Frederick and #akf.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageLabelPanel extends JPanel implements ActionListener {
private static final int N = 4;
private final List<JLabel> list = new ArrayList<JLabel>();
private final Timer timer = new Timer(1000, this);
ImageLabelPanel() {
this.setLayout(new GridLayout(N, N));
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
int w = bi.getWidth() / N;
int h = bi.getHeight() / N;
BufferedImage b = bi.getSubimage(c * w, r * h, w, h);
list.add(new JLabel(new ImageIcon(b)));
}
}
createPane();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
timer.start();
}
private void createPane() {
this.removeAll();
for (JLabel label : list) add(label);
this.validate();
}
#Override
public void actionPerformed(ActionEvent e) {
Collections.shuffle(list);
createPane();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageLabelPanel();
}
});
}
}
You are adding all of your components again to your JPanel without actually removing any of them. In your addComponents() method, I would first call removeAll(). You might want to rename that method to highlight the side-effects, as it no longer would only be adding components. Perhaps, resetComponents() would be better.
After changing the components, you need to 'refresh' the Swing component by calling invalidate() or revalidate().

large virtual lists in Swing using AbstractListModel -- limit at 119,000,000 items?

I've got my "virtual list" in swing working well, but it seems to fail when I exceed some particular number of items. By "fail" I mean that the scroll bar magically vanishes when the number of items is > Nmax, and it comes back when the number of items is <= Nmax; Nmax seems to be somewhere around 119,304,000 on my system.
What am I running up against?!?!
(Here's a test program: on my computer, if I type in 119,304 it works ok, but I click the up arrow and the scroll bar disappears)
package com.example.test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
// based on:
// http://www.java2s.com/Tutorial/Java/0240__Swing/extendsAbstractListModel.htm
// http://www.java2s.com/Tutorial/Java/0240__Swing/SpinnerNumberModel.htm
// http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/SpinnerNumberModel.html
// http://www.java2s.com/Tutorial/Java/0240__Swing/ListeningforJSpinnerEventswithaChangeListener.htm
// http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html
public class BigVirtualList extends JFrame {
public static void main(String[] args) {
new BigVirtualList();
}
static final int initialLength = 1;
final private JList list1 = new JList();
final private BVLData bvldata = new BVLData(initialLength*1000);
public BigVirtualList() {
this.setTitle("Big virtual list");
this.getContentPane().setLayout(new BorderLayout());
this.setSize(new Dimension(400, 300));
list1.setModel(bvldata);
list1.setPrototypeCellValue(list1.getModel().getElementAt(0));
SpinnerModel model1 = new SpinnerNumberModel(initialLength,1,1000000,1);
final JSpinner spinner1 = new JSpinner(model1);
this.getContentPane().add(new JScrollPane(list1), BorderLayout.CENTER);
JLabel label1 = new JLabel("Length (1000s of items):");
JPanel panel1 = new JPanel(new BorderLayout());
panel1.add(label1, BorderLayout.WEST);
panel1.add(spinner1, BorderLayout.CENTER);
this.getContentPane().add(panel1, BorderLayout.SOUTH);
ChangeListener listener = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Integer newLength = (Integer)spinner1.getValue();
bvldata.setLength(newLength*1000);
}
};
spinner1.addChangeListener(listener);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
class BVLData extends AbstractListModel {
public BVLData(int length) { this.length = length; }
private int length;
public int getLength() { return length; }
public void setLength(int length) {
int oldLength = getLength();
this.length = length;
int newLength = getLength();
if (newLength > oldLength)
fireIntervalAdded(this, oldLength+1, newLength);
else if (newLength < oldLength)
fireIntervalRemoved(this, newLength+1, oldLength);
}
#Override
public Object getElementAt(int index) {
return "Item "+index+" mod 107 = "+(index%107);
}
#Override
public int getSize() { return getLength(); }
}
Well I don't see the purpose but anyway ...
I guess you break the integer max value somewhere in the scroll pane:
System.out.println("CellHeight:"+list1.getFixedCellHeight());
System.out.println("CellHeight*119304000:"+NumberFormat.getNumberInstance().format(list1.getFixedCellHeight()*119304000.0));
System.out.println("MAXINT:"+Integer.MAX_VALUE);
Gives you the numbers:
CellHeight:18
CellHeight*119304000:2.147.472.000
MAXINT:2.147.483.647
As you can see adding another 18000 pixel in height will go beyond MAXINT ... this gets you in trouble.

Categories