Related
I'm trying to write a kanban board. But if there are two and more stickers in one column, often the JToolBar with buttons will be shown only if you click on a sticker in this column for the firs time.
I thought that there were some problems with coordinates, but I didn't found it. The StickerListener responds th event, even prints "условие работает" if coordinates are correct, but the JToolBar remainds invisible.
import java.awt.*;
import javax.swing.*;
public class Main {
public static void main(String[] args)
{
Window window = new Window();
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Window extends JFrame {
public JButton Edit;
public JButton Read;
public JButton Delete;
private Window window;
private JToolBar jtb;
public boolean stickerToolBarActivated;
public Window() {
window= this;
setSize(500, 500);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
Desk d = new Desk();
createMenu(d);
add(d);
setDefaultSizeToProgressTypesColumns(d, this);
d.setBackground(new Color(255, 255, 255));
StickerListener sl = new StickerListener(d, this);
this.addMouseMotionListener(sl);
this.addMouseListener(sl);
this.addComponentListener(new ComponentListener() {
public void componentResized(ComponentEvent e) {
setDefaultSizeToProgressTypesColumns(d,window);
}
#Override
public void componentMoved(ComponentEvent e) {}
#Override
public void componentShown(ComponentEvent e) {}
#Override
public void componentHidden(ComponentEvent e) {}
});
jtb = new JToolBar();
Edit = new JButton("Редактровать");
jtb.add(Edit);
Delete = new JButton("Удалить");
jtb.add(Delete);
Read = new JButton("Просмотреть");
jtb.add(Read);
add(jtb, BorderLayout.NORTH);
jtb.setVisible(false);
stickerToolBarActivated=false;
setVisible(true);
}
private void createMenu(Desk d)
{
JMenuBar menuBar = new JMenuBar();
JMenu DeskFile = new JMenu("Файл");
JMenuItem SaveDesk = new JMenuItem("Сохранить доску");
DeskFile.add(SaveDesk);
menuBar.add(DeskFile);
JMenu StickerOptions = new JMenu("Стикер");
JMenuItem NewSticker = new JMenuItem("Добавить стикер");
NewSticker.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e) {
d.ProgressTypes.get(0).addSticker();
setDefaultSizeToProgressTypesColumns(d, window);
d.repaint();
}
});
StickerOptions.add(NewSticker);
menuBar.add(StickerOptions);
add(menuBar, BorderLayout.NORTH);
setJMenuBar(menuBar);
}
public JToolBar getStickerToolbar() {
return jtb;
}
public static void setDefaultSizeToProgressTypesColumns(Desk d, Window window)
{
int x=0;
int y=0;
int WindowWidth = window.getWidth();
int WindowHeight = window.getHeight();
int ptCount = d.ProgressTypes.size();
for(ProgressType pt: d.ProgressTypes)
{
pt.x=x;
pt.y=y;
pt.width= WindowWidth/ptCount;
pt.height = WindowHeight;
x+=pt.width;
for(int s=0; s<pt.stickers.size(); ++s) {
pt.stickers.get(s).setWidth(pt.width);
pt.stickers.get(s).setHeight(pt.width);
pt.stickers.get(s).y=pt.height/20+pt.width*s;
pt.stickers.get(s).x=pt.x;
}
}
}
public JButton getEdit() {
return Edit;
}
}
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Desk extends JPanel {
public ArrayList<ProgressType> ProgressTypes;
public int width;
public Desk()
{
ProgressTypes = new ArrayList<ProgressType>();
ProgressTypes.add(new ProgressType("Идеи"));
ProgressTypes.add(new ProgressType("Сделать"));
ProgressTypes.add(new ProgressType("В процессе"));
ProgressTypes.add(new ProgressType("Тестируется"));
ProgressTypes.add(new ProgressType("Готово"));
}
#Override
public void paint(Graphics g) {
super.paint(g);
for(ProgressType pt: ProgressTypes) {
pt.paint(g);
}
for(ProgressType pt: ProgressTypes)
for(Sticker s : pt.stickers)
s.paint(g);
}
}
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class ProgressType extends JPanel {
public ArrayList<Sticker> stickers;
public String name;
public int x, y, width, height;
public ProgressType(String n)
{
this.name = n;
stickers = new ArrayList<>();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
final BasicStroke borderLine = new BasicStroke(4.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_ROUND, 5.0f);
g2d.setStroke(borderLine);
g2d.setColor(Color.black);
g2d.drawLine(x, y, x+width, y);
g2d.drawLine(x, y, x, y+height);
g2d.drawLine(x, y+height/20, x+width, y+height/20); //height/20 это высота шапки таблицы
g2d.drawLine(x+width, y, x+width, y+height);
}
public int findSticker(String search) {
for(int i=0; i<stickers.size(); ++i)
{
if(stickers.get(i).title.matches(search))
return i;
}
return -1;
}
public void addSticker()
{
StickerBuilder sb = new StickerBuilder();
Sticker s = sb.getSticker();
s.y=(height/20)+(width*stickers.size())+5;
stickers.add(s);
repaint();
}
public void addSticker(Sticker s)
{
for(int i=0; i<stickers.size(); ++i)
{
stickers.get(i).y=s.y=(height/20)+(width*(i+1))+5*(i+1);
}
s.y=(height/20);
stickers.add(s);
}
}
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
public class Sticker extends JPanel {
public String text;
private String Progress;
public String title;
private BufferedImage img;
public int x;
public int y;
public int width;
public int height;
public Sticker ( String text, String Progress,String title, int x, int y)
{
this.text=text;
this.Progress=Progress;
this.title = title;
this.x=x;
this.y=y;
this.width = -1;
this.height = -1;
try {
URL resource = Sticker.class.getResource("\\transparentSticker.png");
img = null;
this.img = ImageIO.read(Paths.get(resource.toURI()).toFile());
System.out.println("c");
} catch (IOException | URISyntaxException e) {
System.out.println("caught");
}
}
public void setText(String text) {
this.text = text;
}
public void setProgress(String progress) {
Progress = progress;
}
public void setTitle(String title) {
this.title = title;
}
public void setWidth(int width){
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Sticker clone()
{
Sticker s= new Sticker(text, Progress, title, x, y);
s.setHeight(width);
s.setWidth(width);
return s;
}
#Override
public void paint(Graphics g) {
super.paint(g);
System.out.print("p");
g.drawImage(img, x, y, width-4, height, null);
String NormStr;
if(title!=null) {
NormStr = NormalizeLabel(title, g);
g.drawString(NormStr, x, y + width / 5);
}
if(text!=null) {
NormStr = NormalizeLabel(text, g);
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt = fm.getHeight();
String [] n=NormStr.split("\n");
for(int i= 0; i<n.length; ++i) {
g.drawString(n[i], x, y + width / 5 + hgt * 13 / 10 * (i + 1));
if(width / 5 + hgt * 13 / 10 * (i + 1)>=width*0.75)
{
g.drawString("...", x, y + width / 5 + hgt * 13 / 10 * (i + 1));
break;
}
}
}
}
private String NormalizeLabel(String s, Graphics g)
{
String NormalizedString = "";
String buf="";
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt= fm.getHeight();
int strw=0;
for(int i=0; i<s.length(); ++i)
{
buf+=s.charAt(i);
strw=fm.stringWidth(buf);
if(strw>=width*0.75)
{
NormalizedString+=buf;
NormalizedString+="\n";
buf="";
}
}
NormalizedString+=buf;
return NormalizedString;
}
}
import java.util.ArrayList;
public interface Builder {
void setText(String text);
void setProgress(String Progress);
void setTitle(String title);
Sticker getSticker();
}
import java.util.ArrayList;
public class StickerBuilder implements Builder{
public StickerBuilder() {
}
private String text;
private String Progress;
private String title;
public void setText(String text) {
this.text = text;
}
public void setProgress(String progress) {
Progress = progress;
}
public void setTitle(String title) {
this.title = title;
}
public Sticker getSticker()
{
return new Sticker(text, Progress, title, 0, 0);//возможно, стоит добавить функцию для х и у
}
}
import java.util.ArrayList;
import javax.swing.*;
import java.awt.*;
public class StickerChanger implements Builder {
private Sticker sticker;
public StickerChanger(Sticker sticker) {
this.sticker = sticker;
}
#Override
public void setText(String text) {
this.sticker.setText(text);
}
#Override
public void setProgress(String Progress) {
this.sticker.setProgress(Progress);
}
#Override
public void setTitle(String title) {
this.sticker.setTitle(title);
}
#Override
public Sticker getSticker() {
return null;
}
}
import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;
public class StickerListener implements MouseMotionListener, MouseListener {
private ArrayList<ProgressType> PTs;
private boolean StickerIsBeingDragged;
private int DistanceToTheEndX;
private int DistanceToTheEndY;
private Sticker CurrentSticker;
private Desk d;
private Window window;
private boolean sd2;
private final int Y_DELTA=50;
private ActionListener del;
private ActionListener edit;
private ActionListener rd;
private StickerEditorWindow sew;
public StickerListener(Desk d, Window w)
{
this.d = d;
this.PTs=d.ProgressTypes;
this.DistanceToTheEndX=this.DistanceToTheEndY=0;
this.StickerIsBeingDragged = this.sd2=false;
this.window =w;
}
#Override
public void mouseDragged(MouseEvent e) {
if (StickerIsBeingDragged)
{
sd2=true;
CurrentSticker.x=e.getX()-DistanceToTheEndX;
CurrentSticker.y=e.getY()-DistanceToTheEndY;
System.out.println(CurrentSticker.x+" "+CurrentSticker.y+" "+e.getX()+" "+ e.getY()+" "+"dragged");
d.repaint();
}
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
boolean f = true;
if(e.getButton() == MouseEvent.BUTTON1)
for (ProgressType pt : PTs) {
for (Sticker s : pt.stickers) {
System.out.println((e.getX() >= s.x) + " " + (e.getX() <= (s.x + s.width))+ " " +
(e.getY()-Y_DELTA >= s.y ) + " " + (e.getY()-Y_DELTA <= (s.y + s.width)));
System.out.println(e.getX() + " "+ e.getY()+ " " + s.x+ " "+ s.y);
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY()-Y_DELTA >= s.y && e.getY()-Y_DELTA <= (s.y + s.width)) {
CurrentSticker = s;
f=false;
JToolBar jtb = window.getStickerToolbar();
jtb.setVisible(true);
System.out.println("условие работает");
window.stickerToolBarActivated = true;
setListeners(s, pt, jtb);
f = false;
//Sticker buf = (Sticker) CurrentSticker.clone();
//pt.addSticker(buf);
d.repaint();
} else {
window.getStickerToolbar().setVisible(false);
sew = null;
window.stickerToolBarActivated = false;
if(rd!=null)
{
window.Read.removeActionListener(rd);
rd = null;
}
if(del!=null)
{
window.Delete.removeActionListener(del);
del = null;
}
if(edit!=null)
{
window.Edit.removeActionListener(edit);
edit = null;
}
}
}
}
System.out.println(e.getX()+" "+ e.getY()+" "+"cliicked");
}
private void setListeners(Sticker s, ProgressType pt, JToolBar jtb) {
del = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int iRes = JOptionPane.showConfirmDialog(window, "Удалить этот стикер?", "",
JOptionPane.YES_NO_OPTION);
if (iRes == JOptionPane.YES_NO_OPTION) {
pt.stickers.remove(s);
jtb.setVisible(false);
d.repaint();
}
}
};
edit = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (sew == null) {
createStickerEditorWindow(s);
}
}
};
rd = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
StickerReadingWindow srw = new StickerReadingWindow(s);
}
};
window.Delete.addActionListener(del);
window.Edit.addActionListener(edit);
window.Read.addActionListener(rd);
}
#Override
public void mousePressed(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1)
for(ProgressType pt: PTs) {
for (Sticker s : pt.stickers) {
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY()-Y_DELTA >= s.y && e.getY()-Y_DELTA <= (s.y + s.width)) {
DistanceToTheEndX = e.getX()-s.x;
DistanceToTheEndY = e.getY()-s.y;
StickerIsBeingDragged = true;
CurrentSticker = s;
System.out.println(s.x+" "+s.y+" "+e.getX()+" "+ e.getY()+" "+"pressed");
}
}
}
}
private void createStickerEditorWindow(Sticker s)
{
DefaultListModel listModel = new DefaultListModel();
for (ProgressType pt: PTs)
listModel.addElement(pt.name);
sew = new StickerEditorWindow(s, listModel);
sew.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
sew=null;
d.repaint();
}
});
}
#Override
public void mouseReleased(MouseEvent e) {
if(StickerIsBeingDragged) {
if(sd2) {
System.out.println(CurrentSticker.x + " " + CurrentSticker.y + " " + e.getX() + " " + e.getY() + " " + "released");
StickerIsBeingDragged = false;
d.repaint();
if (CurrentSticker.x < 0)
CurrentSticker.x = 0;
else if (CurrentSticker.x > window.getWidth())
CurrentSticker.x = window.getWidth() - 15;
for (ProgressType pt : PTs) {
if (CurrentSticker.x >= pt.x && CurrentSticker.x < pt.x + pt.width && CurrentSticker.x >= 0) {
CurrentSticker.x = pt.x;
Sticker buf = (Sticker) CurrentSticker.clone();
pt.addSticker(buf);
}
if (pt.stickers.indexOf(CurrentSticker) != -1) {
pt.stickers.remove(CurrentSticker);
}
}
sd2=false;
d.repaint();
}
}
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
public class StickerEditorWindow extends JFrame {
private Sticker sticker;
private JTextField title;
private JTextArea text;
private JList ProgressTypes;
private JButton Save;
private JButton DelayTitleChanges;
private JButton DelayTextChanges;
private JButton DelayProgressTypeChanges;
private DefaultListModel listModel;
public StickerEditorWindow(Sticker s, DefaultListModel lm) {
this.sticker = s;
setSize(600,300);
setTitle("Редактировать стикер");
setAlwaysOnTop(true);
// setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(
0, 0,
1, 1,
4, 0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets(5, 5, 5, 5),
0, 0
);
title = new JTextField("Тема");
text = new JTextArea("Введите текст");
this.listModel = lm;
ProgressTypes = new JList(listModel);
this.add(title, gbc);
++gbc.gridy;
gbc.weighty=4;
this.add(text, gbc);
this.add(new JScrollPane(text), gbc);
gbc.weighty=0;
++gbc.gridy;
this.add(ProgressTypes, gbc);
ProgressTypes.setFocusable(false);
this.add(new JScrollPane(ProgressTypes), gbc);
ProgressTypes.setVisible(true);
Save = new JButton("Cохранить");
DelayTitleChanges = new JButton("Отменить изм. темы");
DelayTextChanges = new JButton("Отменить изм. текста");
DelayProgressTypeChanges = new JButton("Отменить изм. колонки прогресса");
gbc.gridx=1;
gbc.weightx=1;
gbc.gridy = 3;
this.add(Save, gbc);
gbc.gridy = 0;
this.add(DelayTitleChanges, gbc);
gbc.gridy = 1;
gbc.weighty=4;
this.add(DelayTextChanges, gbc);
gbc.gridy = 2;
this.add(DelayProgressTypeChanges, gbc);
if(sticker.text!=null) {
text.setText(sticker.text);
}
if(sticker.title!=null)
title.setText(sticker.title);
setListeners();
setVisible(true);
}
private void setListeners()
{
StickerEditorWindow w = this;
this.Save.addActionListener(new StickerChangeListener(w, this.Save));
this.DelayProgressTypeChanges.addActionListener(new StickerChangeListener(w, this.DelayProgressTypeChanges));
this.DelayTitleChanges.addActionListener(new StickerChangeListener(w, this.DelayTitleChanges));
this.DelayTextChanges.addActionListener(new StickerChangeListener(w, this.DelayTextChanges));
}
public void SaveStickerChanges()
{
sticker.title=title.getText();
sticker.text = text.getText();
}
public void CancelTitleChanges()
{
title.setText(sticker.title);
}
public void CancelTextChanges()
{
text.setText(sticker.text);
}
}
import javax.swing.*;
import javax.swing.plaf.basic.BasicOptionPaneUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class StickerChangeListener implements ActionListener {
private StickerEditorWindow sew;
private JButton sender;
public StickerChangeListener(StickerEditorWindow sew, JButton sender) {
this.sew = sew;
this.sender = sender;
}
#Override
public void actionPerformed(ActionEvent e) {
if(sender.getText().equals("Cохранить")){
sew.SaveStickerChanges();
}
if(sender.getText().equals("Отменить изм. темы")){
sew.CancelTitleChanges();
}
if(sender.getText().equals("Отменить изм. текста")){
sew.CancelTextChanges();
}
if(sender.getText().equals("Отменить изм. колонки прогресса")){}
}
}
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
public class StickerReadingWindow extends JFrame{
private Sticker sticker;
private int width;
private int height;
ReadingCrutch rc;
public StickerReadingWindow(Sticker s) throws HeadlessException {
this.sticker = s;
width=height=500;
String winHeader = "";
if(sticker.title!=null)
winHeader+="Тема: "+sticker.title+ " ";
setTitle(winHeader);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel jp = new JPanel();
add(jp);
Graphics g =jp.getGraphics();
setSize(width,height);
setTitle("Редактировать стикер");
setAlwaysOnTop(true);
BufferedImage img = null;
try {
URL resource = Sticker.class.getResource("\\transparentSticker.png");
img = ImageIO.read(Paths.get(resource.toURI()).toFile());
System.out.println("c");
} catch (IOException | URISyntaxException e) {
System.out.println("caught");
}
if(img!=null)
rc = new ReadingCrutch(img, sticker.text, width);
add(rc);
setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ReadingCrutch extends JPanel {
private BufferedImage img;
private String str;
private int width;
public ReadingCrutch(BufferedImage img, String str, int w) {
this.img = img;
this.str = str;
this.width =w;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(img, 0, 0, 450, 450, null);
g.setColor(Color.black);
String txt = str;
String [] s=txt.split(" ");
String buf= "";
String NormalizedString="";
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt= fm.getHeight();
int strw=0;
for(int i=0; i<s.length; ++i)
{
buf+=s[i]+" ";
strw=fm.stringWidth(buf);
if(strw>=width*0.75)
{
NormalizedString+=buf;
NormalizedString+="\n";
buf="";
}
}
NormalizedString+=buf;
g.setColor(Color.black);
String[] forWrite= NormalizedString.split("\n");
for(int i=0; i<forWrite.length; ++i)
{
g.drawString(forWrite[i]+" ", 0, 0 + width / 5 + hgt * 13 / 10 * (i + 1));
}
}
}
The problem is in the control flow of the StickerListener.mouseClicked(): you search the stickers to find the one that has been clicked.
Due to the if / else you reset the toolbar for every sticker that has not been clicked, meaning that your code only works if you clicked on the last sticker (in order of iteration).
Your code will work if you move the code from the else part before the loop (so that it executes only once):
#Override
public void mouseClicked(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1) {
window.getStickerToolbar().setVisible(false);
sew = null;
window.stickerToolBarActivated = false;
if (rd != null) {
window.Read.removeActionListener(rd);
rd = null;
}
if (del != null) {
window.Delete.removeActionListener(del);
del = null;
}
if (edit != null) {
window.Edit.removeActionListener(edit);
edit = null;
}
for (ProgressType pt : PTs) {
for (Sticker s : pt.stickers) {
System.out.println((e.getX() >= s.x) + " " + (e.getX() <= (s.x + s.width)) + " " +
(e.getY() - Y_DELTA >= s.y) + " " + (e.getY() - Y_DELTA <= (s.y + s.width)));
System.out.println(e.getX() + " " + e.getY() + " " + s.x + " " + s.y);
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY() - Y_DELTA >= s.y && e.getY() - Y_DELTA <= (s.y + s.width)) {
CurrentSticker = s;
JToolBar jtb = window.getStickerToolbar();
jtb.setVisible(true);
System.out.println("условие работает");
window.stickerToolBarActivated = true;
setListeners(s, pt, jtb);
//Sticker buf = (Sticker) CurrentSticker.clone();
//pt.addSticker(buf);
d.repaint();
return;
}
}
}
}
System.out.println(e.getX()+" "+ e.getY()+" "+"cliicked");
}
My program generates random numbers from 0 to 12 but if the result is 12 it would set dash as the text of JLabel, instead of the number generated.
Now, I wanted to sort my JPanel in ascending order based on the JLabel contents. In case of similarities in numbers, the black JPanels are placed on the left. It works fine except when there are dashes included, in which it doesn't sort properly. I would like to insert the JPanels containing dashes anywhere but it's not working as expected.
Screencaps from a shorter version of my program:
Pure numbers:
Dash included:
Here's the shorter version of my code (using the logic of integer sorting):
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Comparator;
public class SortFrames extends JFrame
{
static ArrayList<JPanel> panels = new ArrayList<JPanel>();
JPanel panel = new JPanel();
JPanel sortPane = new JPanel();
int toWrite = 0;
int colorGen = 0;
int comparison = 0;
Random rand = new Random();
public SortFrames()
{
for(int i = 0; i<4;i++)
{
panels.add(new JPanel());
}
for(JPanel p: panels)
{
toWrite = rand.nextInt(13);
colorGen = rand.nextInt(2);
p.add(new JLabel());
JLabel lblToSet = (JLabel)p.getComponent(0);
if(colorGen == 0)
{
p.setBackground(Color.BLACK);
lblToSet.setForeground(Color.WHITE);
}
if(colorGen == 1)
{
p.setBackground(Color.WHITE);
lblToSet.setForeground(Color.BLACK);
}
if(toWrite != 12){lblToSet.setText("" +toWrite);}
if(toWrite == 12){lblToSet.setText("-");}
p.setPreferredSize(new Dimension(30, 30));
panel.add(p);
}
sortMethod();
for(JPanel p: panels)
{
panel.add(p);
panel.revalidate();
}
add(panel);
panel.setPreferredSize(new Dimension(300, 300));
setPreferredSize(new Dimension(300, 300));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
pack();
setLocationRelativeTo(null);
}
public void sortMethod()
{
for(int i = 0; i<(panels.size());i++)
{
for(int j = i+1; j<(panels.size());j++)
{
JLabel one = (JLabel)(panels.get(i)).getComponent(0);
JLabel two = (JLabel)(panels.get(j)).getComponent(0);
String lblOne = one.getText();
String lblTwo = two.getText();
if(!lblOne.equals("-") && !lblTwo.equals("-"))
{
int comp1 = Integer.parseInt(lblOne);
int comp2 = Integer.parseInt(lblTwo);
JPanel pnl1 = panels.get(i);
JPanel pnl2 = panels.get(j);
if(comp1 == comp2)
{
if(pnl1.getBackground() == Color.BLACK && pnl2.getBackground() == Color.WHITE)
{
panels.set(i, pnl1);
panels.set(j, pnl2);
}
if(pnl1.getBackground() == Color.WHITE && pnl2.getBackground() == Color.BLACK)
{
panels.set(i, pnl2);
panels.set(j, pnl1);
}
}
if(comp1 != comp2)
{
if(comp1>comp2)
{
panels.set(i, pnl2);
panels.set(j, pnl1);
}
}
}
if(lblOne.equals("-") && !lblTwo.equals("-"))
{
JPanel pnl1 = panels.get(i);
panels.set(rand.nextInt(panels.size()), pnl1);
}
if(!lblOne.equals("-") && lblTwo.equals("-"))
{
JPanel pnl2 = panels.get(j);
panels.set(rand.nextInt(panels.size()), pnl2);
}
}
}
}
public static void main(String args[])
{
new SortFrames();
}
}
I also have another method, which is by using Comparator class which also creates the same problem (this sorts equal numbers based on foreground but still the same as to sort equal numbers based on background so it has no effect on the said issue).
private static class JPanelSort implements Comparator<JPanel>
{
#Override
public int compare(JPanel arg0, JPanel arg1)
{
JLabel one = ((JLabel) arg0.getComponent(0));
JLabel two = ((JLabel) arg1.getComponent(0));
String firstContent = one.getText();
String secondContent = two.getText();
try
{
comparisonRes = Integer.compare(Integer.parseInt(firstContent), Integer.parseInt(secondContent));
if(comparisonRes == 0)
{
if(one.getForeground() == Color.BLACK && two.getForeground() == Color.WHITE)
{
comparisonRes = 1;
}
if(two.getForeground() == Color.BLACK && one.getForeground() == Color.WHITE)
{
comparisonRes = -1;
}
}
}
catch(NumberFormatException e)
{
comparisonRes = 0;
}
return comparisonRes;
}
}
Please tell me your ideas. Thank you.
It's much easier to sort data than to sort JPanels.
Here's mu GUI displaying your numbers.
So, lets create a Java object to hold the card data.
public class DataModel {
private final int number;
private final int colorNumber;
private final Color backgroundColor;
private final Color foregroundColor;
public DataModel(int number, int colorNumber, Color backgroundColor,
Color foregroundColor) {
this.number = number;
this.colorNumber = colorNumber;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public int getNumber() {
return number;
}
public int getColorNumber() {
return colorNumber;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
}
Pretty straightforward. We have fields to hold the information and getters to retrieve the information. We can make all the fields final since we're not changing anything once we set the values.
The sort class is pretty simple as well.
public class DataModelComparator implements Comparator<DataModel> {
#Override
public int compare(DataModel o1, DataModel o2) {
if (o1.getNumber() < o2.getNumber()) {
return -1;
} else if (o1.getNumber() > o2.getNumber()) {
return 1;
} else {
if (o1.getColorNumber() < o2.getColorNumber()) {
return -1;
} else if (o1.getColorNumber() > o2.getColorNumber()) {
return 1;
} else {
return 0;
}
}
}
}
Since we keep the color number, sorting by color is as easy as sorting a number.
Now that we've moved the data to it's own List, we can concentrate on creating the GUI.
package com.ggl.testing;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SortFrames implements Runnable {
private List<DataModel> dataModels;
private JPanel[] panels;
private JLabel[] labels;
private Random random = new Random();
public SortFrames() {
this.dataModels = new ArrayList<>();
this.random = new Random();
for (int i = 0; i < 4; i++) {
int number = random.nextInt(13);
int colorNumber = random.nextInt(2);
Color backgroundColor = Color.BLACK;
Color foregroundColor = Color.WHITE;
if (colorNumber == 1) {
backgroundColor = Color.WHITE;
foregroundColor = Color.BLACK;
}
dataModels.add(new DataModel(number, colorNumber, backgroundColor,
foregroundColor));
}
Collections.sort(dataModels, new DataModelComparator());
}
#Override
public void run() {
JFrame frame = new JFrame("Sort Frames");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
panels = new JPanel[dataModels.size()];
labels = new JLabel[dataModels.size()];
for (int i = 0; i < dataModels.size(); i++) {
DataModel dataModel = dataModels.get(i);
panels[i] = new JPanel();
panels[i].setBackground(dataModel.getBackgroundColor());
labels[i] = new JLabel(getDisplayText(dataModel));
labels[i].setBackground(dataModel.getBackgroundColor());
labels[i].setForeground(dataModel.getForegroundColor());
panels[i].add(labels[i]);
mainPanel.add(panels[i]);
}
frame.add(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
private String getDisplayText(DataModel dataModel) {
if (dataModel.getNumber() == 12) {
return "-";
} else {
return Integer.toString(dataModel.getNumber());
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new SortFrames());
}
public class DataModel {
private final int number;
private final int colorNumber;
private final Color backgroundColor;
private final Color foregroundColor;
public DataModel(int number, int colorNumber, Color backgroundColor,
Color foregroundColor) {
this.number = number;
this.colorNumber = colorNumber;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public int getNumber() {
return number;
}
public int getColorNumber() {
return colorNumber;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
}
public class DataModelComparator implements Comparator<DataModel> {
#Override
public int compare(DataModel o1, DataModel o2) {
if (o1.getNumber() < o2.getNumber()) {
return -1;
} else if (o1.getNumber() > o2.getNumber()) {
return 1;
} else {
if (o1.getColorNumber() < o2.getColorNumber()) {
return -1;
} else if (o1.getColorNumber() > o2.getColorNumber()) {
return 1;
} else {
return 0;
}
}
}
}
}
The lessons to be learned here are:
Separate the data from the view.
Focus on one part of the problem at a time. Divide and conquer.
Another problem, same program:
The following is MainGUI.java
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class MainGUI extends JFrame implements ActionListener
{
private static final long serialVersionUID = 4149825008429377286L;
private final double version = 8;
public static int rows;
public static int columns;
private int totalCells;
private MainCell[] cell;
public static Color userColor;
JTextField speed = new JTextField("250");
Timer timer = new Timer(250,this);
String generationText = "Generation: 0";
JLabel generationLabel = new JLabel(generationText);
int generation = 0;
public MainGUI(String title, int r, int c)
{
rows = r;
columns = c;
totalCells = r*c;
System.out.println(totalCells);
cell = new MainCell[totalCells];
setTitle(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Timer set up
timer.setInitialDelay(Integer.parseInt(speed.getText()));
timer.setActionCommand("timer");
//set up menu bar
JMenuBar menuBar = new JMenuBar();
JMenu optionsMenu = new JMenu("Options");
JMenu aboutMenu = new JMenu("About");
menuBar.add(optionsMenu);
menuBar.add(aboutMenu);
JMenuItem helpButton = new JMenuItem("Help!");
helpButton.addActionListener(this);
helpButton.setActionCommand("help");
aboutMenu.add(helpButton);
JMenuItem aboutButton = new JMenuItem("About");
aboutButton.addActionListener(this);
aboutButton.setActionCommand("about");
aboutMenu.add(aboutButton);
JMenuItem colorSelect = new JMenuItem("Select a Custom Color");
colorSelect.addActionListener(this);
colorSelect.setActionCommand("colorSelect");
optionsMenu.add(colorSelect);
JMenuItem sizeChooser = new JMenuItem("Define a Custom Size");
sizeChooser.addActionListener(this);
sizeChooser.setActionCommand("sizeChooser");
optionsMenu.add(sizeChooser);
//Create text field to adjust speed and its label
JPanel speedContainer = new JPanel();
JLabel speedLabel = new JLabel("Enter the speed of a life cycle (in ms):");
speedContainer.add(speedLabel);
speedContainer.add(speed);
speedContainer.add(generationLabel);
Dimension speedDim = new Dimension(100,25);
speed.setPreferredSize(speedDim);
//Create various buttons
JPanel buttonContainer = new JPanel();
JButton randomizerButton = new JButton("Randomize");
randomizerButton.addActionListener(this);
randomizerButton.setActionCommand("randomize");
buttonContainer.add(randomizerButton);
JButton nextButton = new JButton("Next"); //forces a cycle to occur
nextButton.addActionListener(this);
nextButton.setActionCommand("check");
buttonContainer.add(nextButton);
JButton startButton = new JButton("Start");
startButton.addActionListener(this);
startButton.setActionCommand("start");
buttonContainer.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(this);
stopButton.setActionCommand("stop");
buttonContainer.add(stopButton);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(this);
clearButton.setActionCommand("clear");
buttonContainer.add(clearButton);
//holds the speed container and button container, keeps it neat
JPanel functionContainer = new JPanel();
BoxLayout functionLayout = new BoxLayout(functionContainer, BoxLayout.PAGE_AXIS);
functionContainer.setLayout(functionLayout);
functionContainer.add(speedContainer);
speedContainer.setAlignmentX(CENTER_ALIGNMENT);
functionContainer.add(buttonContainer);
buttonContainer.setAlignmentX(CENTER_ALIGNMENT);
//finish up with the cell container
GridLayout cellLayout = new GridLayout(rows,columns);
JPanel cellContainer = new JPanel(cellLayout);
cellContainer.setBackground(Color.black);
int posX = 0;
int posY = 0;
for(int i=0;i<totalCells;i++)
{
MainCell childCell = new MainCell();
cell[i] = childCell;
childCell.setName(String.valueOf(i));
childCell.setPosX(posX);
posX++;
childCell.setPosY(posY);
if(posX==columns)
{
posX = 0;
posY++;
}
cellContainer.add(childCell);
childCell.deactivate();
Graphics g = childCell.getGraphics();
childCell.paint(g);
}
//make a default color
userColor = Color.yellow;
//change icon
URL imgURL = getClass().getResource("images/gol.gif");
ImageIcon icon = new ImageIcon(imgURL);
System.out.println(icon);
setIconImage(icon.getImage());
//add it all up and pack
JPanel container = new JPanel();
BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
container.setLayout(containerLayout);
container.add(cellContainer);
container.add(functionContainer);
add(menuBar);
setJMenuBar(menuBar);
add(container);
pack();
}
private void checkCells()
{
//perform check for every cell
for(int i=0;i<totalCells;i++)
{
cell[i].setNeighbors(checkNeighbors(i));
}
//use value from check to determine life
for(int i=0;i<totalCells;i++)
{
int neighbors = cell[i].getNeighbors();
if(cell[i].isActivated())
{
System.out.println(cell[i].getName()+" "+neighbors);
if(neighbors==0||neighbors==1||neighbors>3)
{
cell[i].deactivate();
}
}
if(cell[i].isActivated()==false)
{
if(neighbors==3)
{
cell[i].activate();
}
}
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
if(rn.nextInt(6)==0)
{
cell[i].activate();
}
}
}
//help button, self-explanatory
if(e.getActionCommand().equals("help"))
{
JOptionPane.showMessageDialog(this, "The game is governed by four rules:\nFor a space that is 'populated':"
+ "\n Each cell with one or no neighbors dies, as if by loneliness."
+ "\n Each cell with four or more neighbors dies, as if by overpopulation."
+ "\n Each cell with two or three neighbors survives."
+ "\nFor a space that is 'empty' or 'unpopulated':"
+ "\n Each cell with three neighbors becomes populated."
+ "\nLeft click populates cells. Right click depopulates cells.","Rules:",JOptionPane.PLAIN_MESSAGE);
}
//shameless self promotion
if(e.getActionCommand().equals("about"))
{
JOptionPane.showMessageDialog(this, "Game made and owned by *****!"
+ "\nFree usage as see fit, but give credit where credit is due!\nVERSION: "+version,"About:",JOptionPane.PLAIN_MESSAGE);
}
//clears all the cells
if(e.getActionCommand().equals("clear"))
{
timer.stop();
generation = 0;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
}
}
//starts timer
if(e.getActionCommand().equals("start"))
{
if(Integer.parseInt(speed.getText())>0)
{
timer.setDelay(Integer.parseInt(speed.getText()));
timer.restart();
}
else
{
JOptionPane.showMessageDialog(this, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
}
//stops timer
if(e.getActionCommand().equals("stop"))
{
timer.stop();
}
//run when timer
if(e.getActionCommand().equals("timer"))
{
generation++;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
timer.stop();
checkCells();
timer.setInitialDelay(Integer.parseInt(speed.getText()));
timer.restart();
}
//see checkCells()
if(e.getActionCommand().equals("check"))
{
generation++;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
checkCells();
}
//color select gui
if(e.getActionCommand().equals("colorSelect"))
{
userColor = JColorChooser.showDialog(this, "Choose a color:", userColor);
if(userColor==null)
{
userColor = Color.yellow;
}
}
//size chooser!
if(e.getActionCommand().equals("sizeChooser"))
{
SizeChooser size = new SizeChooser();
size.setLocationRelativeTo(null);
size.setVisible(true);
}
}
private int checkNeighbors(int c)
{
//if a LIVE neighbor is found, add one
int neighbors = 0;
if(cell[c].getPosX()!=0&&cell[c].getPosY()!=0)
{
if(c-columns-1>=0)
{
if(cell[c-columns-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosY()!=0)
{
if(c-columns>=0)
{
if(cell[c-columns].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=0)
{
if(c-columns+1>=0)
{
if(cell[c-columns+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns+1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=0)
{
if(c-1>=0)
{
if(cell[c-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1)
{
if(c+1<totalCells)
{
if(cell[c+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=0&&cell[c].getPosY()!=rows-1)
{
if(c+columns-1<totalCells)
{
if(cell[c+columns-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosY()!=rows-1&&cell[c].getPosY()!=rows-1)
{
if(c+columns<totalCells)
{
if(cell[c+columns].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=rows-1)
{
if(c+columns+1<totalCells)
{
if(cell[c+columns+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns+1].getName());
neighbors++;
}
}
}
return neighbors;
}
}
The following is MainCell.java:
public class MainCell extends JPanel implements MouseListener
{
//everything here should be self-explanatory
private static final long serialVersionUID = 1761933778208900172L;
private boolean activated = false;
public static boolean leftMousePressed;
public static boolean rightMousePressed;
private int posX = 0;
private int posY = 0;
private int neighbors = 0;
private URL cellImgURL_1 = getClass().getResource("images/cellImage_1.gif");
private ImageIcon cellImageIcon_1 = new ImageIcon(cellImgURL_1);
private Image cellImage_1 = cellImageIcon_1.getImage();
private URL cellImgURL_2 = getClass().getResource("images/cellImage_2.gif");
private ImageIcon cellImageIcon_2 = new ImageIcon(cellImgURL_2);
private Image cellImage_2 = cellImageIcon_2.getImage();
private URL cellImgURL_3 = getClass().getResource("images/cellImage_3.gif");
private ImageIcon cellImageIcon_3 = new ImageIcon(cellImgURL_3);
private Image cellImage_3 = cellImageIcon_3.getImage();
public MainCell()
{
Dimension dim = new Dimension(17, 17);
setPreferredSize(dim);
addMouseListener(this);
}
public void activate()
{
setBackground(MainGUI.userColor);
System.out.println(getName()+" "+posX+","+posY+" activated");
setActivated(true);
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}
else if(getPosY()!=0&&getPosX()!=MainGUI.columns-1)
{
g.drawImage(cellImage_1,0,0,null);
}
else if(getPosY()==0)
{
g.drawImage(cellImage_2,0,0,null);
}
else if(getPosX()==MainGUI.columns-1)
{
g.drawImage(cellImage_3,0,0,null);
}
}
public void setActivated(boolean b)
{
activated = b;
}
public void deactivate()
{
setBackground(Color.gray);
System.out.println(getName()+" "+posX+","+posY+" deactivated");
setActivated(false);
}
public boolean isActivated()
{
return activated;
}
public void setNeighbors(int i)
{
neighbors = i;
}
public int getNeighbors()
{
return neighbors;
}
public int getPosX()
{
return posX;
}
public void setPosX(int x)
{
posX = x;
}
public int getPosY()
{
return posY;
}
public void setPosY(int y)
{
posY = y;
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
if(leftMousePressed&&SwingUtilities.isLeftMouseButton(e))
{
activate();
}
if(rightMousePressed&&SwingUtilities.isRightMouseButton(e))
{
deactivate();
}
}
public void mouseExited(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
if(SwingUtilities.isRightMouseButton(e)&&!leftMousePressed)
{
deactivate();
rightMousePressed = true;
}
if(SwingUtilities.isLeftMouseButton(e)&&!rightMousePressed)
{
activate();
leftMousePressed = true;
}
}
public void mouseReleased(MouseEvent e)
{
if(SwingUtilities.isRightMouseButton(e))
{
rightMousePressed = false;
}
if(SwingUtilities.isLeftMouseButton(e))
{
leftMousePressed = false;
}
}
}
The following is SizeChooser.java:
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.*;
public class SizeChooser extends JFrame
{
private static final long serialVersionUID = -6431709376438241788L;
public static MainGUI GUI;
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
JTextField rowsTextField = new JTextField(String.valueOf((screenSize.height/17)-15));
JTextField columnsTextField = new JTextField(String.valueOf((screenSize.width/17)-10));
private static int rows = screenSize.height/17-15;
private static int columns = screenSize.width/17-10;
public SizeChooser()
{
setResizable(false);
setTitle("Select a size!");
JPanel container = new JPanel();
BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
container.setLayout(containerLayout);
add(container);
JLabel rowsLabel = new JLabel("Rows:");
container.add(rowsLabel);
container.add(rowsTextField);
JLabel columnsLabel = new JLabel("Columns:");
container.add(columnsLabel);
container.add(columnsTextField);
JButton confirmSize = new JButton("Confirm");
confirmSize.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
GUI.setVisible(false);
GUI = null;
if(Integer.parseInt(rowsTextField.getText())>0)
{
rows = Integer.parseInt(rowsTextField.getText());
}
else
{
JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
if(Integer.parseInt(columnsTextField.getText())>0)
{
columns = Integer.parseInt(columnsTextField.getText());
}
else
{
JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
GUI = new MainGUI("The Game of Life!", rows, columns);
GUI.setLocationRelativeTo(null);
GUI.setVisible(true);
setVisible(false);
}
});
container.add(confirmSize);
URL imgURL = getClass().getResource("images/gol.gif");
ImageIcon icon = new ImageIcon(imgURL);
System.out.println(icon);
setIconImage(icon.getImage());
pack();
}
public static void main(String[]args)
{
GUI = new MainGUI("The Game of Life!", rows, columns);
GUI.setLocationRelativeTo(null);
GUI.setVisible(true);
}
}
So the problem now is, when the randomize button is pressed, or a large number of cells exist and then the timer is started, the cells aren't as snappy as they would be with less active cells. For example, with 100 columns and 50 rows, when the randomize button is pressed, one cell activates, then the next, then another, and so forth. Can I have them all activate at exactly the same time? Is this just a problem with too many things calculated at once? Would concurrency help?
QUICK EDIT: Is the swing timer the best idea for this project?
I havent read through your code completely but I am guessing that your listener methods are fairly computationally intensive and hence the lag in updating the display.
This simple test reveals that your randomize operation should be fairly quick:
public static void main(String args[]) {
Random rn = new Random();
boolean b[] = new boolean[1000000];
long timer = System.nanoTime();
for (int i = 0; i < b.length; i++) {
b[i] = rn.nextInt(6) == 0;
}
timer = System.nanoTime() - timer;
System.out.println(timer + "ns / " + (timer / 1000000) + "ms");
}
The output for me is:
17580267ns / 17ms
So this leads me into thinking activate() or deactivate() is causing your UI to be redrawn.
I am unable to run this because I don't have your graphical assets, but I would try those changes to see if it works:
In MainGUI#actionPerformed, change:
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
if(rn.nextInt(6)==0)
{
cell[i].activate();
}
}
}
to:
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
// This will not cause the object to be redrawn and should
// be a fairly cheap operation
cell[i].setActivated(rn.nextInt(6)==0);
}
// Cause the UI to repaint
repaint();
}
Add this to MainCell
// You can specify those colors however you like
public static final Color COLOR_ACTIVATED = Color.RED;
public static final Color COLOR_DEACTIVATED = Color.GRAY;
And change:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}
to:
protected void paintComponent(Graphics g)
{
// We now make UI changes only when the component is painted
setBackground(activated ? COLOR_ACTIVATED : COLOR_DEACTIVATED);
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}
This question already has answers here:
How do I fade an image in swing?
(3 answers)
Fade in and fade out effect in java applet
(3 answers)
Closed 9 years ago.
The applet is working fine, in showing the image and the text, I would like the image to fade where it is currently but reappear in another spot, then reload in the same spot later.
I would also like to fade and move the test as well,
Here's my code so far, forgive me I'm a newbie!
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;
public class FadeImage extends Applet {
Image img, faded;
int level, sign;
MediaTracker tracker;
AlphaFilter f;
FilteredImageSource fis;
String msg2 = "University of Utah Football";
public void init() {
setBackground(Color.red);
setForeground(Color.black);
level = 0;
sign = 15;
tracker = new MediaTracker(this);
try {
img = getImage(new URL(getDocumentBase(), "uofu.jpg"));
tracker.addImage(img,0);
tracker.waitForID(0);
}
catch (Exception e) {
e.printStackTrace();
}
f = new AlphaFilter();
f.setLevel(level);
fis = new FilteredImageSource(img.getSource(), f) ;
FadeThread ft = new FadeThread();
ft.delayedFading(this, 20);
ft.start();
}
public void paint(Graphics g) {
Font myFont = new Font("Times New Roman", Font.BOLD, 24);
g.setFont(myFont);
g.setColor(Color.red);
g.drawString(msg2, 10, 465);
if (faded != null) {
g.drawImage(faded,0,0,this);
Font myFont2 = new Font("Times New Roman", Font.BOLD, 33);
g.setFont(myFont2);
setBackground(Color.black);
setForeground(Color.white);
g.setColor(Color.white);
g.drawString("Get Season tickets now!", 10, 490);
}
}
public void fadeIt() {
Graphics g = this.getGraphics();
level += sign;
if (level < 0) {
level=0;
sign = sign * -1;
}
if (level > 255) {
level=255;
sign = sign * -1;
try {
Thread.sleep(1000);
}
catch (Exception e) {}
}
f.setLevel(level);
if (faded != null) faded.flush();
faded = this.createImage(fis);
tracker.addImage(faded,0);
try {
tracker.waitForID(0);
}
catch (Exception ex) {
ex.printStackTrace();
}
repaint();
}
class FadeThread extends Thread {
FadeImage fadeApplet;
int delay;
public void delayedFading(FadeImage f, int delay) {
this.fadeApplet = f;
this.delay = delay;
}
public void run() {
while (true) {
try {
sleep(delay);
fadeApplet.fadeIt();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
class AlphaFilter extends RGBImageFilter {
private int level;
public AlphaFilter() {
canFilterIndexColorModel = true;
}
public void setLevel(int lev) {
level = lev;
}
public int filterRGB(int x, int y, int rgb) {
int a = level * 0x01000000;
return (rgb & 0x00ffffff) | a;
}
}
}
I want to create a text field that will be for dates and will have dd.mm.YYYY format. Now what I want the user to type only the numbers, not the dots to. So the field would be like:
_ _. _ _ . _ _ _ _
So when the user wants to type the date: 15.05.2010 for example, he will only type the numbers in the sequence 15052010.
Also I would like, when he presses on left or right arrow, the cursor to go from one field (not JTextField, but field in the JTextField) to the next. So lets say I have JTextField with this text in it: 15.05.2010 If the user is on the beginning and he presses the right arrow, the cursor should go to the .05 field.
I hope you understand me because right now I don't have any idea how to make this, or at least how to look for it on google.
Well, here are 4 classes that solve your problem.
In my case its version control but IP address has the same structure and its easy to modify it.
package com.demo.textfield.version;
import javax.swing.text.Document;
/**
* create documents for text fields
*/
public class DocumentsFactory {
private DocumentsFactory() {}
public static Document createIntDocument() {
return createIntDocument(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public static Document createIntDocument(int maxValue) {
return createIntDocument(maxValue, Integer.MAX_VALUE);
}
public static Document createIntDocument(int maxValue, int maxLength) {
IntDocument intDocument = new IntDocument();
intDocument.setMaxVal(maxValue);
intDocument.setMaxLength(maxLength);
return intDocument;
}
}
in the followed class we define view:
package com.demo.textfield.version;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JPanel;
public class GridbagPanel extends JPanel {
private static final long serialVersionUID = 1L;
public static final Insets NO_INSETS = new Insets(0, 0, 0, 0);
public GridBagConstraints constraints;
private GridBagLayout layout;
public GridbagPanel() {
layout = new GridBagLayout();
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = NO_INSETS;
setLayout(layout);
}
public void setHorizontalFill() {
constraints.fill = GridBagConstraints.HORIZONTAL;
}
public void setNoneFill() {
constraints.fill = GridBagConstraints.NONE;
}
public void add(Component component, int x, int y, int width, int
height, int weightX, int weightY) {
GridBagLayout gbl = (GridBagLayout) getLayout();
gbl.setConstraints(component, constraints);
add(component);
}
public void add(Component component, int x, int y, int width, int height) {
add(component, x, y, width, height, 0, 0);
}
public void setBothFill() {
constraints.fill = GridBagConstraints.BOTH;
}
public void setInsets(Insets insets) {
constraints.insets = insets;
}
}
We use a plain document that contains our main logic (your changes should be here):
package com.demo.textfield.version;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/**
* a class for positive integers
*/
public class IntDocument extends PlainDocument {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final String NUMERIC = "0123456789";
private int maxVal = -1;
private int maxLength = -1;
public IntDocument() {
this.maxVal = -1;
maxVal = Integer.MAX_VALUE;
maxLength = Integer.MAX_VALUE;
}
public void setMaxLength(int maxLength) {
if (maxLength < 0)
throw new IllegalArgumentException("maxLength<0");
this.maxLength = maxLength;
}
public void setMaxVal(int maxVal) {
this.maxVal = maxVal;
}
public void insertString
(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null)
return;
if (str.startsWith(" ") && offset == 0) {
beep();
str = "";
}
if (!isValidForAcceptedCharsPolicy(str))
return;
if (validateLength(offset, str) == false)
return;
if (!isValidForMaxVal(offset, str))
return;
super.insertString(offset, str, attr);
}
public boolean isValidForAcceptedCharsPolicy(String str) {
if (str.equals("")) {
beep();
return false;
}
for (int i = 0; i < str.length(); i++) {
if (NUMERIC.indexOf(String.valueOf(str.charAt(i))) == -1) {
beep();
return false;
}
}
return true;
}
public boolean isValidForMaxVal(int offset, String toAdd) {
String str_temp;
//String str_text = "";
String str1 = "";
String str2 = "";
try {
str1 = getText(0, offset);
str2 = getText(offset, getLength() - offset);
} catch (Exception e) {
e.printStackTrace();
}
int i_value;
str_temp = str1 + toAdd + str2;
//str_temp = str_temp.trim();
i_value = Integer.parseInt(str_temp);
if (i_value > maxVal) {
beep();
return false;
} else
return true;
}
private boolean validateLength(int offset, String toAdd) {
String str_temp;
//String str_text = "";
String str1 = "";
String str2 = "";
try {
str1 = getText(0, offset);
str2 = getText(offset, getLength() - offset);
} catch (Exception e) {
e.printStackTrace();
}
str_temp = str1 + toAdd + str2;
if (maxLength < str_temp.length()) {
beep();
return false;
} else
return true;
}
private void beep() {
//java.awt.Toolkit.getDefaultToolkit().beep();
}
}
And this is last one with main method that implements all above posted code and you get pretty good view. In my case I used list of 4 text fields separated by dot. You can jump from one "window" to another by using arrows or tab or dot or if your number length reached 4. It will work with implementation of FocusAdapter class:
package com.demo.textfield.version;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
* diplays an version text field
*/
![enter image description here][1]public class VersionTextField extends GridbagPanel {
private static final long serialVersionUID = 1L;
/**
* a text field for each byte
*/
private JTextField[] textFields;
/**
* dots between text fields
*/
private JLabel[] dotsLabels;
/**
* used to calculate enable/disable color; never shown
*/
private static JTextField sampleTextField = new JTextField();
/**
* listen to changes in the byte fields
*/
private MyDocumentListener documentListener;
/**
* list of key listeners
*/
private List<KeyListener> keyListenersList;
/**
* List of Focus Adapter that select all data in JTextFiled during action
* */
private List<FocusAdapter> focusAdapterList;
/**
* list of key listeners
*/
private List<FocusListener> focusListenersList;
private int maxHeight = 0;
public VersionTextField() {
this(4);
}
/**
* #param byteCount
* number of bytes to display
*/
private VersionTextField(int byteCount) {
textFields = new JTextField[byteCount];
for (int i = 0; i < textFields.length; i++) {
textFields[i] = new JTextField(4);
}
//layout
//constraints.insets = new Insets(0, 0, 0, 0);
List<JLabel> dotsLabelsList = new ArrayList<JLabel>();
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setHorizontalAlignment(JTextField.CENTER);
Document document = DocumentsFactory.createIntDocument(9999);
textField.setDocument(document);
if (i < textFields.length-1) {
add(textField, i * 2, 0, 1, 1);
if (textField.getPreferredSize().height > maxHeight)
maxHeight = textField.getPreferredSize().height;
JLabel label = new JLabel(".");
add(label, (i * 2) + 1, 0, 1, 1);
if (label.getPreferredSize().height > maxHeight)
maxHeight = label.getPreferredSize().height;
dotsLabelsList.add(label);
} else
add(textField, i * 2, 0, 1, 1);
}
//dotsLabels = new JLabel[dotsLabelsList.size()];
dotsLabels = new JLabel[dotsLabelsList.size()];
dotsLabels = dotsLabelsList.toArray(dotsLabels);
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setBorder(BorderFactory.createEmptyBorder());
}
//init
Color backgroundColor = UIManager.getColor("TextField.background");
setBackground(backgroundColor);
Border border = UIManager.getBorder("TextField.border");
setBorder(border);
//register listeners
for (int i = 1; i < textFields.length; i++) {
JTextField field = textFields[i];
field.addKeyListener(new BackKeyAdapter());
}
documentListener = new MyDocumentListener();
for (int i = 0; i < textFields.length - 1; i++) {
JTextField field = textFields[i];
field.getDocument().addDocumentListener(documentListener);
field.addKeyListener(new ForwardKeyAdapter());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addKeyListener(new MyKeyListener());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addFocusListener(new MyFocusAdapter());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addFocusListener(new MyFocusAdapter());
}
keyListenersList = new ArrayList<KeyListener>();
focusListenersList = new ArrayList<FocusListener>();
focusAdapterList = new ArrayList<FocusAdapter>();
}
public synchronized void addKeyListener(KeyListener l) {
super.addKeyListener(l);
keyListenersList.add(l);
}
public synchronized void addFocusListener(FocusListener l) {
super.addFocusListener(l);
if (focusListenersList != null)
focusListenersList.add(l);
}
public synchronized void removeKeyListener(KeyListener l) {
super.removeKeyListener(l);
if (focusListenersList != null)
keyListenersList.remove(l);
}
public synchronized void removeFocusListener(FocusListener l) {
super.removeFocusListener(l);
keyListenersList.remove(l);
}
public void setEnabled(boolean b) {
super.setEnabled(b);
sampleTextField.setEnabled(b);
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setEnabled(b);
}
for (int i = 0; i < dotsLabels.length; i++) {
JLabel dotsLabel = dotsLabels[i];
dotsLabel.setEnabled(b);
}
setBackground(sampleTextField.getBackground());
setForeground(sampleTextField.getForeground());
setBorder(sampleTextField.getBorder());
}
public void requestFocus() {
super.requestFocus();
textFields[0].requestFocus();
}
public void setEditable(boolean b) {
sampleTextField.setEditable(b);
setBackground(sampleTextField.getBackground());
setForeground(sampleTextField.getForeground());
setBorder(sampleTextField.getBorder());
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setEditable(b);
}
for (int i = 0; i < dotsLabels.length; i++) {
JLabel dotsLabel = dotsLabels[i];
dotsLabel.setForeground(sampleTextField.getForeground());
}
}
public boolean isFieldEmpty() {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
String sCell = textField.getText().trim();
if (!(sCell.equals("")))
return false;
}
return true;
}
public Dimension getPreferredSize() {
if (super.getPreferredSize().height > maxHeight)
maxHeight = super.getPreferredSize().height;
return new Dimension(super.getPreferredSize().width, maxHeight);
}
/**
* clears current text in text fiekd
*/
private void reset() {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.getDocument().removeDocumentListener(documentListener);
textField.setText("");
textField.getDocument().addDocumentListener(documentListener);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("test");
VersionTextField ipTextField = new VersionTextField();
ipTextField.setText("9.1.23.1479");
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(ipTextField);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void setText(String version) {
if (version == null || "".equals(version) || "null".equals(version))
reset();
else {
setVer(version.split("[.]"));
}
}
private void setVer(String[] ver) {
if (ver == null) {
reset();
return;
}
Enumeration<String> enumeration = Collections.enumeration(Arrays.asList(ver));
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
String s = (String) enumeration.nextElement();
textField.getDocument().removeDocumentListener(documentListener);
textField.setText(s);
textField.getDocument().addDocumentListener(documentListener);
}
}
public void setToolTipText(String toolTipText) {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setToolTipText(toolTipText);
}
}
private class MyDocumentListener implements DocumentListener {
#Override
public void insertUpdate(DocumentEvent e) {
Document document = e.getDocument();
try {
JTextField textField = (JTextField) FocusManager.getCurrentManager().getFocusOwner();
String s = document.getText(0, document.getLength());
if (s.length() == 4){ // && textField.getCaretPosition() == 2) {
textField.transferFocus();
}
} catch (BadLocationException e1) {
e1.printStackTrace();
return;
}
}
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
// Document document = e.getDocument();
// try {
// Component component = FocusManager.getCurrentManager().getFocusOwner();
// String s = document.getText(0, document.getLength());
//
// // get selected integer
// int valueInt = Integer.parseInt(s);
//
// if (valueInt > 25) {
// component.transferFocus();
// }
//
// } catch (BadLocationException e1) {
// e1.printStackTrace();
// return;
// }
}
}
private class BackKeyAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getComponent();
if (textField.getCaretPosition() == 0
&& KeyEvent.VK_LEFT == e.getKeyCode()
&& e.getModifiers() == 0)
textField.transferFocusBackward();
if (textField.getCaretPosition() == 0
&& KeyEvent.VK_BACK_SPACE == e.getKeyCode()
&& e.getModifiers() == 0) {
textField.transferFocusBackward();
}
}
}
private class ForwardKeyAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getComponent();
if (KeyEvent.VK_RIGHT == e.getKeyCode() && e.getModifiers() == 0) {
int length = textField.getText().length();
int caretPosition = textField.getCaretPosition();
if (caretPosition == length) {
textField.transferFocus();
e.consume();
}
}
if (e.getKeyChar() == '.' &&
textField.getText().trim().length() != 0) {
textField.setText(textField.getText().trim());
textField.transferFocus();
e.consume();
}
}
}
/**
* #return current text in ip text field
*/
public String getText() {
StringBuffer buffer = new StringBuffer();
String ipResult;
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
if(textField.getText().trim().equals("")){
return "";
}
buffer.append(Integer.parseInt(textField.getText()));
if (i < textFields.length - 1){
buffer.append('.');
}
}
ipResult = buffer.toString();
return ipResult;
}
/**
* general purpose key listener
*/
private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyPressed(new KeyEvent(VersionTextField.this,
e.getID(), e.getWhen(), e.getModifiers(), e
.getKeyCode(), e.getKeyChar(), e
.getKeyLocation()));
}
}
public void keyReleased(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyReleased(new KeyEvent(VersionTextField.this, e
.getID(), e.getWhen(), e.getModifiers(),
e.getKeyCode(), e.getKeyChar(), e.getKeyLocation()));
}
}
public void keyTyped(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyTyped(new KeyEvent(VersionTextField.this, e.getID(),
e.getWhen(), e.getModifiers(), e.getKeyCode(), e
.getKeyChar(), e.getKeyLocation()));
}
}
}
private class MyFocusAdapter extends FocusAdapter {
public void focusGained(FocusEvent e) {
for (int i = 0; i < focusListenersList.size(); i++) {
FocusListener focusListener = focusListenersList.get(i);
focusListener.focusGained(new FocusEvent(
VersionTextField.this,
e.getID(),
e.isTemporary(),
e.getOppositeComponent()
));
}
if(e.getComponent() instanceof javax.swing.JTextField){
highlightText((JTextField)e.getSource());
}
}
public void focusLost(FocusEvent e) {
for (int i = 0; i < focusListenersList.size(); i++) {
FocusListener focusListener = focusListenersList.get(i);
focusListener.focusLost(new FocusEvent(
VersionTextField.this,
e.getID(),
e.isTemporary(),
e.getOppositeComponent()
));
}
}
public void highlightText(javax.swing.JTextField ctr){
//ctr.setSelectionColor(Color.BLUE);
//ctr.setSelectedTextColor(Color.WHITE);
ctr.setSelectionStart(0);
ctr.setSelectionEnd(ctr.getText().length());
System.out.println(ctr.getText());
}
}
}
here a view what we got:
here you go
JFormattedTextField