The menu bar won't draw and the keylistener won't work. Should I add the menu bar to a panel or a content pane? What am I doing wrong? What to do? Help? Thank you!
Please copy and run the code first.
CLASS DRAWINGDEMO
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawingDemo extends JFrame implements ActionListener, KeyListener{
DrawingPanel demo = new DrawingPanel();
public DrawingDemo()
{
getContentPane().add(demo);
setVisible(true);
setSize(1024,720);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JPanel p = new JPanel();
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File");
JMenu edit = new JMenu("Edit");
JMenu settings = new JMenu("Settings");
JMenu help = new JMenu("Help");
JMenuItem exit = new JMenuItem(">Exit");
JMenuItem imp = new JMenuItem(">Import");
JMenuItem exp = new JMenuItem(">Export");
JMenuItem sav = new JMenuItem(">Save");
JMenuItem ope = new JMenuItem(">Open");
file.add(ope);
file.add(sav);
file.add(imp);
file.add(exp);
file.add(exit);
mb.add(file);
mb.add(edit);
mb.add(settings);
mb.add(help);
setJMenuBar(mb);
while(true){
demo.repaint();
}
}
public void actionPerformed(java.awt.event.ActionEvent e)
{
}
public void KeyEvent(java.awt.event.ActionEvent e)
{
}
public void keyReleased(java.awt.event.KeyEvent e)
{
}
public void keyPressed(java.awt.event.KeyEvent e)
{
switch (e.getKeyCode()){
case KeyEvent.VK_A :
{
demo.pos_camx -= 0.5;
}
break;
case KeyEvent.VK_D :
{
demo.pos_camx += 0.5;
}
break;
case KeyEvent.VK_W :
{
demo.pos_camy += 0.5;
}
break;
case KeyEvent.VK_S :
{
demo.pos_camy -= 0.5;
}
break;
}
}
public void keyTyped(java.awt.event.KeyEvent e)
{
}
public static void main(String[] args)
{
new DrawingDemo();
}
}
CLASS DRAWINGPANEL
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics;
public class DrawingPanel extends JPanel {
long nextSecond = System.currentTimeMillis() + 1000;
int framesInLastSecond = 0;
int framesInCurrentSecond = 0;
int[][] LP= new int[19][3];
double pos_camx,pos_camy,pos_camz,rot_camx,rot_camy,xpoint,ypoint,zpoint;
double rot_radx,rot_rady,nclip,xscr,yscr,kx,ky;
int pxscr,pyscr,nxscr,nyscr,e;
public void paint(Graphics g)
{
LP[0][0] = -1;
LP[0][1] = -1;
LP[0][2] = -1;
LP[1][0] = 1;
LP[1][1] = -1;
LP[1][2] = -1;
LP[2][0] = 1;
LP[2][1] = 1;
LP[2][2] = -1;
LP[3][0] = -1;
LP[3][1] = 1;
LP[3][2] = -1;
LP[4][0] = -1;
LP[4][1] = -1;
LP[4][2] = -1;
LP[5][0] = 1;
LP[5][1] = 1;
LP[5][2] = -1;
LP[6][0] = 1;
LP[6][1] = 1;
LP[6][2] = 1;
LP[7][0] = -1;
LP[7][1] = 1;
LP[7][2] = 1;
LP[8][0] = -1;
LP[8][1] = -1;
LP[8][2] = 1;
LP[9][0] = 1;
LP[9][1] = -1;
LP[9][2] = 1;
LP[10][0] = 1;
LP[10][1] = 1;
LP[10][2] = 1;
LP[11][0] = -1;
LP[11][1] = -1;
LP[11][2] = 1;
LP[12][0] = -1;
LP[12][1] = -1;
LP[12][2] = -1;
LP[13][0] = 1;
LP[13][1] = -1;
LP[13][2] = 1;
LP[14][0] = 1;
LP[14][1] = -1;
LP[14][2] = -1;
LP[15][0] = 1;
LP[15][1] = 1;
LP[15][2] = 1;
LP[16][0] = -1;
LP[16][1] = 1;
LP[16][2] = -1;
LP[17][0] = -1;
LP[17][1] = 1;
LP[17][2] = 1;
LP[18][0] = -1;
LP[18][1] = -1;
LP[18][2] = -1;
pos_camx = 0;
pos_camy = 0;
pos_camz = 0;
rot_camx = 0;
rot_camy = 0;
rot_radx = 3.1415*rot_camx/180;
rot_rady = 3.1415*rot_camy/180;
nclip = 0.275;
kx = 8.52/getWidth();
ky = 5.46/getHeight();
super.paint(g);
Graphics2D g1 = (Graphics2D)g;
g1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.black);
xpoint = (double)(LP[0][0])/2;
ypoint = 20 + (double)(LP[0][1])/2;
zpoint = (double)(LP[0][2])/2;
pxscr = (int)(
((xpoint - pos_camx)*Math.cos(rot_radx) + (ypoint + pos_camy)*Math.sin(rot_radx))*nclip
/((ypoint - pos_camy)*Math.cos(rot_radx) + (pos_camx- xpoint)*Math.sin(rot_radx) + 0.0000000012)*100/kx
+ getWidth()/2);
pyscr = (int)(
getHeight()/2-
(((ypoint + pos_camy)*Math.sin(rot_rady) + (zpoint - pos_camz)*Math.cos(rot_rady))*nclip
/((ypoint - pos_camy)*Math.cos(rot_radx) + (pos_camx + xpoint)*Math.sin(rot_radx) + 0.0000000012)*100/ky)
);
for (int i=1; i<19;i++){
xpoint = (double)(LP[i][0])/2;
ypoint = 20 + (double)(LP[i][1])/2;
zpoint = (double)(LP[i][2])/2;
nxscr = (int)(
((xpoint - pos_camx)*Math.cos(rot_radx) + (ypoint + pos_camy)*Math.sin(rot_radx))*nclip
/((ypoint - pos_camy)*Math.cos(rot_radx)+(pos_camx + xpoint)*Math.sin(rot_radx)+0.0000000012)*100/kx
+getWidth()/2);
nyscr = (int)(
getHeight()/2-
(((ypoint + pos_camy)*Math.sin(rot_rady)+(zpoint - pos_camz)*Math.cos(rot_rady))*nclip
/((ypoint - pos_camy)*Math.cos(rot_radx)+(pos_camx + xpoint)*Math.sin(rot_radx)+0.0000000012)*100/ky)
);
g1.drawLine(pxscr,pyscr,nxscr,nyscr);
pxscr = nxscr;
pyscr = nyscr;
}
g.drawString("(" + pxscr + "," + pyscr + ")",20,40);
long currentTime = System.currentTimeMillis();
if (currentTime > nextSecond) {
nextSecond += 1000;
framesInLastSecond = framesInCurrentSecond;
framesInCurrentSecond = 0;
}
framesInCurrentSecond++;
g.drawString(framesInLastSecond + " fps", 20, 20);
}
}
Swing is an Event Driven environment, blocking the Event Dispatching Thread in any way will prevent it from begin able to process any events (such as mouse or keyboard events).
KeyListener is a low level API and is generally discourage for a number of reasons, focus issues been the most prominent. In order for a component to be able to respond to a KeyListener it must be focusable and have focus. The problem you have, is neither of these conditions are actually being meet (nor are you actually registering the key listener with anything).
While the JFrame is focusable, it contains a JRootPane which contains (amongst other things) a content pane, which contains your DrawingPanel. Any of these may steal focus from the frame at any time, rendering your KeyListener useless.
The preferred method is to use the key bindings API
Generally, you are discouraged from overriding paint. Paint is a very complex method and you should only override it if you are absolutely sure it is the right thing to do. The preferred method for performing custom painting is to override the paintComponent method, as out lined here. The most important reason for this, is this method is double buffered, making you painting smoother, also, you, generally, won't interfere with other components that may be on the component.
Also, in your paint method, you are setting the camera positions to 0 which basically undoes all you good work with your non-functional key listeners ;)
public class DrawingDemo extends JFrame { //implements ActionListener, KeyListener {
DrawingPanel demo = new DrawingPanel();
public DrawingDemo() {
getContentPane().add(demo);
setVisible(true);
setSize(1024, 720);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JPanel p = new JPanel();
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File");
JMenu edit = new JMenu("Edit");
JMenu settings = new JMenu("Settings");
JMenu help = new JMenu("Help");
JMenuItem exit = new JMenuItem(">Exit");
JMenuItem imp = new JMenuItem(">Import");
JMenuItem exp = new JMenuItem(">Export");
JMenuItem sav = new JMenuItem(">Save");
JMenuItem ope = new JMenuItem(">Open");
file.add(ope);
file.add(sav);
file.add(imp);
file.add(exp);
file.add(exit);
mb.add(file);
mb.add(edit);
mb.add(settings);
mb.add(help);
setJMenuBar(mb);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DrawingDemo();
}
});
}
public class DrawingPanel extends JPanel {
long nextSecond = System.currentTimeMillis() + 1000;
int framesInLastSecond = 0;
int framesInCurrentSecond = 0;
int[][] LP = new int[19][3];
double pos_camx, pos_camy, pos_camz, rot_camx, rot_camy, xpoint, ypoint, zpoint;
double rot_radx, rot_rady, nclip, xscr, yscr, kx, ky;
int pxscr, pyscr, nxscr, nyscr, e;
public DrawingPanel() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "Move.A");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "Move.D");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "Move.W");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "Move.S");
ActionMap am = getActionMap();
am.put("Move.A", new MoveXAction(this, 0.5f));
am.put("Move.D", new MoveXAction(this, -0.5f));
am.put("Move.W", new MoveYAction(this, 0.5f));
am.put("Move.S", new MoveYAction(this, -0.5f));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
LP[0][0] = -1;
LP[0][1] = -1;
LP[0][2] = -1;
LP[1][0] = 1;
LP[1][1] = -1;
LP[1][2] = -1;
LP[2][0] = 1;
LP[2][1] = 1;
LP[2][2] = -1;
LP[3][0] = -1;
LP[3][1] = 1;
LP[3][2] = -1;
LP[4][0] = -1;
LP[4][1] = -1;
LP[4][2] = -1;
LP[5][0] = 1;
LP[5][1] = 1;
LP[5][2] = -1;
LP[6][0] = 1;
LP[6][1] = 1;
LP[6][2] = 1;
LP[7][0] = -1;
LP[7][1] = 1;
LP[7][2] = 1;
LP[8][0] = -1;
LP[8][1] = -1;
LP[8][2] = 1;
LP[9][0] = 1;
LP[9][1] = -1;
LP[9][2] = 1;
LP[10][0] = 1;
LP[10][1] = 1;
LP[10][2] = 1;
LP[11][0] = -1;
LP[11][1] = -1;
LP[11][2] = 1;
LP[12][0] = -1;
LP[12][1] = -1;
LP[12][2] = -1;
LP[13][0] = 1;
LP[13][1] = -1;
LP[13][2] = 1;
LP[14][0] = 1;
LP[14][1] = -1;
LP[14][2] = -1;
LP[15][0] = 1;
LP[15][1] = 1;
LP[15][2] = 1;
LP[16][0] = -1;
LP[16][1] = 1;
LP[16][2] = -1;
LP[17][0] = -1;
LP[17][1] = 1;
LP[17][2] = 1;
LP[18][0] = -1;
LP[18][1] = -1;
LP[18][2] = -1;
// pos_camx = 0;
// pos_camy = 0;
// pos_camz = 0;
rot_camx = 0;
rot_camy = 0;
rot_radx = 3.1415 * rot_camx / 180;
rot_rady = 3.1415 * rot_camy / 180;
nclip = 0.275;
kx = 8.52 / getWidth();
ky = 5.46 / getHeight();
Graphics2D g1 = (Graphics2D) g;
g1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.black);
xpoint = (double) (LP[0][0]) / 2;
ypoint = 20 + (double) (LP[0][1]) / 2;
zpoint = (double) (LP[0][2]) / 2;
pxscr = (int) (((xpoint - pos_camx) * Math.cos(rot_radx) + (ypoint + pos_camy) * Math.sin(rot_radx)) * nclip
/ ((ypoint - pos_camy) * Math.cos(rot_radx) + (pos_camx - xpoint) * Math.sin(rot_radx) + 0.0000000012) * 100 / kx
+ getWidth() / 2);
pyscr = (int) (getHeight() / 2
- (((ypoint + pos_camy) * Math.sin(rot_rady) + (zpoint - pos_camz) * Math.cos(rot_rady)) * nclip
/ ((ypoint - pos_camy) * Math.cos(rot_radx) + (pos_camx + xpoint) * Math.sin(rot_radx) + 0.0000000012) * 100 / ky));
for (int i = 1; i < 19; i++) {
xpoint = (double) (LP[i][0]) / 2;
ypoint = 20 + (double) (LP[i][1]) / 2;
zpoint = (double) (LP[i][2]) / 2;
nxscr = (int) (((xpoint - pos_camx) * Math.cos(rot_radx) + (ypoint + pos_camy) * Math.sin(rot_radx)) * nclip
/ ((ypoint - pos_camy) * Math.cos(rot_radx) + (pos_camx + xpoint) * Math.sin(rot_radx) + 0.0000000012) * 100 / kx
+ getWidth() / 2);
nyscr = (int) (getHeight() / 2
- (((ypoint + pos_camy) * Math.sin(rot_rady) + (zpoint - pos_camz) * Math.cos(rot_rady)) * nclip
/ ((ypoint - pos_camy) * Math.cos(rot_radx) + (pos_camx + xpoint) * Math.sin(rot_radx) + 0.0000000012) * 100 / ky));
g1.drawLine(pxscr, pyscr, nxscr, nyscr);
pxscr = nxscr;
pyscr = nyscr;
}
g.drawString("(" + pxscr + "," + pyscr + ")", 20, 40);
long currentTime = System.currentTimeMillis();
if (currentTime > nextSecond) {
nextSecond += 1000;
framesInLastSecond = framesInCurrentSecond;
framesInCurrentSecond = 0;
}
framesInCurrentSecond++;
g.drawString(framesInLastSecond + " fps", 20, 20);
}
}
public class MoveXAction extends AbstractAction {
private float direction;
private final DrawingPanel pane;
private MoveXAction(DrawingPanel pane, float amount) {
this.direction = amount;
this.pane = pane;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("...x by " + direction);
pane.pos_camx += direction;
pane.repaint();
}
}
public class MoveYAction extends AbstractAction {
private float direction;
private final DrawingPanel pane;
private MoveYAction(DrawingPanel pane, float amount) {
this.direction = amount;
this.pane = pane;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("...y by " + direction);
pane.pos_camy += direction;
pane.repaint();
}
}
}
I had a quick play around and I have to say, Nice ;)
you only need to repaint if something changed, and even then, probably not a million times a second ( or whatever your cpu can handle). so i would suggest to change the while(true) to a loop which waits for a bit, or repaint in the keylistener (depending on what you want the application to do)
and you implement the keylistener interface, but you are not adding it to the registered listeners so you need a this.addKeyListener(this);
the JMenuBar doesnt show up because you make the frame visible before adding the menubar. normally you want to make the window visible after initializing its components.
so put the setVisible(true); after you add the menubar
Related
I have a JLayeredPane that has four layers:
JPanel set as a background
Grid of JPanels each holding a JLabel
Grid of JPanels each holding several JLabels that are only set to visible if the label in the panel below is empty
A custom component that is only used to override the paintComponent() method to draw over everything below
For some reason if I change the background colour of the labels in layer 3 and then draw to layer 4, the labels in layer 3 are painted over the graphics painted in level 4. I have tried to set ignoreRepaint() on various components as well as playing around with the opacity and code structure but all to no avail.
Does anyone know how to prevent this from happening?
I won't attach the source code because the project is quite large but I've attached an example that runs as a stand alone program and demonstrates my problem when you hit the "add arrow" button.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class GraphicsTest {
#SuppressWarnings("serial")
class Painter extends JComponent {
public Painter(int x, int y) {
setBounds(0, 0, x, y);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
private static final int CELL_SIZE = 40;
private static final int NOTE_SIZE = 20;
private JFrame frame;
private static JButton test;
private static JButton clear;
private static JLayeredPane pane = new JLayeredPane();
private static JPanel back = new JPanel();
private static JPanel[][] cellPanels = new JPanel[10][10];
private static JLabel[][] cells = new JLabel[10][10];
private static JPanel[][] notePanels = new JPanel[10][10];
private static JLabel[][][] notes = new JLabel[10][10][4];
private static Painter painter;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GraphicsTest window = new GraphicsTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public GraphicsTest() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setSize(600, 700);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
pane.setBounds(50, 50, 500, 500);
pane.setLayout(null);
frame.getContentPane().add(pane);
back.setBounds(0, 0, 500, 500);
back.setBackground(Color.BLACK);
pane.add(back, new Integer(100));
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
String text = "";
if ((i % 2) == 1 && (k % 2) == 1) text = (i + k) + "";
cellPanels[i][k] = new JPanel();
cellPanels[i][k].setBounds(k * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
cellPanels[i][k].setBackground(Color.WHITE);
cellPanels[i][k].setBorder(new LineBorder(Color.BLACK, 1));
cells[i][k] = new JLabel(text);
cells[i][k].setBounds(0, 0, CELL_SIZE, CELL_SIZE);
cells[i][k].setOpaque(false);
cellPanels[i][k].add(cells[i][k]);
pane.add(cellPanels[i][k], new Integer(200));
}
}
boolean display;
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
if ((i % 2) == 0 && (k % 2) == 0) {
display = true;
} else {
display = false;
}
notePanels[i][k] = new JPanel();
notePanels[i][k].setBounds(k * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
notePanels[i][k].setBackground(Color.WHITE);
notePanels[i][k].setBorder(new LineBorder(Color.BLACK, 1));
notePanels[i][k].setLayout(null);
for (int m = 0; m < 2; m++) {
for (int p = 0; p < 2; p++) {
notes[i][k][(m * 2) + p] = new JLabel(30 + "");
notes[i][k][(m * 2) + p].setBounds(m * NOTE_SIZE, p * NOTE_SIZE, NOTE_SIZE, NOTE_SIZE);
notes[i][k][(m * 2) + p].setOpaque(true);
notePanels[i][k].add(notes[i][k][(m * 2) + p]);
}
}
if (display) {
notePanels[i][k].setVisible(true);
} else {
notePanels[i][k].setVisible(false);
}
pane.add(notePanels[i][k], new Integer(300));
}
}
painter = new Painter(500, 500);
pane.add(painter, new Integer(400));
test = new JButton("Add Arrow");
test.setBounds(50, 600, 100, 25);
test.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
highlightNotes();
Arrow.drawArrow(painter.getGraphics(), 20, 20, 400, 400, 20, 30, 40, Color.BLACK, Color.GREEN);
}
});
frame.getContentPane().add(test);
clear = new JButton("Clear");
clear.setBounds(175, 600, 100, 25);
clear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
painter.repaint();
}
});
frame.getContentPane().add(clear);
}
private static void highlightNotes() {
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
for (int n = 0; n < 4; n++) {
notes[i][k][n].setBackground(Color.BLUE);
}
}
}
}
static class Arrow {
public static void drawArrow(Graphics g, int tailx, int taily, int headx, int heady,
int shaftw, int headw, int headh, Color outline, Color fill) {
if ((shaftw % 2) == 0) {
shaftw--;
}
if ((headw % 2) == 0) {
headw--;
}
if ((headh % 2) == 0) {
headh--;
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double length = Math.sqrt((double) (((headx - tailx) * (headx - tailx))
+ ((heady - taily) * (heady - taily))));
int tailLength = (int) (length - headw) + 1;
double theta = Math.atan2(heady - taily, headx - tailx);
Point point1 = new Point(0, -(shaftw / 2));
point1 = getTransPoint(point1, theta);
point1.x += tailx;
point1.y += taily;
Point point2 = new Point(tailLength, -(shaftw / 2));
point2 = getTransPoint(point2, theta);
point2.x += tailx;
point2.y += taily;
Point point3 = new Point(tailLength, -(headw / 2));
point3 = getTransPoint(point3, theta);
point3.x += tailx;
point3.y += taily;
Point point4 = new Point((int) length, 0);
point4 = getTransPoint(point4, theta);
point4.x += tailx;
point4.y += taily;
Point point5 = new Point(tailLength, (headw / 2));
point5 = getTransPoint(point5, theta);
point5.x += tailx;
point5.y += taily;
Point point6 = new Point(tailLength, (shaftw / 2));
point6 = getTransPoint(point6, theta);
point6.x += tailx;
point6.y += taily;
Point point7 = new Point(0, (shaftw / 2));
point7 = getTransPoint(point7, theta);
point7.x += tailx;
point7.y += taily;
//Create arrow at tail coordinates passed in
Polygon arrow = new Polygon();
arrow.addPoint(point1.x, point1.y);
arrow.addPoint(point2.x, point2.y);
arrow.addPoint(point3.x, point3.y);
arrow.addPoint(point4.x, point4.y);
arrow.addPoint(point5.x, point5.y);
arrow.addPoint(point6.x, point6.y);
arrow.addPoint(point7.x, point7.y);
//Draw and fill the arrow
g2.setColor(fill);
g2.fillPolygon(arrow);
g2.setColor(outline);
g2.drawPolygon(arrow);
}
private static Point getTransPoint(Point point, double theta) {
int x = (int) ((point.x * Math.cos(theta)) - (point.y * Math.sin(theta)));
int y = (int) ((point.y * Math.cos(theta)) + (point.x * Math.sin(theta)));
return new Point(x, y);
}
}
}
Im just starting to code and learn javafx and doing an easy project and my problem is after i add a Glow effect on my graphic context the animation slows down dramaticly.
/**
* JavaFX rocks ;)
*/
public class CDLMatrix extends Application {
Stage matrixStage;
private final String characters = "Effect glow = new Glow(1.0); gc.setEffect(glow); WHY SHATTERS ?!";
private final Random random = new Random();
protected final Font font = Font.font("MS PGothic", FontWeight.BOLD, 15);
char[] data = new char[2000 * 2000];
int[] path = new int[2000 * 2000];
private long lastTime = 0;
int getNumberOfCharsPerRow() {
return (int) matrixStage.getWidth() / 12;
}
int getNumberOfCharsPerColumn() {
return (int) matrixStage.getHeight() / 12;
}
// takes random for now
private char getChar() {
return characters.charAt(Math.abs(random.nextInt()
% characters.length()));
}
void update(long now) {
if (lastTime == 0) {
lastTime = now;
}
// fadeTime = how fast trail will fade out
// flipRate = how fast trail chars will change
final int fadeTime = 3;
final float flipRate = 0.01f;
final int fillStart = 100;
final float fillRate = 0.01f;
int numberOfCharsPerRow = getNumberOfCharsPerRow();
int numberOfCharsPerColumn = getNumberOfCharsPerColumn();
int numberOfChars = numberOfCharsPerRow * numberOfCharsPerColumn;
for (int i = numberOfChars - 1; i >= 0; --i) {
if (i + numberOfCharsPerRow < numberOfChars) {
if (path[i] == 255) {
// This means char was just set
// Initialize the next row at this X
// position
path[i + numberOfCharsPerRow] = 255;
data[i + numberOfCharsPerRow] = getChar();
}
}
// path[i] > 64 means if this char Green component > 25%
if (path[i] > 64 && random.nextFloat() < flipRate) {
data[i] = getChar();
}
// Decrement the char Green component
if (path[i] > fadeTime) {
path[i] -= fadeTime;
} else {
path[i] = 0;
}
// First row
// Start doing stuff only if the Green component > 40%
if (i < numberOfCharsPerRow && path[i] <= fillStart) {
if (random.nextFloat() < fillRate) {
path[i] = 255;
data[i] = getChar();
}
}
}
lastTime = now;
}
#Override
public void start(Stage stage) throws Exception {
this.matrixStage = stage;
matrixStage.setTitle("CDL Matrix");
Group root = new Group();
Scene scene = new Scene(root, 1024, 768);
scene.addEventHandler(KeyEvent.KEY_PRESSED,
new EventHandler<KeyEvent>() {
#Override
// F key for full screen ;)
public void handle(KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.F) {
matrixStage.setFullScreen(!matrixStage
.isFullScreen());
}
// ctrl + Q = exit
if (keyEvent.isControlDown()
&& keyEvent.getCode() == KeyCode.Q) {
matrixStage.close();
}
}
});
Canvas canvas = new Canvas();
canvas.widthProperty().bind(matrixStage.widthProperty());
canvas.heightProperty().bind(matrixStage.heightProperty());
final GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFont(font);
// Effect glow = new Glow(1.0); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// gc.setEffect(glow); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
new AnimationTimer() {
#Override
public void handle(long now) {
update(now);
gc.clearRect(0, 0, matrixStage.getWidth(),
matrixStage.getHeight());
gc.setFill(Color.rgb(0, 1, 0));
gc.fillRect(0, 0, matrixStage.getWidth(),
matrixStage.getHeight());
int y = 0;
int numberOfCharsPerRow = getNumberOfCharsPerRow();
int numberOfCharsPerColumn = getNumberOfCharsPerColumn();
// Colors
for (int i = 0; i < numberOfCharsPerRow
* numberOfCharsPerColumn; ++i) {
gc.setFill(Color.rgb(0, path[i], 0));
String text = String.valueOf(data[i]);
gc.fillText(text, (i % numberOfCharsPerRow) * 12 + 1,
y + 13);
if (i % numberOfCharsPerRow == numberOfCharsPerRow - 1) {
y += 12;
}
}
}
}.start();
root.getChildren().add(canvas);
matrixStage.setScene(scene);
matrixStage.show();
}
}
Apply the glow to the Canvas node rather than to the GraphicsContext.
Animation will then occur at normal speed rather than slideshow speed.
Change:
gc.setEffect(glow);
To:
canvas.setEffect(glow);
There must be something in the internal implementation of JavaFX which causes applying effects such as Glow to a GraphicsContext rather than a Node to be orders of magnitude less efficient. You might want to file an issue in the JavaFX issue tracker to have a developer look into it.
Test environment: Java 8u40, OS X 10.9
i am creating a maze generation application. what i want to happen is that, when i run my program, it will show the animation on how the maze was created (it will show how it knocks the wall to create a path).
i tried to put delay on some of its parts but it won't run.thank you for the HUGE HELP!
here's the code:
public class Maze extends JPanel {
private Room[][] rooms;// m x n matrix of rooms
private ArrayList<Wall> walls; // List of walls
private Random rand;// for random wall
private int height;// height of matrix
private int width;// width of matrix
private int num;// incrementor
private JoinRoom ds;// union paths
// paint methods //
private int x_cord; // x-axis rep
private int y_cord;// y-axis rep
private int roomSize;
private int randomWall;
private int create;
int mazectr;
public static int m;// these are variables for the size of maze (m x n)
public static int n;
public Maze(int m, int n) {
JPanel j = new JPanel();
final JFrame f = new JFrame();
this.height = m;
this.width = n;
rooms = new Room[m][n];
walls = new ArrayList<Wall>((m - 1) * (n - 1));
long startTime = System.currentTimeMillis();
generateRandomMaze();
long endTime = System.currentTimeMillis();
final JLabel jl = new JLabel("Time Taken: " + (endTime-startTime) + "ms");
final JButton y = new JButton("OK");
j.add(jl);
j.add(y);
f.add(j);
y.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent e)
{
f.setVisible(false);
}
});
f.setVisible(true);
f.setSize(100, 100);
//jl.setLocation(1000, 1500);
//jl.setBounds(0, 0, 110, 130);
setPreferredSize(new Dimension(800, 700));
}
private void generateRandomMaze() {
generateInitialRooms();// see next method
ds = new JoinRoom(width * height);
rand = new Random(); // here is the random room generator
num = width * height;
while (num > 1) {
// when we pick a random wall we want to avoid the borders getting eliminated
randomWall = rand.nextInt(walls.size());
Wall temp = walls.get(randomWall);
// we will pick two rooms randomly
int roomA = temp.currentRoom.y + temp.currentRoom.x * width;
int roomB = temp.nextRoom.y + temp.nextRoom.x * width;
// check roomA and roomB to see if they are already members
if (ds.find(roomA) != ds.find(roomB)) {
walls.remove(randomWall);
ds.unionRooms(ds.find(roomA), ds.find(roomB));
temp.isGone = true;
temp.currentRoom.adj.add(temp.nextRoom);
temp.nextRoom.adj.add(temp.currentRoom);
num--;
}// end of if
}// end of while
}
// name the room to display
private int roomNumber = 0;
private static Label input;
private static Label input2;
/**
* Sets the grid of rooms to be initially boxes
* This is self explanitory, we are only creating an reverse L for all
* The rooms and there is an L for the border
*/
private void generateInitialRooms() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
// create north walls
rooms[i][j] = new Room(i, j);
if (i == 0) {
rooms[i][j].north = new Wall(rooms[i][j]);
} else {
rooms[i][j].north = new Wall(rooms[i - 1][j], rooms[i][j]);
walls.add(rooms[i][j].north);
}
if (i == height - 1) {
rooms[i][j].south = new Wall(rooms[i][j]);
}
if (j == 0) {
rooms[i][j].west = new Wall(rooms[i][j]);
} else {
rooms[i][j].west = new Wall(rooms[i][j - 1], rooms[i][j]);
walls.add(rooms[i][j].west);
}
if (j == width - 1) {
rooms[i][j].east = new Wall(rooms[i][j]);
}
rooms[i][j].roomName = roomNumber++;// we will name the rooms
}
}
// initalize entrance and exit
rooms[0][0].west.isGone = true;// you can replace .west.isGone with .north.isGone
// this is just saying the roomName for top left is 0
rooms[0][0].roomName = 0;
// we will remove the south wall of the last room
rooms[height - 1][width - 1].south.isGone = true;
// this is just saying the roomName for bottom right is the last element in the mxn room matrix
rooms[height - 1][width - 1].roomName = (height * width);
}
public void paintComponent(Graphics g) {
x_cord = 40;
y_cord = 40;
Thread t = new Thread();
// could have taken height as well as width
// just need something to base the roomsize
roomSize = (width - x_cord) / width + 20;
// temp variables used for painting
int x = x_cord;
int y = y_cord;
for (int i = 0; i <= height - 1; i++) {
for (int j = 0; j <= width - 1; j++) {
if (!(rooms[i][j].north.isGone)) {
g.drawLine(x, y, x + roomSize, y);
}//end of north if
// west wall not there draw the line
if (rooms[i][j].west.isGone == false) {
g.drawLine(x, y, x, y + roomSize);
}// end of west if
if ((i == height - 1) && rooms[i][j].south.isGone == false) {
g.drawLine(x, y + roomSize, x + roomSize,
y + roomSize);
}// end of south if
if ((j == width - 1) && rooms[i][j].east.isGone == false) {
g.drawLine(x + roomSize, y, x + roomSize,
y + roomSize);
}// end of east if
x += roomSize;// change the horizontal
try
{
Thread.sleep(50);
} catch (Exception e) {};
t.start();
}// end of inner for loop
x = x_cord;
y += roomSize;
}// end of outer for loop
}
public static void main(String[] args) throws IOException {
// use JFrame to put the created panel on
String path = "E:\\Iskul\\trys\\tryy\\bin\\GUI.jpg";
File file = new File("E:\\Iskul\\trys\\tryy\\bin\\GUI.jpg");
BufferedImage image = ImageIO.read(file);
File fileRec = new File("E:\\Iskul\\trys\\tryy\\bin\\re.jpg");
BufferedImage imageRec = ImageIO.read(fileRec);
File fileHex = new File("E:\\Iskul\\trys\\tryy\\bin\\hexx.jpg");
BufferedImage imageHex = ImageIO.read(fileHex);
final JFrame frame = new JFrame("Prim's Algorithm");
final JPanel jp = new JPanel();
final JTextField input = new JTextField(10);
final JTextField input2 = new JTextField(10);
final JButton jb = new JButton(new ImageIcon(imageRec));
jb.setBorder(BorderFactory.createEmptyBorder());
final JButton jb1 = new JButton(new ImageIcon(imageHex));
jb1.setBorder(BorderFactory.createEmptyBorder());
final JLabel label = new JLabel(new ImageIcon(image));
jb.setLocation(100, 10);
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
frame.setSize(400, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(795, 501));
jp.add(input);
jp.add(input2);
frame.add(jp);
jp.add(jb);
jp.add(jb1);
//jb.setImage(image);
jb.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//int mazectr = 1;
int m = Integer.valueOf(input.getText());
int n = Integer.valueOf(input2.getText());
frame.remove(label);
frame.remove(jp);
//frame.add(new Maze(m,n));
frame.getContentPane().add(new Maze(m, n));
frame.pack();
}});
jb1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//int m = Integer.valueOf(input.getText());
//int n = Integer.valueOf(input2.getText());
Hexa1 hexa = new Hexa1();
hexa.main();
//hexa.run();
}
});
}}// end of main
Your code wont work, you cant do an sleep in the Paint method, because if you do so, he wont draw, he just waits and at the end he'll draw your whole image.
If you want to do a nice effect, you should draw one step after the other but you should be aware that this is a lot of work to realize...
I have a gui where data is entered and the averages are calculated for 5 different sets of data. These are stored in an array with the five averages in the five positions.
How do I make it draw rectangles in a jpanel to look like a graph of those 5 averages ?
..make it draw rectangles in a jpanel to look like a graph...
Assuming, youre talking about bar graph,
Have a look at this example :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SimpleBarChart extends JPanel {
private double[] value;
private String[] languages;
private String title;
public SimpleBarChart(double[] val, String[] lang, String t) {
languages = lang;
value = val;
title = t;
}
#Override
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
if (value == null || value.length == 0) {
return;
}
double minValue = 0;
double maxValue = 0;
for (int i = 0; i < value.length; i++) {
if (minValue > value[i]) {
minValue = value[i];
}
if (maxValue < value[i]) {
maxValue = value[i];
}
}
Dimension dim = getSize();
int clientWidth = dim.width;
int clientHeight = dim.height;
int barWidth = clientWidth / value.length;
Font titleFont = new Font("Book Antiqua", Font.BOLD, 15);
FontMetrics titleFontMetrics = graphics.getFontMetrics(titleFont);
Font labelFont = new Font("Book Antiqua", Font.PLAIN, 10);
FontMetrics labelFontMetrics = graphics.getFontMetrics(labelFont);
int titleWidth = titleFontMetrics.stringWidth(title);
int q = titleFontMetrics.getAscent();
int p = (clientWidth - titleWidth) / 2;
graphics.setFont(titleFont);
graphics.drawString(title, p, q);
int top = titleFontMetrics.getHeight();
int bottom = labelFontMetrics.getHeight();
if (maxValue == minValue) {
return;
}
double scale = (clientHeight - top - bottom) / (maxValue - minValue);
q = clientHeight - labelFontMetrics.getDescent();
graphics.setFont(labelFont);
for (int j = 0; j < value.length; j++) {
int valueP = j * barWidth + 1;
int valueQ = top;
int height = (int) (value[j] * scale);
if (value[j] >= 0) {
valueQ += (int) ((maxValue - value[j]) * scale);
} else {
valueQ += (int) (maxValue * scale);
height = -height;
}
graphics.setColor(Color.blue);
graphics.fillRect(valueP, valueQ, barWidth - 2, height);
graphics.setColor(Color.black);
graphics.drawRect(valueP, valueQ, barWidth - 2, height);
int labelWidth = labelFontMetrics.stringWidth(languages[j]);
p = j * barWidth + (barWidth - labelWidth) / 2;
graphics.drawString(languages[j], p, q);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(350, 300);
double[] value = new double[5];
String[] languages = new String[5];
value[0] = 1;
languages[0] = "Visual Basic";
value[1] = 2;
languages[1] = "PHP";
value[2] = 3;
languages[2] = "C++";
value[3] = 4;
languages[3] = "C";
value[4] = 5;
languages[4] = "Java";
frame.getContentPane().add(new SimpleBarChart(value, languages,
"Programming Languages"));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Also see JFreeChart and if you dont mind using an external library.
Example that you might need via #trashGod : example and its source code.
I have a series of components underneath each other in a JPanel set as a GridLayout.
I need to temporarily hide the components but setVisible(false) doesn't cut it, because there is still an empty gap where the components were.
Is there a quick and easy way to do this? Or do I have to stay saving the state of the JPanel, removing the components, then restoring it?
SSCCE:
[GridLayout2.java]
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
public class GridLayout2 extends GridLayout
{
public GridLayout2() {
this(1, 0, 0, 0);
}
public GridLayout2(int rows, int cols) {
this(rows, cols, 0, 0);
}
public GridLayout2(int rows, int cols, int hgap, int vgap) {
super(rows, cols, hgap, vgap);
}
public Dimension preferredLayoutSize(Container parent) {
//System.err.println("preferredLayoutSize");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
}
else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i ++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
int nw = 0;
for (int j = 0; j < ncols; j ++) {
nw += w[j];
}
int nh = 0;
for (int i = 0; i < nrows; i ++) {
nh += h[i];
}
return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(),
insets.top + insets.bottom + nh + (nrows-1)*getVgap());
}
}
public Dimension minimumLayoutSize(Container parent) {
System.err.println("minimumLayoutSize");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
}
else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i ++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getMinimumSize();
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
int nw = 0;
for (int j = 0; j < ncols; j ++) {
nw += w[j];
}
int nh = 0;
for (int i = 0; i < nrows; i ++) {
nh += h[i];
}
return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(),
insets.top + insets.bottom + nh + (nrows-1)*getVgap());
}
}
public void layoutContainer(Container parent) {
//System.err.println("layoutContainer");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (ncomponents == 0) {
return;
}
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
}
else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int hgap = getHgap();
int vgap = getVgap();
// scaling factors
Dimension pd = preferredLayoutSize(parent);
double sw = (1.0 * parent.getWidth()) / pd.width;
double sh = (1.0 * parent.getHeight()) / pd.height;
// scale
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i ++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
d.width = (int) (sw * d.width);
d.height = (int) (sh * d.height);
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
for (int c = 0, x = insets.left; c < ncols; c ++) {
for (int r = 0, y = insets.top; r < nrows; r ++) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, w[c], h[r]);
}
y += h[r] + vgap;
}
x += w[c] + hgap;
}
}
}
}
[SSCCE.java]
import java.awt.Color;
import javax.swing.*;
import javax.swing.border.*;
public class SSCCE extends JFrame{
JPanel innerPane = new JPanel();
JScrollPane scr = new JScrollPane(innerPane);
public static void main(String[] args) {
new SSCCE();
}
public SSCCE() {
setSize(400, 800);
innerPane.setLayout(new GridLayout2(0, 1));
add(scr);
for (int i = 0; i < 30; i++)
{
innerPane.add(getPane());
}
setVisible(true);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
for (int i = 0; i < 30; i++)
{
if (i%2==0)
innerPane.getComponent(i).setVisible(false);
}
}
private JPanel getPane()
{
JPanel ret = new JPanel();
JLabel lbl = new JLabel("This is a pane.");
ret.add(lbl);
ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
ret.setBackground(Color.gray);
return ret;
}
}
because there is still an empty gap where the components were.
Yes, GridLayout is not that smart. It just uses the total number of components to determine the number of row/columns.
Is there a quick and easy way to do this?
I would create a custom layout manager. Just copy the GridLayout code and make a couple of changes. The basic changes would be:
Override the ncomponents variable. Instead of just using the number of components on the panel you would need to loop thorugh all the components and count the visible ones.
In the layout code you would need to add an if (visible) check.
Edit:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class InvisibleGridLayout implements LayoutManager, java.io.Serializable
{
int hgap;
int vgap;
int rows;
int cols;
public InvisibleGridLayout() {
this(1, 0, 0, 0);
}
public InvisibleGridLayout(int rows, int cols) {
this(rows, cols, 0, 0);
}
public InvisibleGridLayout(int rows, int cols, int hgap, int vgap) {
if ((rows == 0) && (cols == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.rows = rows;
this.cols = cols;
this.hgap = hgap;
this.vgap = vgap;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
if ((rows == 0) && (this.cols == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.rows = rows;
}
public int getColumns() {
return cols;
}
public void setColumns(int cols) {
if ((cols == 0) && (this.rows == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.cols = cols;
}
public int getHgap() {
return hgap;
}
public void setHgap(int hgap) {
this.hgap = hgap;
}
public int getVgap() {
return vgap;
}
public void setVgap(int vgap) {
this.vgap = vgap;
}
public void addLayoutComponent(String name, Component comp) {
}
public void removeLayoutComponent(Component comp) {
}
public Dimension preferredLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
// int ncomponents = parent.getComponentCount();
int ncomponents = getVisibleComponents(parent);
int nrows = rows;
int ncols = cols;
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int w = 0;
int h = 0;
// for (int i = 0 ; i < ncomponents ; i++) {
for (int i = 0 ; i < parent.getComponentCount(); i++) {
Component comp = parent.getComponent(i);
if (!comp.isVisible()) continue; // added
Dimension d = comp.getPreferredSize();
if (w < d.width) {
w = d.width;
}
if (h < d.height) {
h = d.height;
}
}
Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
return d;
}
}
public Dimension minimumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
// int ncomponents = parent.getComponentCount();
int ncomponents = getVisibleComponents(parent);
int nrows = rows;
int ncols = cols;
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int w = 0;
int h = 0;
// for (int i = 0 ; i < ncomponents ; i++) {
for (int i = 0 ; i < parent.getComponentCount(); i++) {
Component comp = parent.getComponent(i);
if (!comp.isVisible()) continue; // added
Dimension d = comp.getMinimumSize();
if (w < d.width) {
w = d.width;
}
if (h < d.height) {
h = d.height;
}
}
Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
return d;
}
}
public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
// int ncomponents = parent.getComponentCount();
int ncomponents = getVisibleComponents(parent);
int nrows = rows;
int ncols = cols;
boolean ltr = parent.getComponentOrientation().isLeftToRight();
if (ncomponents == 0) {
return;
}
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
// int w = parent.width - (insets.left + insets.right);
// int h = parent.height - (insets.top + insets.bottom);
int w = parent.getSize().width - (insets.left + insets.right);
int h = parent.getSize().height - (insets.top + insets.bottom);
w = (w - (ncols - 1) * hgap) / ncols;
h = (h - (nrows - 1) * vgap) / nrows;
/*
if (ltr) {
for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) {
for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, w, h);
}
}
}
} else {
// for (int c = 0, x = parent.width - insets.right - w; c < ncols ; c++, x -= w + hgap) {
for (int c = 0, x = parent.getSize().width - insets.right - w; c < ncols ; c++, x -= w + hgap) {
for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, w, h);
}
}
}
}
}
*/
int i = 0;
if (ltr)
{
for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap)
{
int c = 0;
int x = insets.left;
while (c < ncols)
{
if (i >= parent.getComponentCount()) break;
Component component = parent.getComponent(i);
if (component.isVisible())
{
parent.getComponent(i).setBounds(x, y, w, h);
c++;
x += w + hgap;
}
i++;
}
}
}
}}
private int getVisibleComponents(Container parent)
{
int visible = 0;
for (Component c: parent.getComponents())
{
if (c.isVisible())
visible++;
}
return visible;
}
public String toString() {
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
",rows=" + rows + ",cols=" + cols + "]";
}
public static void main(String[] args)
{
final JPanel innerPane = new JPanel();
JScrollPane scr = new JScrollPane(innerPane);
innerPane.setLayout(new InvisibleGridLayout(0, 3));
for (int i = 0; i < 30; i++)
{
JPanel ret = new JPanel();
JLabel lbl = new JLabel("This is pane " + i);
ret.add(lbl);
ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
ret.setBackground(Color.gray);
innerPane.add(ret);
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scr);
frame.setBounds(400, 0, 400, 700);
frame.setVisible(true);
javax.swing.Timer timer = new javax.swing.Timer(2000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < 30; i++)
{
if (i%2==0)
innerPane.getComponent(i).setVisible(false);
}
}
});
timer.setRepeats(false);
timer.start();
}
}
Here are 3 ways off the top of my head.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class HideComponents {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel gui = new JPanel(new BorderLayout());
JToolBar tb = new JToolBar();
gui.add(tb, BorderLayout.NORTH);
final JButton openTool = new JButton("Open");
final JButton saveTool = new JButton("Save");
tb.add( openTool );
tb.add( saveTool );
JPanel buttonFlow = new JPanel(new FlowLayout(3));
gui.add(buttonFlow, BorderLayout.CENTER);
final JButton openFlow = new JButton("Open");
final JButton saveFlow = new JButton("Save");
buttonFlow.add( openFlow );
buttonFlow.add( saveFlow );
JPanel buttonBox = new JPanel();
gui.add(buttonBox, BorderLayout.EAST);
BoxLayout bl = new BoxLayout(buttonBox, BoxLayout.Y_AXIS);
buttonBox.setLayout(bl);
final JButton openBox = new JButton("Open");
final JButton saveBox = new JButton("Save");
buttonBox.add( openBox );
buttonBox.add( saveBox );
final JCheckBox openChoice = new JCheckBox("Show open", true);
openChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
openTool.setVisible(openChoice.isSelected());
openFlow.setVisible(openChoice.isSelected());
openBox.setVisible(openChoice.isSelected());
}
});
gui.add(openChoice, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
On reflection
Please consider swapping:
button.setVisible(false);
For:
button.setEnabled(false);
This will be more intuitive to most users who view the GUI, and has the same ultimate effect.
Vis:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class DisableComponents {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel gui = new JPanel(new BorderLayout());
JToolBar tb = new JToolBar();
gui.add(tb, BorderLayout.NORTH);
final JButton openTool = new JButton("Open");
final JButton saveTool = new JButton("Save");
tb.add( openTool );
tb.add( saveTool );
JPanel buttonFlow = new JPanel(new FlowLayout(3));
gui.add(buttonFlow, BorderLayout.CENTER);
final JButton openFlow = new JButton("Open");
final JButton saveFlow = new JButton("Save");
buttonFlow.add( openFlow );
buttonFlow.add( saveFlow );
JPanel buttonBox = new JPanel();
gui.add(buttonBox, BorderLayout.EAST);
BoxLayout bl = new BoxLayout(buttonBox, BoxLayout.Y_AXIS);
buttonBox.setLayout(bl);
final JButton openBox = new JButton("Open");
final JButton saveBox = new JButton("Save");
buttonBox.add( openBox );
buttonBox.add( saveBox );
final JCheckBox openChoice = new JCheckBox("Enable open", true);
openChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
openTool.setEnabled(openChoice.isSelected());
openFlow.setEnabled(openChoice.isSelected());
openBox.setEnabled(openChoice.isSelected());
}
});
gui.add(openChoice, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
don't call Thread.sleep(int); during EDT, because block EDT, use javax.swing.Timer
for example
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.*;
public class SSCCE extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel innerPane = new JPanel();
private JScrollPane scr = new JScrollPane(innerPane);
private Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SSCCE sSCCE = new SSCCE();
}
});
}
private JPanel getPane() {
JPanel ret = new JPanel();
JLabel lbl = new JLabel("This is a pane.");
ret.add(lbl);
ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
ret.setBackground(Color.gray);
return ret;
}
public SSCCE() {
innerPane.setLayout(new GridLayout(0, 1));
add(scr);
for (int i = 0; i < 30; i++) {
innerPane.add(getPane());
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
start();
}
private void start() {
timer = new javax.swing.Timer(2000, updateCol());
timer.start();
timer.setRepeats(false);
}
private Action updateCol() {
return new AbstractAction("Hide Row Action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 30; i++) {
if (i % 2 == 0) {
innerPane.getComponent(i).setVisible(false);
}
}
}
};
}
}
I really don't like the GridLayout. Instead of writing your own layout manager, I would suggest you take a look at the TableLayout. I use it all the time.
The initial learning curve is a bit steeper than the GridLayout, but it is easy to get it to behave the way you want.
http://java.sun.com/products/jfc/tsc/articles/tablelayout/
try to use BoxLayout with component alignment. For example:
JPanel innerPane = new JPanel();
BoxLayout innerPaneLayout = new BoxLayout(innerPane,BoxLayout.Y_AXIS);
innerPane.setLayout(innerPaneLayout);
for (int i = 0; i < 30; i++)
{
JPane newPane = getPane();
innerPane.add(newPane);
newPane.setAlignmentY(Component.TOP_ALIGNMENT);
}
for (int i = 0; i < 30; i++)
{
if (i%2==0)
innerPane.getComponent(i).setVisible(false);
}
Just for completeness of the answers, you are free to add() and remove() components to and from a layout in order for them not to occupy space.
That can be a simpler solution sometimes than dealing with custom layouts.
I'm not a Java Swing expert but you may need to invalidate/revalidate the layout when adding/removing components. Methods invalidate(), revalidate() and repaint() may be useful.