I have 3 classes. One class is my mainframe, another class is my JInternalFrame and also my Observer and the third class does a simulation with a field ob buttons and that one is also my observable class.
Basically I made a button in my observer that copies itself. That includes the add to the desktoppane and the addObserver function of my observable class.
The clone of my observer should also observer the very same observable. So if I interact with the one JInternalFrame, it also changes stuff for the other InternalFrame. It should act like a mirror. (Actually the copy should have like diffrent color buttons and a diffrent orientation but I think that should not be a problem to implement, as soon as I successfully could mirror my Observer)
So since I am using the Observable pattern, I also have to implement the "update" function in my Observer class. I did that and I works like a charm. But when I copy my JInternalFrame, the new InternalFrame observes the Observable(Simulation), but my original JInternalFrame loses the observable connection. It does not show buttons anymore etc.
What I tried: I created a second Observer/JInternalFrame class that extends my first Observer class. That did not work as well. I don't know if thats even a possibility to achieve what I want to.
Sorry for my non perfect english. Sorry for some german words that you might find in the code and sorry that I post so much code. But I am really uncertain right now where my mistake is since I tried to find the error for ours so far.
So here are 2 pictures for you:
First picture shows how my JInternalFrame looks like when I create it. Here everything works perfectly.
Second picture shows what it looks like when I click on the New View button. As already described. The original JInternalFrame does not show the simulation anymore. Although they are both observing the same Observable.
And here are my 3 imporant classes:
MainFrame:
public class LangtonsAmeise extends JFrame implements ActionListener {
JDesktopPane desk;
JPanel panelButtons;
JMenuBar jmb;
JMenu file, modus;
JMenuItem load, save, exit, mSetzen, mMalen, mLaufen;
JSlider slider;
static int xInt, yInt, xKindFrame = 450, yKindFrame = 450, xLocation,
yLocation, xMainFrame = 1000, yMainFrame = 900;
static boolean bSetzen = false, bMalen = false, running = true;
static JFileChooser fc;
Random randomGenerator = new Random();
JLabel xLabel, yLabel, speed, statusText, status;
JButton start, stop, addAnt;
JTextField xField, yField;
public LangtonsAmeise() {
// Desktop
desk = new JDesktopPane();
getContentPane().add(desk, BorderLayout.CENTER);
// File Chooser
fc = new JFileChooser(System.getProperty("user.dir"));
speed = new JLabel("Geschwindigkeit");
xLabel = new JLabel("x:");
yLabel = new JLabel("y:");
xLabel.setHorizontalAlignment(JLabel.RIGHT);
yLabel.setHorizontalAlignment(JLabel.RIGHT);
xLabel.setOpaque(true);
yLabel.setOpaque(true);
xField = new JTextField();
yField = new JTextField();
start = new JButton("Fenster erstellen");
stop = new JButton("Pause/Fortsetzen");
start.setMargin(new Insets(0, 0, 0, 0));
stop.setMargin(new Insets(0, 0, 0, 0));
// Buttons
panelButtons = new JPanel();
panelButtons.setLayout(new GridLayout());
panelButtons.add(start);
panelButtons.add(xLabel);
panelButtons.add(xField);
panelButtons.add(yLabel);
panelButtons.add(yField);
panelButtons.add(speed);
panelButtons.add(new Panel());
panelButtons.add(stop);
start.addActionListener(this);
stop.addActionListener(this);
add(panelButtons, BorderLayout.NORTH);
statusText = new JLabel("Status:");
status = new JLabel("Stopp");
// JMenuBar
jmb = new JMenuBar();
setJMenuBar(jmb);
file = new JMenu("File");
modus = new JMenu("Mode");
mLaufen = new JMenuItem("Laufen");
mMalen = new JMenuItem("Malen");
mSetzen = new JMenuItem("Setzen");
load = new JMenuItem("Simulation laden");
//save = new JMenuItem("Simulation speichern");
mSetzen.addActionListener(this);
mMalen.addActionListener(this);
mLaufen.addActionListener(this);
exit = new JMenuItem("Exit");
file.add(load);
file.addSeparator();
file.add(exit);
load.addActionListener(this);
modus.add(mLaufen);
modus.add(mSetzen);
modus.add(mMalen);
jmb.add(file);
jmb.add(modus);
for (int i = 0; i < 20; i++) {
jmb.add(new JLabel(" "));
}
jmb.add(statusText);
jmb.add(status);
setSize(new Dimension(xMainFrame, yMainFrame));
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width / 2 - this.getSize().width / 2, dim.height
/ 2 - this.getSize().height / 2);
xField.setText("5");
yField.setText("5");
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Fenster erstellen")) {
if (xField.getText().equals("") || yField.getText().equals("")) {
} else {
xInt = Integer.parseInt(xField.getText());
yInt = Integer.parseInt(yField.getText());
state s = new state();
kindFenster k = new kindFenster(s, this);
s.addObserver(k);
addChild(k);
s.startSimulation();
}
}
if (e.getActionCommand().equals("Pause/Fortsetzen")) {
running = !running;
System.out.println(running);
status.setText("Stopp");
}
if (e.getActionCommand().equals("Setzen")) {
status.setText("Setzen");
running = false;
bSetzen = true;
bMalen = false;
}
if (e.getActionCommand().equals("Laufen")) {
status.setText("Laufen");
running = true;
bSetzen = false;
bMalen = false;
}
if (e.getActionCommand().equals("Malen")) {
status.setText("Malen");
running = false;
bSetzen = false;
bMalen = true;
}
if (e.getActionCommand().equals("Simulation laden")) {
LangtonsAmeise.running = false;
InputStream fis = null;
try {
fc.showOpenDialog(null);
fis = new FileInputStream(fc.getSelectedFile().getPath());
ObjectInputStream ois = new ObjectInputStream(fis);
state s = (state) ois.readObject();
kindFenster k = new kindFenster(s, this);
s.addObserver(k);
addChild(k);
s.startSimulation();
} catch (IOException | ClassNotFoundException
| NullPointerException e1) {
LangtonsAmeise.running = true;
} finally {
try {
fis.close();
} catch (NullPointerException | IOException e1) {
LangtonsAmeise.running = true;
}
}
LangtonsAmeise.running = true;
}
}
public void addChild(JInternalFrame kind) {
xLocation = randomGenerator.nextInt(xMainFrame - xKindFrame);
yLocation = randomGenerator.nextInt(yMainFrame - yKindFrame - 100);
kind.setSize(370, 370);
kind.setLocation(xLocation, yLocation);
desk.add(kind);
kind.setVisible(true);
}
public static void main(String[] args) {
LangtonsAmeise hauptFenster = new LangtonsAmeise();
}
}
JInternalFrame:
public class kindFenster extends JInternalFrame implements ActionListener,
Serializable,Observer,Cloneable {
/**
*
*/
private static final long serialVersionUID = 8939449766068226519L;
static int nr = 0;
static int x,y,xScale,yScale,xFrame,yFrame;
state s;
ArrayList<ImageIcon> ameisen = new ArrayList<ImageIcon>();
JFileChooser fc;
LangtonsAmeise la;
Color alteFarbe, neueFarbe;
JButton save, addAnt, newView;
JPanel panelButtonsKind;
JSlider sliderKind;
public JPanel panelSpielfeld,panelSpielfeldKopie;
JButton[] jbArrayy;
static SetzenActionListener sal = new SetzenActionListener();
static MouseMotionActionListener mmal = new MouseMotionActionListener();
public kindFenster(state s,LangtonsAmeise la) {
super("Kind " + (++nr), true, true, true, true);
setLayout(new BorderLayout());
this.s=s;
jbArrayy=new JButton[s.jbArrayy.length];
for (int b = 1; b<s.jbArrayy.length;b++) {
this.jbArrayy[b] = s.jbArrayy[b];
}
this.la=la;
setSize(new Dimension(xFrame, yFrame));
this.addInternalFrameListener(listener);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
panelSpielfeld = new JPanel();
panelSpielfeld.setLayout(new GridLayout(s.y, s.x));
panelButtonsKind = new JPanel();
panelButtonsKind.setLayout(new GridLayout(1, 3));
save = new JButton("<html>Save<br>simulation</html>");
addAnt = new JButton("<html>Add<br>ant</html>");
newView = new JButton("<html>New<br>View</html>");
save.setActionCommand("save");
addAnt.setActionCommand("addAnt");
newView.setActionCommand("newView");
save.setMargin(new Insets(0, 0, 0, 0));
addAnt.setMargin(new Insets(0, 0, 0, 0));
addAnt.addActionListener(this);
save.addActionListener(this);
newView.addActionListener(this);
sliderKind = new JSlider(JSlider.HORIZONTAL, 1, 9, 5);
sliderKind.setSnapToTicks(true);
sliderKind.setPaintTicks(true);
sliderKind.setPaintTrack(true);
sliderKind.setMajorTickSpacing(1);
sliderKind.setPaintLabels(true);
sliderKind.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
state.sleeptime = 1000 / speed;
}
}
});
panelButtonsKind.add(save);
panelButtonsKind.add(newView);
panelButtonsKind.add(sliderKind);
panelButtonsKind.add(addAnt);
add(panelButtonsKind, BorderLayout.NORTH);
add(panelSpielfeld, BorderLayout.CENTER);
this.addComponentListener(new MyComponentAdapter());
for (int i = 1 ; i<jbArrayy.length;i++) {
panelSpielfeld.add(jbArrayy[i]);
}
}
// I have been trying around to change the orientation of the buttons in the copy of the frame
public void secondViewFrameSettings() {
int temp;
for (int i = 1; i<=x;i++) {
for (int k = 0; k<y;k++) {
temp = i+(k*x);
panelSpielfeldKopie.add(s.jbArrayy[temp]);
}
}
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("addAnt")) {
s.addAnt();
}
if (e.getActionCommand().equals("newView")){
kindFenster kk = new kindFenster(s,la);
s.addObserver(kk);
la.addChild(kk);
}
if (e.getActionCommand().equals("save")) {
OutputStream fos = null;
try {
LangtonsAmeise.running=false;
try {
fc = new JFileChooser(System.getProperty("user.dir"));
fc.showSaveDialog(null);
LangtonsAmeise.fc.setCurrentDirectory(fc.getSelectedFile());
fos = new FileOutputStream(fc.getSelectedFile());
ObjectOutputStream o = new ObjectOutputStream(fos);
o.writeObject(s);
} catch (NullPointerException e2) {
System.out.println("Fehler beim Auswählen der Datei. Wenden Sie sich an den Entwickler.");
}
} catch (IOException e1) {
LangtonsAmeise.running=true;
System.err.println(e1);
} finally {
try {
fos.close();
} catch (NullPointerException | IOException e1) {
LangtonsAmeise.running=true;
}
LangtonsAmeise.running=true;
}
LangtonsAmeise.running=true;
}
}
InternalFrameListener listener = new InternalFrameAdapter() {
public void internalFrameClosing(InternalFrameEvent e) {
e.getInternalFrame().dispose();
s.simulation.suspend();
}
};
class MyComponentAdapter extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
//Ameisenbilder an die Buttongrößen anpassen
xScale=s.jbArrayy[1].getSize().width;
yScale=s.jbArrayy[1].getSize().height;
s.ameisen.clear();
s.ameisen.add(new ImageIcon(new ImageIcon("ameise.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
}
}
public void update(Observable o, Object arg) {
if (o == s) {
for (int i = 1;i<s.jbArrayy.length;i++) {
jbArrayy[i].setBackground(s.jbArrayy[i].getBackground());
}
}
}
}
class SetzenActionListener implements ActionListener,Serializable {
JButton source;
#Override
public void actionPerformed(ActionEvent e) {
source = (JButton) e.getSource();
if (LangtonsAmeise.bSetzen == true) {
if (source.getBackground().equals(Color.GREEN)) {
source.setBackground(Color.WHITE);
} else {
source.setBackground(Color.GREEN);
}
}
}
}
class MouseMotionActionListener extends MouseInputAdapter implements Serializable {
boolean dragged = false;
JButton tempJButton = new JButton();
public void mouseEntered(MouseEvent e) {
if (LangtonsAmeise.bMalen == true && dragged == true) {
((JButton) e.getSource()).setBackground(Color.GREEN);
}
}
public void mouseDragged(MouseEvent e) {
dragged = true;
}
public void mouseReleased(MouseEvent e) {
dragged = false;
}
}
Observable class:
public class state extends Observable implements Serializable {
/**
*
*/
private static final long serialVersionUID = 450773214079105589L;
int[] obRand, reRand, unRand, liRand;
int x, y, temp;
static int sleeptime = 200;
Color background;
int posAmeise, aktuellesIcon = 1, altePosAmeise, xScale, yScale;
Color alteFarbe, neueFarbe, color1, color2;
ArrayList<JButton> jbSer = new ArrayList<JButton>();
private List<Ant> ants = new ArrayList<Ant>();
ArrayList<ImageIcon> ameisen = new ArrayList<>();
JButton[] jbArrayy;
transient Thread simulation;
public state() {
this.x = LangtonsAmeise.xInt;
this.y = LangtonsAmeise.yInt;
color1 = Color.WHITE;
color2 = Color.GREEN;
jbArrayy = new JButton[x * y + 1];
initializeBorders();
initializeAntsImages();
initializeSimulationButtons();
xScale = jbArrayy[1].getSize().width;
yScale = jbArrayy[1].getSize().height;
// Startpunkt für die Ameise festlegen
posAmeise = (((x / 2) * y) - y / 2);
background = jbArrayy[posAmeise].getBackground();
ants.add(new Ant(this));
}
public void initializeAntsImages() {
ameisen.add(new ImageIcon(new ImageIcon("ameise.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
}
// Alle Buttons für das Simulationsfeld werden erstellt
public void initializeSimulationButtons() {
jbArrayy[0] = new JButton();
for (int i = 1; i < jbArrayy.length; i++) {
jbArrayy[i] = new JButton();
jbArrayy[i].setBackground(color1);
jbArrayy[i].addActionListener(kindFenster.sal);
jbArrayy[i].addMouseListener(kindFenster.mmal);
jbArrayy[i].addMouseMotionListener(kindFenster.mmal);
}
}
// Ränderindex in Array schreiben
public void initializeBorders() {
reRand = new int[y];
liRand = new int[y];
obRand = new int[x];
unRand = new int[x];
for (int i = 0; i < x; i++) {
obRand[i] = i + 1;
unRand[i] = (x * y - x) + i + 1;
}
for (int i = 1; i <= y; i++) {
reRand[i - 1] = i * x;
liRand[i - 1] = i * x - (x - 1);
}
}
public void initializeSimulation() {
if (simulation != null && simulation.isAlive()) {
simulation.stop();
}
simulation = new Thread() {
#Override
public void run() {
super.run();
while (true) {
try {
sleep(300);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
while (LangtonsAmeise.running && countObservers() > 0) {
try {
Thread.sleep(sleeptime);
for (Ant a : ants) {
move(a);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
}
public void startSimulation() {
initializeSimulation();
simulation.start();
}
public void changeColor(int altePos, Color c) {
jbArrayy[altePos].setBackground(c);
}
public void addAnt() {
ants.add(new Ant(this));
}
public void changeIcon(boolean k, Ant a) {
int g = (k == true) ? 1 : -1;
if (a.aktuellesIcon + g < 0) {
a.aktuellesIcon = 3;
} else if (a.aktuellesIcon + g > 3) {
a.aktuellesIcon = 0;
} else {
a.aktuellesIcon += g;
}
jbArrayy[a.posAmeise].setIcon(ameisen.get(a.aktuellesIcon));
setChanged();
notifyObservers();
}
public void rightCheck(Ant a) {
if (checkInArray(a.posAmeise, reRand)) {
a.posAmeise -= x - 1;
} else {
a.posAmeise += 1;
}
}
public void leftCheck(Ant a) {
if (checkInArray(a.posAmeise, liRand)) {
a.posAmeise += x - 1;
} else {
a.posAmeise -= 1;
}
}
public void upCheck(Ant a) {
if (checkInArray(a.posAmeise, obRand)) {
a.posAmeise += (y - 1) * x;
} else {
a.posAmeise -= x;
}
}
public void downCheck(Ant a) {
if (checkInArray(a.posAmeise, unRand)) {
a.posAmeise -= (y - 1) * x;
} else {
a.posAmeise += x;
}
}
public void checkAmeisenSize(Ant a) {
while (!(ameisen.size() == 4)) {
}
;
}
public static boolean checkInArray(int currentState, int[] myArray) {
int i = 0;
for (; i < myArray.length; i++) {
if (myArray[i] == currentState)
break;
}
return i != myArray.length;
}
public ImageIcon getAntImage() {
return ameisen.get(aktuellesIcon);
}
public void move(Ant a) throws InterruptedException {
try {
a.altePosAmeise = a.posAmeise;
a.alteFarbe = jbArrayy[a.posAmeise].getBackground();
if (a.alteFarbe.equals(Color.GREEN) && ameisen.size() == 4) {
if (a.aktuellesIcon == 0) {
checkAmeisenSize(a);
rightCheck(a);
} else if (a.aktuellesIcon == 1) {
checkAmeisenSize(a);
downCheck(a);
} else if (a.aktuellesIcon == 2) {
checkAmeisenSize(a);
leftCheck(a);
} else if (a.aktuellesIcon == 3) {
checkAmeisenSize(a);
upCheck(a);
}
changeIcon(true, a);
changeColor(a.altePosAmeise, Color.WHITE);
} else if (a.alteFarbe.equals(Color.WHITE) && ameisen.size() == 4) {
if (a.aktuellesIcon == 0) {
checkAmeisenSize(a);
leftCheck(a);
} else if (a.aktuellesIcon == 1) {
checkAmeisenSize(a);
upCheck(a);
} else if (a.aktuellesIcon == 2) {
checkAmeisenSize(a);
rightCheck(a);
} else if (a.aktuellesIcon == 3) {
checkAmeisenSize(a);
downCheck(a);
}
changeIcon(false, a);
changeColor(a.altePosAmeise, Color.GREEN);
setChanged();
notifyObservers();
}
jbArrayy[a.altePosAmeise].setIcon(new ImageIcon());
} catch (IndexOutOfBoundsException e) {
move(a);
}
}
}
Edit: Ant Class
import java.awt.Color;
import java.awt.Image;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Ant implements Serializable {
int posAmeise, aktuellesIcon = 1, altePosAmeise;
Color alteFarbe, neueFarbe;
ArrayList<ImageIcon> ameisen = new ArrayList<>();
public Ant(state s) {
this.posAmeise = s.posAmeise;
s.jbArrayy[posAmeise].setIcon(s.ameisen.get(aktuellesIcon));
}
}
Related
I am writing a game for a snake in Java Swing using the MVC pattern.
The code of Controller and View are shown below. I am trying to implement a button that will help player choose a difficulty level.
The difficulty level is controlled by a timer in the Controller class. I am beginner in Java and help is appreciated.
Code of Controller class:
public class Controller implements KeyListener, ActionListener{
private Renderer renderer;
private Timer mainTimer;
private Snake snake;
public Controller() {
snake = new Snake();
renderer = new Renderer(this);
this.renderer.addKeyListener(this);
this.mainTimer = new Timer(150, this);
mainTimer.start();
}
public void stopGame(){
mainTimer.stop();
}
public void startGame(){
mainTimer.start();
}
public void keyPressed(KeyEvent e) {
snake.onMove(e.getKeyCode());
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void actionPerformed(ActionEvent arg0) {
renderer.moveForward();
}
public Snake getSnake(){
return snake;
}
View class:
class Renderer extends JFrame {
private final int WIDTH = 500;
private final int HEIGHT = 300;
private Snake snake;
public int LevelConst;
private Controller controller;
public JPanel pamel1, panel2;
public JButton[] ButtonBody = new JButton[200];
public JButton bonusfood;
public JTextArea textArea;
public Fruit fruit;
public int score;
public Random random = new Random();
public JMenuBar mybar;
public JMenu game, help, levels;
public void initializeValues() {
score = 0;
}
Renderer(Controller controller) {
super("Snake: Demo");
this.controller = controller;
snake = controller.getSnake();
fruit = new Fruit();
setBounds(200, 200, 506, 380);
creatbar();
initializeValues();
// GUI
pamel1 = new JPanel();
panel2 = new JPanel();
// Scoreboard
setResizable(false);
textArea = new JTextArea("Счет : " + score);
textArea.setEnabled(false);
textArea.setBounds(400, 400, 100, 100);
textArea.setBackground(Color.GRAY);
// Eating and growing up
bonusfood = new JButton();
bonusfood.setEnabled(false);
//
createFirstSnake();
pamel1.setLayout(null);
panel2.setLayout(new GridLayout(0, 1));
pamel1.setBounds(0, 0, WIDTH, HEIGHT);
pamel1.setBackground(Color.GRAY);
panel2.setBounds(0, HEIGHT, WIDTH, 30);
panel2.setBackground(Color.black);
panel2.add(textArea); // will contain score board
// end of UI design
getContentPane().setLayout(null);
getContentPane().add(pamel1);
getContentPane().add(panel2);
show();
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void createFirstSnake() {
for (int i = 0; i < 3; i++) {
ButtonBody[i] = new JButton(" " + i);
ButtonBody[i].setEnabled(false);
pamel1.add(ButtonBody[i]);
ButtonBody[i].setBounds(snake.x[i], snake.y[i], 10, 10);
snake.x[i + 1] = snake.x[i] - 10;
snake.y[i + 1] = snake.y[i];
}
}
// Creating of menu bar
public void creatbar() {
mybar = new JMenuBar();
game = new JMenu("Game");
JMenuItem newgame = new JMenuItem("New Game");
JMenuItem exit = new JMenuItem("Exit");
newgame.addActionListener(e -> reset());
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
game.add(newgame);
game.addSeparator();
game.add(exit);
mybar.add(game);
levels = new JMenu("Level");
JMenuItem easy = new JMenuItem("Easy");
easy.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
LevelConst = 0;
}
});
JMenuItem middle = new JMenuItem("Medium");
middle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
LevelConst = 1;
}
});
JMenuItem hard = new JMenuItem("Hard");
hard.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
LevelConst = 2;
}
});
levels.add(easy);
levels.addSeparator();
levels.add(middle);
levels.addSeparator();
levels.add(hard);
mybar.add(levels);
help = new JMenu("Help");
JMenuItem creator = new JMenuItem("There must be a button");
creator.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(pamel1, "Random text");
}
});
help.add(creator);
mybar.add(help);
setJMenuBar(mybar);
}
void reset() {
initializeValues();
pamel1.removeAll();
controller.stopGame();
createFirstSnake();
textArea.setText("Score: " + score);
controller.startGame();
}
void growup() {
ButtonBody[snake.getLength()] = new JButton(" " + snake.getLength());
ButtonBody[snake.getLength()].setEnabled(false);
pamel1.add(ButtonBody[snake.getLength()]);
ButtonBody[snake.getLength()].setBounds(snake.getPointBody()[snake.getLength() - 1].x, snake.getPointBody()[snake.getLength() - 1].y, 10, 10);
snake.setLength(snake.getLength() + 1);
}
void moveForward() {
for (int i = 0; i < snake.getLength(); i++) {
snake.getPointBody()[i] = ButtonBody[i].getLocation();
}
snake.x[0] += snake.getDirectionX();
snake.y[0] += snake.getDirectionY();
ButtonBody[0].setBounds(snake.x[0], snake.y[0], 10, 10);
for (int i = 1; i < snake.getLength(); i++) {
ButtonBody[i].setLocation(snake.getPointBody()[i - 1]);
}
if (snake.x[0] == WIDTH) {
controller.stopGame();
} else if (snake.x[0] == 0) {
controller.stopGame();
} else if (snake.y[0] == HEIGHT) {
controller.stopGame();
} else if (snake.y[0] == 0) {
controller.stopGame();
}
createFruit();
collisionFruit();
pamel1.repaint();
}
private void collisionFruit() {
if (fruit.isFood()) {
if (fruit.getPoint().x == snake.x[0] && fruit.getPoint().y == snake.y[0]) {
pamel1.remove(bonusfood);
score += 1;
growup();
textArea.setText("Score: " + score);
fruit.setFood(false);
}
}
}
private void createFruit() {
if (!fruit.isFood()) {
pamel1.add(bonusfood);
bonusfood.setBounds((10 * random.nextInt(50)), (10 * random.nextInt(25)), 10,
10);
fruit.setPoint(bonusfood.getLocation());
fruit.setFood(true);
}
}
Class Model: Fruit:
public class Fruit {
private Point point;
private boolean food;
public Fruit() {
point = new Point();
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public boolean isFood() {
return food;
}
public void setFood(boolean food) {
this.food = food;
}
Class Model: Snake:
public class Snake {
private Point[] pointBody = new Point[300];
private int length;
private boolean isLeft;
private boolean isRight;
private boolean isUp;
private boolean isDown;
private int directionX;
private int directionY;
public int[] x = new int[300];
public int[] y = new int[300];
public Snake() {
isLeft = false;
isRight = true;
isUp = true;
isDown = true;
setDirectionX(10);
setDirectionY(0);
length = 3;
y[0] = 100;
x[0] = 150;
}
public void onMove(int side) {
switch (side) {
case KeyEvent.VK_LEFT:
if (isLeft) {
setDirectionX(-10);
setDirectionY(0);
isRight = false;
isUp = true;
isDown = true;
}
break;
case KeyEvent.VK_UP:
if (isUp) {
setDirectionX(0);
setDirectionY(-10);
isDown = false;
isRight = true;
isLeft = true;
}
break;
case KeyEvent.VK_DOWN:
if (isDown) {
setDirectionX(0);
setDirectionY(+10);
isUp = false;
isRight = true;
isLeft = true;
}
break;
case KeyEvent.VK_RIGHT:
if (isRight) {
setDirectionX(+10);
setDirectionY(0);
isLeft = false;
isUp = true;
isDown = true;
}
break;
default:
break;
}
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Point[] getPointBody() {
return pointBody;
}
public void setPointBody(Point[] pointBody) {
this.pointBody = pointBody;
}
public int getDirectionX() {
return directionX;
}
public void setDirectionX(int directionX) {
this.directionX = directionX;
}
public int getDirectionY() {
return directionY;
}
public void setDirectionY(int directionY) {
this.directionY = directionY;
}
Main:
public class Main {
public static void main(String[] args) {
new Controller();
}
}
Make a property change listener in Controller:
public PropertyChangeListener getViewListener() {
return new ViewListener();
}
private class ViewListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("Level is "+ evt.getNewValue());
//use level
}
}
Invoke createbar by: creatbar(controller.getViewListener());
And use listener :
public void creatbar(PropertyChangeListener listener) {
mybar = new JMenuBar();
mybar.addPropertyChangeListener(listener);//add listener to menu bar
game = new JMenu("Game");
JMenuItem newgame = new JMenuItem("New Game");
JMenuItem exit = new JMenuItem("Exit");
newgame.addActionListener(e -> reset());
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
game.add(newgame);
game.addSeparator();
game.add(exit);
mybar.add(game);
levels = new JMenu("Level");
JMenuItem easy = new JMenuItem("Easy");
easy.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mybar.firePropertyChange("Level", LevelConst, 0); //use listener
LevelConst = 0;
}
});
JMenuItem middle = new JMenuItem("Medium");
middle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mybar.firePropertyChange("Level", LevelConst, 1);
LevelConst = 1;
}
});
JMenuItem hard = new JMenuItem("Hard");
hard.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mybar.firePropertyChange("Level", LevelConst, 2);
LevelConst = 2;
}
});
levels.add(easy);
levels.addSeparator();
levels.add(middle);
levels.addSeparator();
levels.add(hard);
mybar.add(levels);
help = new JMenu("Help");
JMenuItem creator = new JMenuItem("There must be a button");
creator.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(pamel1, "Random text");
}
});
help.add(creator);
mybar.add(help);
setJMenuBar(mybar);
}
In my code I have the following statements inside my Mouse Listener
class CustomMouseListener extends MouseAdapter {
Menu m;
MenuDesign mD;
SlideInLayout s;
public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
this.m = m;
this.mD = mD;
this.s = s;
}
public void mousePressed(MouseEvent mE) {
if(m != null && mD != null) {
if(mE.getSource() == mD) {
if(mD.getInOut()) {
mD.setFade(false);
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
runSwap.start();
try {
runSwap.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
mD.setFade(true);
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getOverlay());
}
}).start();
}
mD.fade();
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
Ideally I would like my runnable animation to run at the same time as mD.fade(); so to do this I would write
Thread runSwap = new Thread(new Runnable() {
public void run() {
s.show(m.getFirstPanel());
}
});
instead of this.
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
However this causes the end result of the animation to happen instantly. The other problem is that when I need to repaint the screen at the end as it ends up like the first frame in the picture below instead of the second frame however using the repaint() and validate() methods causes the animation in the runnable not to happen and the end result just appears again, even after a .join() is used with the thread.
I would appreciate any help in fixing the problem
Full Code if needed
package menutest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Menu {
JFrame myMainWindow = new JFrame("Menu Slide Test");
GridBagConstraints c;
MyFirstPanel fP;
MyOverlay oL;
MyMenuButton mB;
GridBagLayout baseLayout;
GridBagLayout overlayLayout;
SlideInLayout slideIn = new SlideInLayout();
JPanel tempHold = new JPanel(slideIn);
/* Height and Width */
int height = 600;
int width = 600;
private void runGUI(Menu m) {
myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myMainWindow.setLayout(new GridBagLayout());
setContraints();
createPanels(m);
myMainWindow.getContentPane().add(tempHold, c);
myMainWindow.getContentPane().add(mB, c, 0);
slideIn.show(fP);
myMainWindow.pack();
myMainWindow.setVisible(true);
myMainWindow.setLocationRelativeTo(null);
}
private void setContraints() {
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
}
private void createPanels(Menu m) {
createFirstPanel(m);
createOverlay(m);
createMenuButton(m);
tempHold.add(fP);
tempHold.add(oL);
}
private void createFirstPanel(Menu m) {
baseLayout = new GridBagLayout();
fP = new MyFirstPanel(baseLayout, m);
}
private void createOverlay(Menu m) {
overlayLayout = new GridBagLayout();
oL = new MyOverlay(overlayLayout, m);
}
private void createMenuButton(Menu m) {
mB = new MyMenuButton(m);
}
public static void main(String[] args) {
Menu menu = new Menu();
menu.runGUI(menu);
}
/* Getters and Setters */
public JPanel getFirstPanel() {
return fP;
}
public JPanel getOverlay() {
return oL;
}
public JFrame getMainWindow() {
return myMainWindow;
}
public int myGetHeight() {
return height;
}
public int myGetWidth() {
return width;
}
public SlideInLayout getSlide() {
return slideIn;
}
}
class MyFirstPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 2897488186622284953L;
MyFirstPanel(GridBagLayout layout, Menu mM) {
setLayout(layout);
setBackground(Color.RED);
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
}
}
class MyOverlay extends JPanel {
/**
*
*/
private static final long serialVersionUID = 4595122972358754430L;
MyOverlay(GridBagLayout layout, Menu mM) {
setLayout(layout);
setBackground(Color.GREEN);
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
}
}
class MyMenuButton extends JPanel {
/**
*
*/
private static final long serialVersionUID = -4986432081497113479L;
MyMenuButton(Menu mM) {
setLayout(null);
setBackground(new Color(0, 0, 0, 0));
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
add(new MenuDesign(15, 15, mM, mM.myGetWidth()));
}
}
class MenuDesign extends JLabel {
/**
*
*/
private static final long serialVersionUID = 2255075501909089222L;
boolean inOut = false; //true for fade out, false for fade in
//starts on false because it changes to true on first click on label
float alpha = 1F;
Timer timer;
//Start Points
double[] r1Points = {0, 6.67766953};
double[] r2Points = {0, 16.67766953};
double[] r3Points = {0, 26.67766953};
//Current Points
double[] curR1Points = {r1Points[0], r1Points[1]};
double[] curR3Points = {r3Points[0], r3Points[1]};
//End Points
double[] endR1Points = {2.828427125, 0};
double[] endR3Points = {0, 35.35533906};
//Angles
double ang1 = 0;
double ang2 = 0;
//Height and width of component to make it as efficient as possible
int width = 50;
int height = 40;
MenuDesign(int x, int y, Menu m, int width) {
setBounds(x, y, this.width, height);
setCursor(new Cursor(Cursor.HAND_CURSOR));
addMouseListener(new CustomMouseListener(m, this, m.getSlide()));
timer = new Timer(5, new CustomActionListener(m, this, r1Points, r3Points, endR1Points, endR3Points, x, width - 60));
}
public void fade() {
timer.start();
System.out.println("Start");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(Color.WHITE);
Rectangle2D r1 = new Rectangle2D.Double(curR1Points[0], curR1Points[1], width, 4);
Rectangle2D r2 = new Rectangle2D.Double(r2Points[0], r2Points[1], width, 4);
Rectangle2D r3 = new Rectangle2D.Double(curR3Points[0], curR3Points[1], width, 4);
//r1
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1F));
g2d.rotate(Math.toRadians(ang1), endR1Points[0], endR1Points[1]);
g2d.fill(r1);
//r3
g2d.rotate(Math.toRadians(-ang1), endR1Points[0], endR1Points[1]);
g2d.rotate(Math.toRadians(-ang2), endR3Points[0], endR3Points[1]);
g2d.fill(r3);
//r2
g2d.rotate(Math.toRadians(ang2), endR3Points[0], endR3Points[1]);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g2d.fill(r2);
}
public Timer getTimer() {
return timer;
}
public float getAlpha() {
return alpha;
}
public void setAplha(float a) {
this.alpha = a;
if(a < 0) {
setAplha(0F);
}
if(a > 1) {
setAplha(1F);
}
validate();
repaint();
}
public boolean getInOut() {
return inOut;
}
public void setFade(boolean b) {
this.inOut = b;
}
public double[] getTransR1() {
return curR1Points;
}
public double[] getTransR3() {
return curR3Points;
}
public void setTransR1(double[] d) {
this.curR1Points = d;
}
public void setTransR3(double[] d) {
this.curR3Points = d;
}
public void setAng1(double d) {
this.ang1 = d;
}
public void setAng2(double d) {
this.ang2 = d;
}
public void stopTheTimer(int i) {
if(i == 101) {
timer.stop();
System.out.println("stop");
}
}
}
class CustomActionListener implements ActionListener {
Menu m;
MenuDesign mD;
MyFirstPanel mFP;
double[] a, b, c, d;
double incrementX1;
double incrementY1;
double incrementX2;
double incrementY2;
double incrementX3;
double incrementY3;
double incrementX4;
double incrementY4;
double angInc = 45.0 / 100.0;
double moveInc;
int i = 0;
int startPoint;
public CustomActionListener(Menu m, MyFirstPanel mFP) {
this.m = m;
this.mFP = mFP;
}
public CustomActionListener(Menu m, MenuDesign mD, double[] a, double[] b, double[] c, double[] d, int startPoint, int endPoint) {
this.m = m;
this.mD = mD;
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.startPoint = startPoint;
//Increments
int incTot = 100;
//r1 increments
incrementX1 = (c[0] - a[0]) / incTot;
incrementY1 = (c[1] - a[1]) / incTot;
incrementX2 = (a[0] - c[0]) / incTot;
incrementY2 = (a[1] - c[1]) / incTot;
//r2 increments
incrementX3 = (d[0] - b[0]) / incTot;
incrementY3 = (d[1] - b[1]) / incTot;
incrementX4 = (b[0] - d[0]) / incTot;
incrementY4 = (b[1] - d[1]) / incTot;
//Movement
moveInc = (endPoint - startPoint) / incTot;
}
public void actionPerformed(ActionEvent e) {
if(m != null && mD != null) {
if(e.getSource() == mD.getTimer()) {
if(mD.getInOut()) { //Start of transform into x
//r1
mD.setTransR1(new double[] {a[0] + (i * incrementX1), a[1] + (i * incrementY1)});
mD.setAng1(i * angInc);
//r2
mD.setAplha(mD.getAlpha() - 0.02F);
//r3
mD.setTransR3(new double[] {b[0] + (i * incrementX3), b[1] + (i * incrementY3)});
mD.setAng2(i * angInc);
//Location
mD.setLocation((int) (startPoint + (i * moveInc)), startPoint);
i++;
} else { //Start of transform into three lines
//r1
mD.setTransR1(new double[] {c[0] + (i * incrementX2), c[1] + (i * incrementY2)});
mD.setAng1((100 - i) * angInc);
//r2
if(i >= 50) {
mD.setAplha(mD.getAlpha() + 0.02F);
}
//r3
mD.setTransR3(new double[] {d[0] + (i * incrementX4), d[1] + (i * incrementY4)});
mD.setAng2((100 - i) * angInc);
//Location
mD.setLocation((int) (540 + (i * -moveInc)), 15);
i++;
}
if(i == 101) {
mD.stopTheTimer(i);
i = 0;
}
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
class CustomMouseListener extends MouseAdapter {
Menu m;
MenuDesign mD;
SlideInLayout s;
public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
this.m = m;
this.mD = mD;
this.s = s;
}
public void mousePressed(MouseEvent mE) {
if(m != null && mD != null) {
if(mE.getSource() == mD) {
if(mD.getInOut()) {
mD.setFade(false);
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
runSwap.start();
try {
runSwap.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
mD.setFade(true);
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getOverlay());
}
}).start();
}
mD.fade();
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
/////////////// Below here is not my code
class SlideInLayout implements LayoutManager {
private Component focusedComponent;
#Override
public void addLayoutComponent(String name, Component comp) {}
#Override
public void removeLayoutComponent(Component comp) {}
#Override
public void layoutContainer(Container parent) {
setSizes(parent);
if (hasFocusedComponent()) {
focusedComponent.setVisible(true);
}
}
private void setSizes(Container parent) {
Insets insets = parent.getInsets();
int maxWidth = parent.getWidth() - (insets.left + insets.right);
int maxHeight = parent.getHeight() - (insets.top + insets.bottom);
for (Component component : parent.getComponents()) {
component.setBounds(0, 0, maxWidth, maxHeight);
}
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return new Dimension(0, 0);
}
#Override
public Dimension preferredLayoutSize(Container parent) {
Dimension preferredSize = new Dimension(0, 0);
if (hasFocusedComponent()) {
preferredSize = focusedComponent.getPreferredSize();
}
else if (parent.getComponentCount() > 0) {
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension componentSize = component.getPreferredSize();
maxWidth = Math.max(maxWidth, componentSize.width);
maxHeight = Math.max(maxHeight, componentSize.height);
}
preferredSize = new Dimension(maxWidth, maxHeight);
}
return preferredSize;
}
private boolean hasFocusedComponent() {
return focusedComponent != null;
}
public void show(Component component) {
if (hasFocusedComponent())
swap(focusedComponent, component);
focusedComponent = component;
}
private void swap(Component transitionOut, Component transitionIn) {
new SwapTimerAction(transitionOut, transitionIn).start();
}
private class SwapTimerAction implements ActionListener {
private Timer timer;
private Component transitionOut;
private Component transitionIn;
private static final int tick = 16; //16ms
private static final int speed = 50;
public SwapTimerAction(Component transitionOut, Component transitionIn) {
this.transitionOut = transitionOut;
this.transitionIn = transitionIn;
}
public void start() {
Container container = transitionOut.getParent();
container.setComponentZOrder(transitionOut, 1);
container.setComponentZOrder(transitionIn, 0);
transitionIn.setBounds(-transitionOut.getWidth(), 0, transitionOut.getWidth(), transitionOut.getHeight());
timer = new Timer(tick, this);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
int newX = Math.min(transitionIn.getX() + speed, transitionOut.getX());
transitionIn.setLocation(newX, 0);
if (newX == transitionOut.getX()) {
timer.stop();
}
}
}
}
First it will be a little longer because I want to show all the code I have done until now, so excuse me..
This is my first time in java.
I'm trying to build an aquarium with fish and jellyfish drawing and use threads.
When I try to add animal I want to paint it but without success, I built PaintComponent method but when I try to use repaint I can not draw..
What am I missing?
It looks that way, when I click on Add Animal window opens , I choose the values and after I click OK, need to draw the animal
I hope that the rest of what I did was okay .. thank you so much for helping!
paintComponent and repaint is at AquaPanel Class.
public class AquaFrame extends JFrame {
private AquaPanel mPanel;
private JLabel label1;
private ImageIcon icon;
private BufferedImage imag;
public AquaFrame() {
super("my Aquarium");
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(700, 600);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
mPanel = new AquaPanel(getGraphics());
add(mPanel);
}
public void buildFrame(){
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu file = new JMenu("File");
menuBar.add(file);
JMenuItem exItem = new JMenuItem("Exit");
file.add(exItem);
exItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JMenu background = new JMenu("Background");
menuBar.add(background);
JMenuItem blue = new JMenuItem("Blue");
blue.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(Color.BLUE);
}
});
JMenuItem none = new JMenuItem("None");
none.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(null);
}
});
JMenuItem image = new JMenuItem("Image");
image.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
imag = ImageIO.read(new File("aquarium_background.jpg"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
background.add(image);
background.add(blue);
background.add(none);
JMenu help = new JMenu("Help");
JMenuItem helpItem = new JMenuItem("help");
helpItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"GUI # Threads");
}
});
menuBar.add(help);
help.add(helpItem);
setVisible(true);
}
public void paint(Graphics g){
g.drawImage(imag, 0, 0, null);
}
public static void main(String[] args) {
AquaFrame mFrame = new AquaFrame();
mFrame.buildFrame();
}
}
/******************************************/
public class AquaPanel extends JPanel {
private JFrame infoTableFrame;
private JTable infoTable;
private Set<Swimmable > swimmables = new HashSet<Swimmable>();
private AddAnimalDialog animalDialog;
private int totalEatCounter;
private Graphics g;
public AquaPanel(Graphics g) {
this.g = g;
totalEatCounter = 0;
infoTableFrame = new JFrame();
infoTableFrame.setVisible(false);
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.PAGE_END;
constraints.weighty = 1;
JButton btAdd = new JButton("Add Animal");
btAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() >= 5)
{
JOptionPane.showMessageDialog(null, "You can't have more than 5 animals at the same time.");
}
else
{
animalDialog = new AddAnimalDialog(AquaPanel.this);
animalDialog.setVisible(true);
}
}
});
JButton btSleep = new JButton("Sleep");
btSleep.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setSuspend();
}
}
});
JButton btWakeup = new JButton("Wake Up");
btWakeup.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setResume();
}
}
});
JButton btRst = new JButton("Reset");
btRst.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.kill();
}
swimmables.clear();
}
});
JButton btFood = new JButton("Food");
btFood.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() > 0)
{
CyclicBarrier barrier = new CyclicBarrier(swimmables.size());
for (Swimmable swimmable : swimmables)
{
swimmable.setBarrier(barrier);
swimmable.setFood(true);
}
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3));
g2.setColor(Color.red);
g2.drawArc(getWidth() / 2, getHeight() / 2 - 5, 10, 10, 30, 210);
g2.drawArc(getWidth()/2, getHeight()/2+5, 10, 10, 180, 270);
g2.setStroke(new BasicStroke(1));
}
}
});
JButton btInfo = new JButton("Info");
btInfo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showInfoTable();
}
});
JButton btExit = new JButton("Exit");
btExit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
add(btAdd,constraints);
add(btSleep,constraints);
add(btWakeup,constraints);
add(btRst,constraints);
add(btFood,constraints);
add(btInfo,constraints);
add(btExit,constraints);
}
public void showInfoTable(){
if (infoTableFrame.isVisible())
{
infoTableFrame.remove(infoTable);
infoTableFrame.setVisible(false);
}
else
{
String[] col = {"Animal","Color","Size","Hor.speed","Ver.speed","Eat counter"};
String[][] data = new String[swimmables.size()][col.length];
int i=0;
for (Swimmable swimmable : swimmables)
{
data[i][0] = swimmable.getAnimalName();
data[i][1] = swimmable.getColor();
data[i][2] = "" + swimmable.getSize();
data[i][3] = "" + swimmable.getHorSpeed();
data[i][4] = "" + swimmable.getVerSpeed();
data[i][5] = "" + swimmable.getEatCount();
++i;
}
infoTable = new JTable(data, col);
//TODO - not overriding values
JScrollPane jPane = new JScrollPane(infoTable);
infoTableFrame.add(jPane, BorderLayout.CENTER);
infoTableFrame.setSize(300, 150);
infoTableFrame.setVisible(true);
}
}
public void addAnimal(Swimmable animal)
{
animal.setAquaPanel(this);
swimmables.add(animal);
animal.run();
//myrepaint();
/**********************************/
repaint();
/**********************************/
}
public void onEatFood(Swimmable eater)
{
eater.eatInc();
++totalEatCounter;
for (Swimmable swimmable : swimmables)
{
swimmable.setFood(false);
}
}
/*public void myrepaint()
{
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}*/
/************************************************/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}
/*********************************************/
}
public abstract class Swimmable extends Thread {
protected AquaPanel aquaPanel;
protected boolean isFood;
protected boolean isSuspended;
protected int horSpeed;
protected int verSpeed;
protected int x_dir, y_dir;
protected int eatCount;
protected CyclicBarrier barrier;
protected int x0, y0;
protected boolean isAlive;
public Swimmable() {
horSpeed = 0;
verSpeed = 0;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
public Swimmable(int hor, int ver) {
horSpeed = hor;
verSpeed = ver;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
#Override
public void run() {
isAlive = true;
while (isAlive) {
try {
sleep(10);
if (isSuspended)
{
wait();
}
else
{
if (isFood)
{
barrier.await();
updateFrontsTowardsFood();
if (isNearFood())
{
aquaPanel.onEatFood(this);
}
}
else
{
updateFronts();
}
//aquaPanel.myrepaint();
aquaPanel.repaint();
}
}
catch (Exception e)
{
//TODO - handle exception
}
}
}
public void kill()
{
isAlive = false;
}
public int getHorSpeed() {
return horSpeed;
}
public int getVerSpeed() {
return verSpeed;
}
public void setHorSpeed(int hor) {
horSpeed = hor;
}
public void setVerSpeed(int ver) {
verSpeed = ver;
}
abstract public int getSize();
abstract public String getColor();
public void setSuspend()
{
isSuspended = true;
}
public void setResume()
{
isSuspended = false;
}
public void eatInc()
{
++eatCount;
}
public int getEatCount()
{
return eatCount;
}
public void setBarrier(CyclicBarrier b)
{
barrier = b;
}
public void setFood(boolean isFood)
{
this.isFood = isFood;
}
public void setAquaPanel(AquaPanel panel)
{
aquaPanel = panel;
x0 = aquaPanel.getWidth() / 2;
y0 = aquaPanel.getHeight() / 2;
}
abstract public String getAnimalName();
abstract public void drawAnimal(Graphics g);
abstract protected void updateFronts();
abstract protected void updateFrontsTowardsFood();
abstract protected boolean isNearFood();
}
public class Fish extends Swimmable {
protected int x_front , y_front;
private int size;
private Color color;
public Fish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
g.setColor(color);
if (x_dir == 1) // fish swims to right side
{
// Body of fish
g.fillOval(x_front - size, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front - size - size / 4, x_front - size - size / 4, x_front - size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(),255 - color.getGreen(),255- color .getBlue()));
g2.fillOval(x_front-size/5, y_front-size/10, size/10, size/10);
//Mouth of fish
if(size>70)
g2.setStroke(new BasicStroke(3));
else if(size>30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front-size/10, y_front+size/10);
g2.setStroke(new BasicStroke(1));
}
else // fish swims to left side
{
// Body of fish
g.fillOval(x_front, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front + size + size / 4, x_front + size + size / 4, x_front + size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()));
g2.fillOval(x_front+size/10, y_front-size/10, size/10, size/10);
// Mouth of fish
if (size > 70)
g2.setStroke(new BasicStroke(3));
else if (size > 30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front + size / 10, y_front + size / 10);
g2.setStroke(new BasicStroke(1));
}
}
public String getAnimalName() {
return "Fish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
protected void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class Jellyfish extends Swimmable {
private int x_front , y_front;
private int size;
private Color color;
public Jellyfish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
int numLegs;
if (size < 40)
numLegs = 5;
else if (size < 80)
numLegs = 9;
else
numLegs = 12;
g.setColor(color);
g.fillArc(x_front - size / 2, y_front - size / 4, size, size / 2, 0, 180);
for (int i = 0; i < numLegs; i++)
g.drawLine(x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front,
x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front + size / 3);
}
public String getAnimalName() {
return "Jellyfish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
public void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class AddAnimalDialog extends JDialog {
private JButton btOk, btCancel;
private JTextField tfSize, tfHspeed, tfVspeed;
private ButtonGroup groupType, groupColor;
private JRadioButton rbFish, rbJellyfish, rbRed, rbGreen, rbOrange;
JPanel panel;
public AddAnimalDialog(AquaPanel aquaPanel) {
this.setLayout(new FlowLayout());
panel = new JPanel();
panel.setLayout(new GridLayout(10, 20));
panel.add(new JLabel("Size(20-320): "));
panel.add(tfSize = new JTextField());
panel.add(new JLabel("Horizontal speed(1-10): "));
panel.add(tfHspeed = new JTextField());
panel.add(new JLabel("Vertical speed(1-10): "));
panel.add(tfVspeed = new JTextField());
panel.add(new JLabel("Type: "));
panel.add(new JLabel(" "));
panel.add(rbFish = new JRadioButton("fish"));
panel.add(rbJellyfish = new JRadioButton("jellyfish"));
panel.add(new JLabel("Color: "));
panel.add(new JLabel(" "));
panel.add(rbRed = new JRadioButton("Red"));
panel.add(rbGreen = new JRadioButton("Green"));
panel.add(rbOrange = new JRadioButton("Orange"));
// Group the radio buttons.
groupType = new ButtonGroup();
groupType.add(rbFish);
groupType.add(rbJellyfish);
rbFish.setSelected(true);
groupColor = new ButtonGroup();
groupColor.add(rbRed);
groupColor.add(rbGreen);
groupColor.add(rbOrange);
rbRed.setSelected(true);
panel.add(new JLabel(""));
panel.add(btOk = new JButton("OK"));
panel.add(btCancel = new JButton("Cancel"));
this.add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.pack();
this.btOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
int size = Integer.parseInt(tfSize.getText());
int hSpeed = Integer.parseInt(tfHspeed.getText());
int vSpeed = Integer.parseInt(tfVspeed.getText());
if (checkValues(size, hSpeed, vSpeed)) {
Color clr = Color.RED;
if (rbRed.isSelected()) {
clr = Color.RED;
} else if (rbGreen.isSelected()) {
clr = Color.GREEN;
} else if (rbOrange.isSelected()) {
clr = Color.ORANGE;
} else {
JOptionPane.showMessageDialog(null, "You must choose a color!");
}
if (rbFish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Fish(clr, size, hSpeed, vSpeed));
} else if (rbJellyfish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Jellyfish(clr, size, hSpeed, vSpeed));
} else {
JOptionPane.showMessageDialog(null, "You must choose animal type!");
}
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "One of the number values has wrong format, please check it");
}
}
});
this.btCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
System.out.println("Click the Close button if you want to stop adding windows");
}
});
}
private boolean checkValues(int size, int hspeed, int vspeed) {
if ((size > 320 || size < 20) || (hspeed < 1 || hspeed > 10) || (vspeed < 1 || vspeed > 10)) {
JOptionPane.showMessageDialog(null, "One of the values is out of bounds, please follow the restrictions.");
return false;
}
return true;
}
}
There are a number of basic problems...
The main problem is with your Swimmable run method, it is blocking the Event Dispatching Thread, preventing it from been able to respond to UI events, including repaint events. See Concurrency in Java for more details.
You should NEVER use getGraphics, apart from been able to return null, anything you paint to it is painted outside of the normal paint cycle and will painted over the next time component is repainted. See Painting in AWT and Swing and Performing Custom Painting for more details.
Your current approach won't scale well, the more fish you add, the more resources they will consume and will affect the ability for the program to keep up with all the different changes and repaint requests.
A better solution would be to have a single "update" loop which takes care of telling each of the Swimmables that it needs to update and then schedules a single repaint each cycle. Personally, I'd start with a Swing Timer as it "ticks" within the EDT, making it much safer to modify the state of the objects which the paintComponent method needs.
See How to use Swing Timers for more details
I would suggest having a look at this, which basically describes what you're trying to do and what I'm suggesting you should do instead
Try calling repaint in your JFrame class after calling the addAnimal method. There is also revalidate() method in there as well and their difference is in this article: Java Swing revalidate() vs repaint()
Good morning,
First my mission is want to make my JTabbedPane Drag-out to window and create new JFrame. Illustration is like NetBeans / SublimeText,
I Found reference for drag & drop JTabbedPane in https://stackoverflow.com/a/61982 , It is success to drag and drop Tab from 1 JTabbedPane or 2/many JTabbedPane
now what i want is whenever drag-out tab the document, it automatic create new Frame and insert tab to new jtabbedPane. And If the jtabbedpane is empty / no-component, the jframe is automatic closed.
--
"Shorted Question"
Can i have, when I drag tab (from jtabbedpane) to desktop/outside JFrame and automatic create JFrame & Tabbedpane inside then placed the tab there ?
Also When the tab drag&drop and there is none component in jtabbedpane, it's can automatic dispose the JFrame/JTabbedPane.
"Very Shorted Question"
How can i get my JTabbedPane like Netbeans TabbedPane Document Editor ?
--
I Include the file my latest Modified Drag & Drop JTabbedPane with Close Button.
Thank you very much. R.
public class DnDCloseButtonTabbedPane extends JTabbedPane {
public static final long serialVersionUID = 1L;
private static final int LINEWIDTH = 3;
private static final String NAME = "TabTransferData";
private final DataFlavor FLAVOR = new DataFlavor(
DataFlavor.javaJVMLocalObjectMimeType, NAME);
private static GhostGlassPane s_glassPane = new GhostGlassPane();
private boolean m_isDrawRect = false;
private final Rectangle2D m_lineRect = new Rectangle2D.Double();
private final Color m_lineColor = new Color(0, 100, 255);
private TabAcceptor m_acceptor = null;
private final DropTarget dropTarget;
private final ImageIcon icon;
private final Dimension buttonSize;
public DnDCloseButtonTabbedPane() {
super();
final DragSourceListener dsl = new DragSourceListener() {
#Override
public void dragEnter(DragSourceDragEvent e) {
e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
}
#Override
public void dragExit(DragSourceEvent e) {
e.getDragSourceContext()
.setCursor(DragSource.DefaultMoveNoDrop);
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
s_glassPane.setPoint(new Point(-1000, -1000));
s_glassPane.repaint();
// System.out.println(e);
}
#Override
public void dragOver(DragSourceDragEvent e) {
//e.getLocation()
//This method returns a Point indicating the cursor location in screen coordinates at the moment
TabTransferData data = getTabTransferData(e);
if (data == null) {
e.getDragSourceContext().setCursor(
DragSource.DefaultMoveNoDrop);
return;
} // if
/*
Point tabPt = e.getLocation();
SwingUtilities.convertPointFromScreen(tabPt, DnDTabbedPane.this);
if (DnDTabbedPane.this.contains(tabPt)) {
int targetIdx = getTargetTabIndex(tabPt);
int sourceIndex = data.getTabIndex();
if (getTabAreaBound().contains(tabPt)
&& (targetIdx >= 0)
&& (targetIdx != sourceIndex)
&& (targetIdx != sourceIndex + 1)) {
e.getDragSourceContext().setCursor(
DragSource.DefaultMoveDrop);
return;
} // if
e.getDragSourceContext().setCursor(
DragSource.DefaultMoveNoDrop);
return;
} // if
*/
e.getDragSourceContext().setCursor(
DragSource.DefaultMoveDrop);
}
public void dragDropEnd(DragSourceDropEvent e) {
m_isDrawRect = false;
m_lineRect.setRect(0, 0, 0, 0);
// m_dragTabIndex = -1;
if (hasGhost()) {
s_glassPane.setVisible(false);
s_glassPane.setImage(null);
}
}
#Override
public void dropActionChanged(DragSourceDragEvent e) {
}
};
final DragGestureListener dgl = new DragGestureListener() {
#Override
public void dragGestureRecognized(DragGestureEvent e) {
// System.out.println("dragGestureRecognized");
Point tabPt = e.getDragOrigin();
int dragTabIndex = indexAtLocation(tabPt.x, tabPt.y);
if (dragTabIndex < 0) {
return;
} // if
initGlassPane(e.getComponent(), e.getDragOrigin(), dragTabIndex);
try {
e.startDrag(DragSource.DefaultMoveDrop,
new TabTransferable(DnDCloseButtonTabbedPane.this, dragTabIndex), dsl);
} catch (InvalidDnDOperationException idoe) {
idoe.printStackTrace();
}
}
};
//dropTarget =
dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE,
new CDropTargetListener(), true);
new DragSource().createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE, dgl);
m_acceptor = new TabAcceptor() {
#Override
public boolean isDropAcceptable(DnDCloseButtonTabbedPane a_component, int a_index) {
return true;
}
};
icon = new ImageIcon(getClass().getResource(Resource.ICON_16X16 + "delete.png"));
buttonSize = new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
#Override
public void addTab(String title, final Component component) {
JPanel tab = new JPanel(new BorderLayout());
tab.setOpaque(false);
JLabel label = new JLabel(title);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 4));
JButton button = new JButton(icon);
button.setPreferredSize(buttonSize);
button.setUI(new BasicButtonUI());
button.setContentAreaFilled(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
((DnDCloseButtonTabbedPane) component.getParent()).remove(component);
}
});
tab.add(label, BorderLayout.WEST);
tab.add(button, BorderLayout.EAST);
tab.setBorder(BorderFactory.createEmptyBorder(2, 1, 1, 1));
super.addTab(title, component);
setTabComponentAt(indexOfComponent(component), tab);
}
public TabAcceptor getAcceptor() {
return m_acceptor;
}
public void setAcceptor(TabAcceptor a_value) {
m_acceptor = a_value;
}
private TabTransferData getTabTransferData(DropTargetDropEvent a_event) {
try {
TabTransferData data = (TabTransferData) a_event.getTransferable().getTransferData(FLAVOR);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private TabTransferData getTabTransferData(DropTargetDragEvent a_event) {
try {
TabTransferData data = (TabTransferData) a_event.getTransferable().getTransferData(FLAVOR);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private TabTransferData getTabTransferData(DragSourceDragEvent a_event) {
try {
TabTransferData data = (TabTransferData) a_event.getDragSourceContext()
.getTransferable().getTransferData(FLAVOR);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private TabTransferData getTabTransferData(DragSourceDropEvent a_event) {
try {
TabTransferData data = (TabTransferData) a_event.getDragSourceContext()
.getTransferable().getTransferData(FLAVOR);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
class TabTransferable implements Transferable {
private TabTransferData m_data = null;
public TabTransferable(DnDCloseButtonTabbedPane a_tabbedPane, int a_tabIndex) {
m_data = new TabTransferData(DnDCloseButtonTabbedPane.this, a_tabIndex);
}
public Object getTransferData(DataFlavor flavor) {
return m_data;
// return DnDTabbedPane.this;
}
public DataFlavor[] getTransferDataFlavors() {
DataFlavor[] f = new DataFlavor[1];
f[0] = FLAVOR;
return f;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.getHumanPresentableName().equals(NAME);
}
}
class TabTransferData {
private DnDCloseButtonTabbedPane m_tabbedPane = null;
private int m_tabIndex = -1;
public TabTransferData() {
}
public TabTransferData(DnDCloseButtonTabbedPane a_tabbedPane, int a_tabIndex) {
m_tabbedPane = a_tabbedPane;
m_tabIndex = a_tabIndex;
}
public DnDCloseButtonTabbedPane getTabbedPane() {
return m_tabbedPane;
}
public void setTabbedPane(DnDCloseButtonTabbedPane pane) {
m_tabbedPane = pane;
}
public int getTabIndex() {
return m_tabIndex;
}
public void setTabIndex(int index) {
m_tabIndex = index;
}
}
private Point buildGhostLocation(Point a_location) {
Point retval = new Point(a_location);
// switch (getTabPlacement()) {
// case JTabbedPane.TOP: {
// retval.y = 1;
// retval.x -= s_glassPane.getGhostWidth() / 2;
// }
// break;
//
// case JTabbedPane.BOTTOM: {
// retval.y = getHeight() - 1 - s_glassPane.getGhostHeight();
// retval.x -= s_glassPane.getGhostWidth() / 2;
// }
// break;
//
// case JTabbedPane.LEFT: {
// retval.x = 1;
// retval.y -= s_glassPane.getGhostHeight() / 2;
// }
// break;
//
// case JTabbedPane.RIGHT: {
// retval.x = getWidth() - 1 - s_glassPane.getGhostWidth();
// retval.y -= s_glassPane.getGhostHeight() / 2;
// }
// break;
// } // switch
retval = SwingUtilities.convertPoint(DnDCloseButtonTabbedPane.this,
retval, s_glassPane);
return retval;
}
class CDropTargetListener implements DropTargetListener {
public void dragEnter(DropTargetDragEvent e) {
// System.out.println("DropTarget.dragEnter: " + DnDCloseButtonTabbedPane.this);
if (isDragAcceptable(e)) {
e.acceptDrag(e.getDropAction());
} else {
e.rejectDrag();
} // if
}
public void dragExit(DropTargetEvent e) {
// System.out.println("DropTarget.dragExit: " + DnDCloseButtonTabbedPane.this);
m_isDrawRect = false;
}
public void dropActionChanged(DropTargetDragEvent e) {
}
public void dragOver(final DropTargetDragEvent e) {
TabTransferData data = getTabTransferData(e);
if (getTabPlacement() == JTabbedPane.TOP
|| getTabPlacement() == JTabbedPane.BOTTOM) {
initTargetLeftRightLine(getTargetTabIndex(e.getLocation()), data);
} else {
initTargetTopBottomLine(getTargetTabIndex(e.getLocation()), data);
} // if-else
repaint();
if (hasGhost()) {
s_glassPane.setPoint(buildGhostLocation(e.getLocation()));
s_glassPane.repaint();
}
}
#Override
public void drop(DropTargetDropEvent a_event) {
// System.out.println("DropTarget.drop: " + DnDTabbedPane.this);
if (isDropAcceptable(a_event)) {
convertTab(getTabTransferData(a_event),
getTargetTabIndex(a_event.getLocation()));
a_event.dropComplete(true);
} else {
a_event.dropComplete(false);
} // if-else
m_isDrawRect = false;
repaint();
}
public boolean isDragAcceptable(DropTargetDragEvent e) {
Transferable t = e.getTransferable();
if (t == null) {
return false;
} // if
DataFlavor[] flavor = e.getCurrentDataFlavors();
if (!t.isDataFlavorSupported(flavor[0])) {
return false;
} // if
TabTransferData data = getTabTransferData(e);
if (DnDCloseButtonTabbedPane.this == data.getTabbedPane()
&& data.getTabIndex() >= 0) {
return true;
} // if
if (DnDCloseButtonTabbedPane.this != data.getTabbedPane()) {
if (m_acceptor != null) {
return m_acceptor.isDropAcceptable(data.getTabbedPane(), data.getTabIndex());
} // if
} // if
boolean transferDataFlavorFound = false;
for (DataFlavor transferDataFlavor : t.getTransferDataFlavors()) {
if (FLAVOR.equals(transferDataFlavor)) {
transferDataFlavorFound = true;
break;
}
}
if (transferDataFlavorFound == false) {
return false;
}
return false;
}
public boolean isDropAcceptable(DropTargetDropEvent e) {
Transferable t = e.getTransferable();
if (t == null) {
return false;
} // if
DataFlavor[] flavor = e.getCurrentDataFlavors();
if (!t.isDataFlavorSupported(flavor[0])) {
return false;
} // if
TabTransferData data = getTabTransferData(e);
if (DnDCloseButtonTabbedPane.this == data.getTabbedPane()
&& data.getTabIndex() >= 0) {
return true;
} // if
if (DnDCloseButtonTabbedPane.this != data.getTabbedPane()) {
if (m_acceptor != null) {
return m_acceptor.isDropAcceptable(data.getTabbedPane(), data.getTabIndex());
} // if
} // if
return false;
}
}
private boolean m_hasGhost = true;
public void setPaintGhost(boolean flag) {
m_hasGhost = flag;
}
public boolean hasGhost() {
return m_hasGhost;
}
/**
* returns potential index for drop.
*
* #param a_point point given in the drop site component's coordinate
* #return returns potential index for drop.
*/
private int getTargetTabIndex(Point a_point) {
boolean isTopOrBottom = getTabPlacement() == JTabbedPane.TOP
|| getTabPlacement() == JTabbedPane.BOTTOM;
// if the pane is empty, the target index is always zero.
if (getTabCount() == 0) {
return 0;
} // if
for (int i = 0; i < getTabCount(); i++) {
Rectangle r = getBoundsAt(i);
if (isTopOrBottom) {
r.setRect(r.x - r.width / 2, r.y, r.width, r.height);
} else {
r.setRect(r.x, r.y - r.height / 2, r.width, r.height);
} // if-else
if (r.contains(a_point)) {
return i;
} // if
} // for
Rectangle r = getBoundsAt(getTabCount() - 1);
if (isTopOrBottom) {
int x = r.x + r.width / 2;
r.setRect(x, r.y, getWidth() - x, r.height);
} else {
int y = r.y + r.height / 2;
r.setRect(r.x, y, r.width, getHeight() - y);
} // if-else
return r.contains(a_point) ? getTabCount() : -1;
}
private void convertTab(TabTransferData a_data, int a_targetIndex) {
DnDCloseButtonTabbedPane source = a_data.getTabbedPane();
// System.out.println("this=source? " + (this == source));
int sourceIndex = a_data.getTabIndex();
if (sourceIndex < 0) {
return;
} // if
//Save the tab's component, title, and TabComponent.
Component cmp = source.getComponentAt(sourceIndex);
String str = source.getTitleAt(sourceIndex);
Component tcmp = source.getTabComponentAt(sourceIndex);
if (this != source) {
source.remove(sourceIndex);
if (a_targetIndex == getTabCount()) {
addTab(str, cmp);
setTabComponentAt(getTabCount() - 1, tcmp);
} else {
if (a_targetIndex < 0) {
a_targetIndex = 0;
} // if
insertTab(str, null, cmp, null, a_targetIndex);
setTabComponentAt(a_targetIndex, tcmp);
} // if
setSelectedComponent(cmp);
return;
} // if
if (a_targetIndex < 0 || sourceIndex == a_targetIndex) {
return;
} // if
if (a_targetIndex == getTabCount()) {
source.remove(sourceIndex);
addTab(str, cmp);
setTabComponentAt(getTabCount() - 1, tcmp);
setSelectedIndex(getTabCount() - 1);
} else if (sourceIndex > a_targetIndex) {
source.remove(sourceIndex);
insertTab(str, null, cmp, null, a_targetIndex);
setTabComponentAt(a_targetIndex, tcmp);
setSelectedIndex(a_targetIndex);
} else {
source.remove(sourceIndex);
insertTab(str, null, cmp, null, a_targetIndex - 1);
setTabComponentAt(a_targetIndex - 1, tcmp);
setSelectedIndex(a_targetIndex - 1);
}
}
private void initTargetLeftRightLine(int next, TabTransferData a_data) {
if (next < 0) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
return;
} // if
if ((a_data.getTabbedPane() == this)
&& (a_data.getTabIndex() == next
|| next - a_data.getTabIndex() == 1)) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
} else if (getTabCount() == 0) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
return;
} else if (next == 0) {
Rectangle rect = getBoundsAt(0);
m_lineRect.setRect(-LINEWIDTH / 2, rect.y, LINEWIDTH, rect.height);
m_isDrawRect = true;
} else if (next == getTabCount()) {
Rectangle rect = getBoundsAt(getTabCount() - 1);
m_lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y,
LINEWIDTH, rect.height);
m_isDrawRect = true;
} else {
Rectangle rect = getBoundsAt(next - 1);
m_lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y,
LINEWIDTH, rect.height);
m_isDrawRect = true;
}
}
private void initTargetTopBottomLine(int next, TabTransferData a_data) {
if (next < 0) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
return;
} // if
if ((a_data.getTabbedPane() == this)
&& (a_data.getTabIndex() == next
|| next - a_data.getTabIndex() == 1)) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
} else if (getTabCount() == 0) {
m_lineRect.setRect(0, 0, 0, 0);
m_isDrawRect = false;
return;
} else if (next == getTabCount()) {
Rectangle rect = getBoundsAt(getTabCount() - 1);
m_lineRect.setRect(rect.x, rect.y + rect.height - LINEWIDTH / 2,
rect.width, LINEWIDTH);
m_isDrawRect = true;
} else if (next == 0) {
Rectangle rect = getBoundsAt(0);
m_lineRect.setRect(rect.x, -LINEWIDTH / 2, rect.width, LINEWIDTH);
m_isDrawRect = true;
} else {
Rectangle rect = getBoundsAt(next - 1);
m_lineRect.setRect(rect.x, rect.y + rect.height - LINEWIDTH / 2,
rect.width, LINEWIDTH);
m_isDrawRect = true;
}
}
private void initGlassPane(Component c, Point tabPt, int a_tabIndex) {
//Point p = (Point) pt.clone();
getRootPane().setGlassPane(s_glassPane);
if (hasGhost()) {
Rectangle rect = getBoundsAt(a_tabIndex);
BufferedImage image = new BufferedImage(c.getWidth(),
c.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
c.paint(g);
image = image.getSubimage(rect.x, rect.y, rect.width, rect.height);
s_glassPane.setImage(image);
} // if
s_glassPane.setPoint(buildGhostLocation(tabPt));
s_glassPane.setVisible(true);
}
private Rectangle getTabAreaBound() {
Rectangle lastTab = getUI().getTabBounds(this, getTabCount() - 1);
return new Rectangle(0, 0, getWidth(), lastTab.y + lastTab.height);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (m_isDrawRect) {
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(m_lineColor);
g2.fill(m_lineRect);
} // if
}
public interface TabAcceptor {
boolean isDropAcceptable(DnDCloseButtonTabbedPane a_component, int a_index);
}
}
class GhostGlassPane extends JPanel {
public static final long serialVersionUID = 1L;
private final AlphaComposite m_composite;
private Point m_location = new Point(0, 0);
private BufferedImage m_draggingGhost = null;
public GhostGlassPane() {
setOpaque(false);
m_composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);
}
public void setImage(BufferedImage draggingGhost) {
m_draggingGhost = draggingGhost;
}
public void setPoint(Point a_location) {
m_location.x = a_location.x;
m_location.y = a_location.y;
}
public int getGhostWidth() {
if (m_draggingGhost == null) {
return 0;
} // if
return m_draggingGhost.getWidth(this);
}
public int getGhostHeight() {
if (m_draggingGhost == null) {
return 0;
} // if
return m_draggingGhost.getHeight(this);
}
public void paintComponent(Graphics g) {
if (m_draggingGhost == null) {
return;
} // if
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(m_composite);
g2.drawImage(m_draggingGhost, (int) m_location.getX(), (int) m_location.getY(), null);
}
}
Ok, After 3 days fighting in 1 file. I Found a way. Still i extend my version of DnD from first link in question.
in DragDropEnd function (Overrides)
#Override
public void dragDropEnd(DragSourceDropEvent e) {
m_isDrawRect = false;
m_lineRect.setRect(0, 0, 0, 0);
// m_dragTabIndex = -1;
if (hasGhost()) {
s_glassPane.setVisible(false);
s_glassPane.setImage(null);
}
// if drop failed, create new JFrame with JTabbedPane included with public access
if(!e.getDropSuccess()){
// MenuLight class Extends JFrame and Included 1 component JTabbedPane called superPane
MenuLight m = new MenuLight();
m.setLocation(e.getLocation());
m.setVisible(true);
// after create Frame, transfer the tab to other jtabbedpane
((DnDCloseButtonTabbedPane) m.superPane).convertTab(getTabTransferData(e), getTargetTabIndex(e.getLocation()));
}
// if current JTabbedPane Tab is empty dispose it.
if(getTabCount() < 1){
// unfortunly i didnt want to close my Original menu, so check the class of parent of DnD is create from MenuLight and dispose it
if(parent.getClass().equals(MenuLight.class)){
((javax.swing.JFrame) parent).dispose();
}
}
}
Also it needed to find parent to close immediately if jtabbedpane is close i need to pass the parent form too. So i change the constructor into this.
public DnDCloseButtonTabbedPane(final Component _parent)
If you want to know MenuLight code, i included it too
public class MenuLight extends javax.swing.JFrame {
public MenuLight() {
initComponents();
}
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
superPane = new com.theflavare.minierp.helper.DnDCloseButtonTabbedPane(this);
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setPreferredSize(new java.awt.Dimension(640, 480));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(superPane, javax.swing.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(superPane, javax.swing.GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
// Variables declaration - do not modify
public javax.swing.JTabbedPane superPane;
// End of variables declaration
}
And Viola, my mission success, make jtabbedpane drag out and automatic create JFrame. also Dispose the JFrame if current JTabbedpane are empty.
Thx. R
Despite I import the applet library, NetBeans cannot recognize and use getDocumentBase() in my code, I have my html file within my project and all other required files as well, here is a part of my code :
import java.awt.*;
import java.applet.*;
public class AirportCanvas extends Canvas
{
SingleLaneAirport controller;
Image redPlane;
Image bluePlane;
Image airport;
//AudioClip crashSound;
int[] redX,redY,blueX,blueY;
int maxCar = 2;
final static int initredX = 5;
final static int initredY = 55;
final static int initblueX = 410;
final static int initblueY = 130;
final static int bridgeY = 90;
boolean frozen = false;
int cycleTime = 20;
AirportCanvas(SingleLaneAirport controller)
{
super();
this.controller = controller;
// crashSound=controller.getAudioClip(controller.getDocumentBase(),"crash.au");
MediaTracker mt;
mt = new MediaTracker(this);
redPlane = controller.getImage(controller.getDocumentBase(), "redplane.png");
mt.addImage(redPlane, 0);
bluePlane = controller.getImage(controller.getDocumentBase(), "blueplane.png");
mt.addImage(bluePlane, 1);
airport = controller.getImage(controller.getDocumentBase(), "airport.png");
mt.addImage(airport, 2);
try
{
mt.waitForID(0);
mt.waitForID(1);
mt.waitForID(2);
}
catch (java.lang.InterruptedException e)
{
System.out.println("Couldn't load one of the images");
}
setSize(airport.getWidth(null),airport.getHeight(null));
init(1);
}
public final void init(int ncars)
{ //set number of cars
maxCar = ncars;
frozen = false;
redX = new int[maxCar];
redY = new int[maxCar];
blueX = new int[maxCar];
blueY = new int[maxCar];
for (int i = 0; i<maxCar ; i++)
{
redX[i] = initredX - i*85;
redY[i] = initredY;
blueX[i] =initblueX + i*85;
blueY[i] =initblueY;
}
repaint();
}
Image offscreen;
Dimension offscreensize;
Graphics offgraphics;
public void backdrop()
{
Dimension d = getSize();
if ((offscreen == null) || (d.width != offscreensize.width)
|| (d.height != offscreensize.height))
{
offscreen = createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
offgraphics.setFont(new Font("Helvetica",Font.BOLD,36));
}
offgraphics.setColor(Color.lightGray);
offgraphics.drawImage(airport,0,0,this);
}
#Override
public void paint(Graphics g)
{
update(g);
}
#Override
public void update(Graphics g)
{
backdrop();
for (int i=0; i<maxCar; i++)
{
offgraphics.drawImage(redPlane,redX[i],redY[i],this);
offgraphics.drawImage(bluePlane,blueX[i],blueY[i],this);
}
if (blueY[0]==redY[0] && Math.abs(redX[0]+80 - blueX[0])<5)
{
offgraphics.setColor(Color.red);
offgraphics.drawString("Crunch!",200,100);
frozen=true;
// crashSound.play();
}
g.drawImage(offscreen, 0, 0, null);
}
//returns true for the period from just before until just after car on bridge
public boolean moveRed(int i) throws InterruptedException
{
int X = redX[i];
int Y = redY[i];
synchronized (this)
{
while (frozen )
wait();
if (i==0 || Math.abs(redX[i-1] - X) > 120)
{
X += 2;
if (X >=500)
{
X = -80; Y = initredY;
}
if (X >=60 && X < 290 && Y<bridgeY)
++Y;
if (X >=290 && Y>initredY)
--Y;
}
redX[i]=X;
redY[i]=Y;
repaint();
}
Thread.sleep(cycleTime);
return (X>25 && X<400);
}
//returns true for the period from just before until just after car on bridge
public boolean moveBlue(int i) throws InterruptedException
{
int X = blueX[i];
int Y = blueY[i];
synchronized (this)
{
while (frozen )
wait();
if (i==0 || Math.abs(blueX[i-1] - X) > 120)
{
X -= 2;
if (X <=-80)
{
X = 500; Y = initblueY;
}
if (X <=370 && X > 130 && Y>bridgeY)
--Y;
if (X <=130 && Y<initblueY)
++Y;
blueX[i]=X;
}
blueY[i]=Y;
repaint();
}
Thread.sleep(cycleTime);
repaint();
return (X>25 && X<400);
}
public synchronized void freeze()
{
frozen = true;
}
public synchronized void thaw()
{
frozen = false;
notifyAll();
}
}
Single Lane Airport Class :
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class SingleLaneAirport {
AirportCanvas display;
Button restart;
Button freeze;
Button onecar;
Button twocar;
Button threecar;
Checkbox fair;
Checkbox safe;
boolean fixed = false;
int maxCar = 1;
Thread red[];
Thread blue[];
#Override
public void init()
{
setLayout(new BorderLayout());
display = new AirportCanvas(this);
add("Center",display);
restart = new Button("Restart");
restart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.thaw();
}
});
freeze = new Button("Freeze");
freeze.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.freeze();
}
});
onecar = new Button("One Car");
onecar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 1;
start();
}
});
twocar = new Button("Two Cars");
twocar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 2;
start();
}
});
threecar = new Button("Three Cars");
threecar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 3;
start();
}
});
safe = new Checkbox("Safe",null,true);
safe.setBackground(Color.lightGray);
safe.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
stop();
start();
}
});
fair = new Checkbox("Fair",null,false);
fair.setBackground(Color.lightGray);
fair.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
stop();
start();
}
});
Panel p1 = new Panel();
p1.setLayout(new FlowLayout());
p1.add(freeze);
p1.add(restart);
p1.add(onecar);
p1.add(twocar);
p1.add(threecar);
p1.add(safe);
p1.add(fair);
add("South",p1);
setBackground(Color.lightGray);
}
#Override
public void start()
{
red = new Thread[maxCar];
blue = new Thread[maxCar];
display.init(maxCar);
Airport b;
if (fair.getState() && safe.getState())
b = new FairAirport();
else if ( safe.getState())
b = new SafeAirport();
else
b = new Airport();
for (int i = 0; i<maxCar; i++)
{
red[i] = new Thread(new RedPlane(b,display,i));
blue[i] = new Thread(new BluePlane(b,display,i));
}
for (int i = 0; i<maxCar; i++)
{
red[i].start();
blue[i].start();
}
}
#Override
public void stop()
{
for (int i = 0; i<maxCar; i++)
{
red[i].interrupt();
blue[i].interrupt();
}
}
}
Your class SingleLaneAirport should extend Applet class in order to use getDocumentBase() function.
Because getDocumentBase() is the function of Applet class and not the Object class