JXMultiSplitPane causes repaint during slider adjustment? - java

I seem to be getting frequent repaint requests during adjustment of the splitter in JXMultiSplitPane. (see program below)
Why?
I have setContinuousLayout(false).
Just to clarify: I understand the repaint should occur after the split-panes are resized. But during splitter adjustment, nothing is being resized; the splitter is moving around on the screen.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jdesktop.swingx.JXMultiSplitPane;
import org.jdesktop.swingx.MultiSplitLayout;
public class MultiVerticalPane<T extends Component> extends JPanel
{
final private List<T> components;
public MultiVerticalPane(List<? extends T> components,
List<Double> weights)
{
this.components = new ArrayList<T>(components);
final int n = this.components.size();
if (weights != null && weights.size() != n)
throw new IllegalArgumentException(
"weights and components should have same length");
JXMultiSplitPane msp = new JXMultiSplitPane();
msp.setContinuousLayout(false);
msp.getMultiSplitLayout().setModel(createSplitModel(weights));
int i = 0;
for (T component : components)
{
msp.add(component, nodeTitle(i++));
}
setLayout(new BorderLayout());
add(msp, BorderLayout.CENTER);
}
private MultiSplitLayout.Split createSplitModel(
List<Double> weights)
{
LinkedList<MultiSplitLayout.Node> nodes =
new LinkedList<MultiSplitLayout.Node>();
int i = 0;
double wtot = 0;
for (double w : weights)
{
wtot += w;
}
for (double w : weights)
{
if (i > 0)
nodes.addFirst(new MultiSplitLayout.Divider());
MultiSplitLayout.Leaf leaf =
new MultiSplitLayout.Leaf(nodeTitle(i++));
leaf.setWeight(w/wtot);
nodes.addFirst(leaf);
}
MultiSplitLayout.Split split =
new MultiSplitLayout.Split();
split.setRowLayout(false);
split.setChildren(nodes);
return split;
}
private String nodeTitle(int i) {
return String.format("%02d", i);
}
/************ test methods *************/
private interface Painter
{
public void paint(Graphics g, Rectangle bounds);
}
static private class RelativeGraphics
{
final private Graphics g;
final private double xofs;
final private double yofs;
final private double xscale;
final private double yscale;
private double cx;
private double cy;
public RelativeGraphics(Graphics g, Rectangle bounds)
{
this.g = g;
this.cx = 0;
this.cy = 0;
this.xofs = bounds.getMinX();
this.yofs = bounds.getMaxY();
this.xscale = bounds.getWidth();
this.yscale = -bounds.getHeight();
}
public void moveTo(double x, double y)
{
this.cx = x;
this.cy = y;
}
public void lineTo(double x, double y)
{
this.g.drawLine(
(int)(this.cx*this.xscale+this.xofs),
(int)(this.cy*this.yscale+this.yofs),
(int)(x*this.xscale+this.xofs),
(int)(y*this.yscale+this.yofs)
);
moveTo(x,y);
}
public void rmoveTo(double dx, double dy)
{
moveTo(this.cx+dx, this.cy+dy);
}
public void rlineTo(double dx, double dy)
{
lineTo(this.cx+dx, this.cy+dy);
}
}
// adapted from http://en.wikipedia.org/wiki/Hilbert_curve#Java
static private class HilbertCurve
{
final private RelativeGraphics rg;
final private double d;
public HilbertCurve(RelativeGraphics rg, int level)
{
this.rg = rg;
double d0 = 1.0;
for (int i = level; i > 0; i--)
d0 /= 2;
this.d = d0;
rg.rmoveTo(d0/2, d0/2);
drawCurveUp(level);
}
private void drawCurveUp(int n)
{
if (n > 0) {
drawCurveLeft(n-1); this.rg.rlineTo(0, this.d);
drawCurveUp(n-1); this.rg.rlineTo(this.d, 0);
drawCurveUp(n-1); this.rg.rlineTo(0, -this.d);
drawCurveRight(n-1);
}
}
private void drawCurveLeft(int n)
{
if (n > 0) {
drawCurveUp(n-1); this.rg.rlineTo(this.d, 0);
drawCurveLeft(n-1); this.rg.rlineTo(0, this.d);
drawCurveLeft(n-1); this.rg.rlineTo(-this.d, 0);
drawCurveDown(n-1);
}
}
private void drawCurveRight(int n)
{
if (n > 0) {
drawCurveDown(n-1); this.rg.rlineTo(-this.d, 0);
drawCurveRight(n-1); this.rg.rlineTo(0, -this.d);
drawCurveRight(n-1); this.rg.rlineTo(this.d, 0);
drawCurveUp(n-1);
}
}
private void drawCurveDown(int n)
{
if (n > 0) {
drawCurveRight(n-1); this.rg.rlineTo(0, -this.d);
drawCurveDown(n-1); this.rg.rlineTo(-this.d, 0);
drawCurveDown(n-1); this.rg.rlineTo(0, this.d);
drawCurveLeft(n-1);
}
}
}
static private class HilbertPainter implements Painter
{
final private int level;
public HilbertPainter(int level) { this.level = level; }
#Override public void paint(Graphics g, Rectangle bounds) {
new HilbertCurve(
new RelativeGraphics(g,
new Rectangle(new Point(0,0),bounds.getSize())),
this.level);
}
}
static private class PainterPanel extends JPanel
{
final private Painter painter;
public PainterPanel(Painter painter)
{
this.painter = painter;
setBackground(Color.WHITE);
setForeground(Color.RED);
}
#Override public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.painter.paint(g, getBounds());
}
}
public static void main(String[] args) { test(); }
private static void test()
{
JFrame frame = new JFrame("MultiVerticalPane test");
List<JPanel> panels = new ArrayList<JPanel>();
List<Double> weights = Arrays.asList(1.0,1.0,2.0,4.0,8.0);
for (int i = 0; i < 5; ++i)
{
panels.add(new PainterPanel(new HilbertPainter(i+4)
{
int count = 0;
#Override public void paint(Graphics g,
Rectangle bounds)
{
super.paint(g,
new Rectangle(bounds.getLocation(),
new Dimension(bounds.width,
bounds.height-10)));
g.drawString(String.format("%d", this.count++),
0, bounds.height);
}
}
));
}
MultiVerticalPane<Component> mvp =
new MultiVerticalPane<Component>(panels, weights);
mvp.setPreferredSize(new Dimension(360,720));
frame.setContentPane(mvp);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

It looks like setContinuousLayout() affects revalidate(), not repaint().

Its not a 'direct' answer. I just put it here since I run out of space in a comment.
I do not think it is too frequent? Why would you think that did you compare it with any other component?
What I think is that every resize a component detects it calls repaint. On top of it goes how a layout manager handles resizing. Please observe that when, for example, you resize the top most panel and are dragging it down it is very rarely repainted, which you cannot say about his neighbour. The situation is reversed when you drag the slider up.
BTW: Might I ask why would you worry about how often and which part of the split pane is repainted?
Please bear in mind that I am not an expert on the internals of the repaint mechanism of this component but I would doubt that SwingX guys would step away from the defaults in this regards.

Related

How to draw a bar in this example?

In this exercise, when you enter the name of a city and its population, in the window it must be graphed a bar that represents the population of that city as shown in the figures, the exercise is almost complete but it doesn't work, could someone tell me what I'm doing wrong?, Why is no bar drawn?, the condition that makes the exercise a bit more difficult to me is that the size of the bars and lines must change if the window size changes. The main class can't be modified because is already given.
package Hw02_Statistics;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import hw01_clocknumbers.DigitalNumber;
public class Statistics extends JFrame {
private JLabel city, population, other;
private JTextField tcity, tpopulation;
private JButton add;
private JTable table;
private DefaultTableModel tablem;
private int index=1;
private bar bars;
public Statistics() {
setTitle("Statistics");
setSize(500, 350);
setupWidgets();
seupEvents();
setVisible(true);
}
private void setupWidgets() {
bars = new bar();
city = new JLabel("City",JLabel.LEFT);
population = new JLabel("Population",JLabel.LEFT);
tcity = new JTextField();
other = new JLabel();
tpopulation = new JTextField();
add = new JButton("Add");
tablem = new DefaultTableModel(new Object[] {"Index", "City", "Population"}, 0);
table = new JTable(tablem);
JPanel norte = new JPanel(new GridLayout(5,1));
JPanel sur = new JPanel(new GridLayout(1,2));
add(norte, BorderLayout.NORTH);
add(sur, BorderLayout.CENTER);
norte.add(city);
norte.add(tcity);
norte.add(population);
norte.add(tpopulation);
norte.add(add);
sur.add(new JScrollPane(table));
sur.add(bars);
}
private void seupEvents() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!tcity.getText().equals("") && !tpopulation.getText().equals("")) {
Object rowinfo[] = {index, tcity.getText(), tpopulation.getText()};
tablem.addRow(rowinfo);
int n= Integer.parseInt(tpopulation.getText());
bars.setScale(1, index);
tcity.setText("");
tpopulation.setText("");
index++;
}
}
});
}
public static void main(String[] args) {
new Statistics();
}
}
This is the second class I used
package Hw02_Statistics;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JComponent;
import hw01_clocknumbers.DigitalNumber;
public class bar extends JComponent {
private int digit;
private Integer scale=0;
private int index;
private rect rects[];
public bar () {
}
public void paint(Graphics g) {
int w =getWidth();
int h =getHeight();
rects = new rect[4];
rects[index] = new rect(scale, index, w, h);
// System.out.println(w); 243
// System.out.println(h); 183
g.drawLine(w/12, h/9, w/12, 8*h/9);
g.drawLine(w/12, 8*h/9, 12*w/12, 8*h/9);
}
public void setScale(Integer scale, int index) {
this.index=index-1;
this.scale=scale;
repaint();
}
}
And this is the last Class I used, and it is the one that doesn't work
package Hw02_Statistics;
import java.awt.Graphics;
import javax.swing.JComponent;
public class rect extends JComponent{
private int scale;
private int index;
private int w, h;
public rect(int scale, int index, int w, int h) {
this.scale = scale;
this.index= index;
this.w =w;
this.h=h;
}
public void paint(Graphics e) {
e.fillRect(6*w/12+w*index/12,h/9,scale*w/12,scale*7*h/9);
System.out.println("Aaaa");
repaint();
}
}
class bar (which should be called Bar according to java naming conventions) was renamed to Bars and changed to hold and draw all bars:
class Bars extends JComponent {
//collection of bar heights
private final List<Integer> barsValues;
private static final int W = 20; //bar width
public Bars () {
barsValues = new ArrayList<>();
}
//override paintComponent rather than paint
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); //always call super
int w = getWidth();
int h = getHeight();
//use double to avoid rounding errors
double minX = w/12 , maxX = 12*minX, maxY = h/9, minY = 8 * maxY;
double graphHeight = minY - maxY;
//draw axis
g.drawLine((int)minX, (int)maxY, (int)minX, (int)minY);
g.drawLine((int)minX, (int)minY, (int)maxX, (int)minY);
//draw bars
if(barsValues.size() == 0) return;
double x = minX + W ;
int maxHeight = getMaxHeight(); //calculate scale based on max height
double scale = maxHeight > 0 ? graphHeight / getMaxHeight() : 1;
for(int barValue : barsValues){
double barHeight = scale*barValue;
g.fillRect((int)x ,(int)(minY - barHeight), W, (int)barHeight);
x += 2*W;
}
}
//add bar values. valid values should be > 0
void addBar(int height) {
barsValues.add(height);
repaint();
}
//get max height
int getMaxHeight(){
int max = 0;
for (int value : barsValues){
if(value > max) {
max = value;
}
}
return max;
}
}
class rect is not needed.
To test you need to do some minor changes in Statistics:
change private bar bars; to private Bars bars;
Initialize it by bars = new Bars();
and change one line in the action listener from bars.setScale(1, index) to bars.addBar(n);
The complete code can be copy-pasted from here

java jpanel how to optimise painting

I am trying to implement langton's ant , and i did it well :
langton's ant java simulation screen
for painting in my jPanel, i override the paintComponent at each step but it take so much time for painting every black or white rectangle , i just want that at each step i only paint the two rectangle who have changed!?
So my question is, how to only paint a rectangle without changing what was painted in previous frame?
here is my code for painting
public void paintComponent(Graphics g){
g.setColor(Color.white);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.black);
int careLargeur = getWidth() / m;
int careHauteur = getHeight() / n;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(map[i][j])
g.fillRect(j*careLargeur,i*careHauteur,careLargeur,careHauteur);
}
//draw fourmi
g.setColor(Color.red);
g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}
any help? or should i give more details ?
here is the jar :
Paint your rectangles to a BufferedImage, and then draw that BufferedImage within your paintComponent method. You could also limit how much is re-drawn by using one of the repaint(...) overrides that specifies the exact rectangular region to repaint.
So your paintComponent method could be as simple as this:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
g.setColor(Color.red);
g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}
With drawing changes being made to the img BufferedImage.
Assuming that you're using a Swing Timer to drive the state changes to your model, you could
change the model, and then
update the BufferedImage based on the model changes, and
call repaint(...) on only the updated region.
Incomplete code attempt.... not yet done!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
/**
* https://en.wikipedia.org/wiki/Langton%27s_ant
* https://stackoverflow.com/a/44930371/522444
* #author Pete
*
*/
public class LangtonsAnt {
private static final int TIMER_DELAY = 30;
private static void createAndShowGui() {
Model model = new Model(800);
View view = new View(800);
Controller controller = new Controller(model, view);
JFrame frame = new JFrame("Langtons Ant");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
controller.startTimer(TIMER_DELAY);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static class Model {
public static final String POINT = "point";
private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
private int gridSize;
private boolean[][] grid; // false is white. Better to use enums
private Point oldValue;
private Point point; // ant location
public Model(int gridSize) {
this.gridSize = gridSize;
grid = new boolean[gridSize][gridSize];
int x = gridSize / 2;
int y = gridSize / 2;
setPoint(new Point(x, y));
}
public void setPoint(Point point) {
this.oldValue = this.point;
Point newValue = point;
this.point = point;
support.firePropertyChange(POINT, oldValue, newValue);
}
public Point getPoint() {
return point;
}
public boolean[][] getGrid() {
return grid;
}
public int getGridSize() {
return gridSize;
}
public void step() {
// first will hold relative new positions
int newX = 0;
int newY = 0;
boolean gridPoint = getGridPoint(point);
if (oldValue == null) {
newX = point.x;
newY = point.y - 1;
} else {
int dX = point.x - oldValue.x;
int dY = point.y - oldValue.y;
if (dX != 0) {
// from left or right
newY = dX > 0 ? 1 : -1; // assume "white" or false
newY = gridPoint ? -newY : newY; // if "black" then reverse
} else {
// from up or down
newX = dY > 0 ? -1 : 1; // assume "white" or false
newX = gridPoint ? -newX : newX; // if "black" then reverse
}
// convert from relative to absolute new positions
newX = point.x + newX;
newY = point.y + newY;
}
setGridPoint(point, !gridPoint);
setPoint(new Point(newX, newY));
}
public boolean getGridPoint(int x, int y) {
return grid[x][y];
}
public boolean getGridPoint(Point p) {
return getGridPoint(p.x, p.y);
}
public void setGridPoint(int x, int y, boolean b) {
grid[x][y] = b;
}
public void setGridPoint(Point p, boolean b) {
setGridPoint(p.x, p.y, b);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
support.addPropertyChangeListener(propertyName, l);
}
}
private static class Controller {
private Model model;
private View view;
private Timer timer;
public Controller(Model model, View view) {
this.model = model;
this.view = view;
view.setAntImg(createAntImg());
model.addPropertyChangeListener(Model.POINT, new ModelListener());
}
private BufferedImage createAntImg() {
// trivial image for now
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor(Color.RED);
g.fillRect(0, 0, 1, 1);
g.dispose();
return img;
}
public void startTimer(int delay) {
timer = new Timer(delay, new TimerListener());
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
model.step();
}
}
private class ModelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO Finish this.
// get the new point and old point
// translate model coord to view coord
// Change the state of the view's buffered image
// repaint the limited region that was changed
}
}
}
private static class View extends JPanel {
private static final Color BACKGROUND = Color.WHITE;
private BufferedImage gridImg;
private BufferedImage antImg;
private Point guiAntLocation;
private int pixelWidth;
public View(int pixelWidth) {
this.pixelWidth = pixelWidth;
gridImg = new BufferedImage(pixelWidth, pixelWidth, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = gridImg.createGraphics();
g2.setColor(BACKGROUND);
g2.fillRect(0, 0, pixelWidth, pixelWidth);
g2.dispose();
}
public int getPixelWidth() {
return pixelWidth;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (getGridImg() != null) {
g.drawImage(getGridImg(), 0, 0, this);
}
if (guiAntLocation != null && antImg != null) {
int x = guiAntLocation.x;
int y = guiAntLocation.y;
g.drawImage(antImg, x, y, this);
}
}
public void setGuiAntLocation(Point guiAntLocation) {
this.guiAntLocation = guiAntLocation;
}
public Point getGuiAntLocation() {
return guiAntLocation;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || getGridImg() == null) {
return super.getPreferredSize();
}
return new Dimension(getGridImg().getWidth(), getGridImg().getHeight());
}
public BufferedImage getGridImg() {
return gridImg;
}
public void setGridImg(BufferedImage gridImg) {
this.gridImg = gridImg;
}
public void setAntImg(BufferedImage antImg) {
this.antImg = antImg;
}
}
}

Generating specific shapes with random dimensions using a JComboBox to select shapes

I am trying to create a program that uses a JComboBox containing specific shapes (Circle, Square, Oval, Rectangle). After the user clicks on a specified shape, the Panel will display 20 of that shape in random dimensions and locations.
I am having trouble on how to make the shapes have random dimensions and locations. Here is my code so far. Any advice or sources to look at would be appreciated.
Thank you.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.awt.event.*;
public class HW1b extends JFrame
{
public HW1b()
{
super("Shapes");
final ComboPanel comboPanel = new ComboPanel();
String[] shapeItems = {"Circle", "Square", "Oval", "Rectangle"};
JComboBox shapeBox = new JComboBox<String>(shapeItems);
shapeBox.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ie)
{
if (ie.getStateChange() == ItemEvent.SELECTED)
{
String item = (String)ie.getItem();
if(shapeBox.getSelectedItem().equals("Circle"))
comboPanel.makeCircles();
if(shapeBox.getSelectedItem().equals("Square"))
comboPanel.makeSquares();
if(shapeBox.getSelectedItem().equals("Oval"))
comboPanel.makeOvals();
if(shapeBox.getSelectedItem().equals("Rectangle"))
comboPanel.makeRectangles();
}
}
});
JPanel southPanel = new JPanel();
southPanel.add(shapeBox);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().add(comboPanel, "Center");
getContentPane().add(southPanel, "South");
setSize( 400, 400 );
setLocation( 200, 200 );
setVisible( true );
}
private class ComboPanel extends JPanel
{
int w, h;
Random rand;
static final int OVAL = 0;
static final int RECTANGLE = 1;
int shapeType = -1;
public ComboPanel()
{
rand = new Random();
setBackground(Color.white);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int width = getWidth();
int height = getHeight();
int x, y;
Shape s = null;
for (int i = 0; i < 20; i++)
{
x = rand.nextInt(width - w);
y = rand.nextInt(width - h);
switch(shapeType)
{
case OVAL: s = new Ellipse2D.Double(x,y,w,h);
break;
case RECTANGLE: s = new Rectangle2D.Double(x,y,w,h);
break;
}
if (shapeType > -1)
g2d.draw(s);
}
}
public void makeCircles()
{
shapeType = OVAL;
w = 75;
h = 75;
repaint();
}
public void makeSquares()
{
shapeType = RECTANGLE;
w = 50;
h = 50;
repaint();
}
public void makeOvals()
{
shapeType = OVAL;
w = 80;
h = 60;
repaint();
}
public void makeRectangles()
{
shapeType = RECTANGLE;
w = 80;
h = 40;
repaint();
}
}
public static void main(String[] args)
{
new HW1b();
}
}
You're hard-coding w and h in your code, and so there's no way for this to vary among your shapes. Instead of doing this, use your Random variable, rand, to select random w and h values that are within some desired range. Myself, I wouldn't create my shapes within the paintComponent method since painting is not fully under my control and can occur when I don't want it to. For instance, in your code, your shapes will vary tremendously if the GUI is resized. Instead I'd create a collection such as an ArrayList<Shape> and fill it with created Shape objects (i.e., Ellipse2D for my circles) when desired, and then iterate through that collection within your paintComponent method, drawing your shapes.
for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class SomeShapes extends JPanel {
private ShapePanel shapePanel = new ShapePanel();
private JComboBox<MyShape> myShapeCombo = new JComboBox<>(MyShape.values());
public SomeShapes() {
myShapeCombo.setSelectedIndex(-1);
myShapeCombo.addItemListener(new ComboListener());
JPanel bottomPanel = new JPanel();
bottomPanel.add(myShapeCombo);
setLayout(new BorderLayout());
add(shapePanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private class ComboListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent e) {
MyShape myShape = (MyShape) e.getItem();
shapePanel.drawShapes(myShape);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SomeShapes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SomeShapes());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum MyShape {
OVAL("Oval"), RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private MyShape(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
class ShapePanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Color SHAPE_COLOR = Color.BLUE;
private static final int SHAPE_COUNT = 20;
private static int MIN = 5;
private static int MAX = 200;
private List<Shape> shapeList = new ArrayList<>();
private Random random = new Random();
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public void drawShapes(MyShape myShape) {
shapeList.clear(); // empty the shapeList
switch (myShape) {
case OVAL:
drawOval();
break;
case RECTANGLE:
drawRectangle();
break;
// etc...
default:
break;
}
repaint();
}
private void drawOval() {
// for loop to do this times SHAPE_COUNT(20) times.
for (int i = 0; i < SHAPE_COUNT; i++) {
// first create random width and height
int w = random.nextInt(MAX - MIN) + MIN;
int h = random.nextInt(MAX - MIN) + MIN;
// then random location, but taking care so that it
// fully fits into our JPanel
int x = random.nextInt(getWidth() - w);
int y = random.nextInt(getHeight() - h);
// then create new Shape and place in our shapeList.
shapeList.add(new Ellipse2D.Double(x, y, w, h));
}
}
private void drawRectangle() {
// .... etc
}
//.. .. etc
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
// set rendering hints for smooth ovals
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(SHAPE_COLOR);
// iterate through the shapeList ArrayList
for (Shape shape : shapeList) {
g2d.draw(shape); // and draw each Shape it holds
}
}
}

Drawing on a Jframe from two different classes

I am trying to create a program that record mouse clicks, draw lines between those points and after some calculations display some circles through a button call. My problem is that I can display the lines or the circles, but not both.
I know there is something overlapping something else, but I am very new to Java and I don't know how to fix it. Here is the code:
package fempack;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.lang.Math;
public class MainFem extends JPanel {
final DrawPoints Npoints = new DrawPoints();
final DrawLines Nline = new DrawLines();
private static final long serialVersionUID = 1L;
private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
public int Xpoint[][] = new int[500][30];
public int Ypoint[][] = new int[500][30];
private double Xmpoint[][] = new double[500][1000]; // [i γραμμή][συντεταγμένη Χ]
private double Ympoint[][] = new double[500][1000];
private double Vec[][][] = new double[500][2][500]; // [i γραμμή][0,1][0α 1β]
private double dist[] = new double[10000];
private boolean drawing;
private int c1;
private int c2;
public MainFem() {
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
// -------------- Draw by clicking -----------------------
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e)){
drawing=false;
c2++;
}
if(SwingUtilities.isLeftMouseButton(e)){
p1 = e.getPoint();
Xpoint[c1][c2] = p1.x;
Ypoint[c1][c2] = p1.y;
if (c1 > 3) {
for (int j = 0; j<c2+1; j++){
for (int i = 0; i<c1; i++){
if ((Math.abs(Xpoint[i][j]-Xpoint[c1][c2]) < 10) && (Math.abs(Ypoint[i][j]-Ypoint[c1][c2]) < 10)) {
Xpoint[c1][c2] = Xpoint[i][j];
Ypoint[c1][c2] = Ypoint[i][j];
System.out.println(Xpoint[i][j]);
}
}
}
}
if (drawing == true){
Nline.addLine(Xpoint[c1][c2], Ypoint[c1][c2], Xpoint[c1-1][c2], Ypoint[c1-1][c2]);
}
c1++;
drawing = true;
}
}
}
// ---------------- Create Mesh Points --------------------------
public void createmesh() {
int mdi = 0;
for (int j = 0; j<=c2; j++){
for (int i = 0; i<c1-1; i++){
// Υπολογισμός a και b συνιστωσών της εξίσωσης της γραμμής
Vec[i][0][mdi] = (Ypoint[i+1][j] - Ypoint[i][j])/(Xpoint[i+1][j] - Xpoint[i][j]);
Vec[i][1][mdi] = Ypoint[i][j] - Xpoint[i][j]*Vec[i][1][mdi];
// Υπολογισμός μέτρου διανύσματος
dist[mdi] = Math.sqrt(Math.pow(Xpoint[i][j] - Xpoint[i+1][j], 2) + Math.pow(Ypoint[i][j] - Ypoint[i+1][j], 2) );
// Υπολογισμός ενδιάμεσον σημείων
int nkom = 3;
double xa = Xpoint[i][j];
double ya = Ypoint[i][j];
for (int ii = 0; ii <nkom; ii++) {
double a = Vec[i][0][mdi];
double b = Vec[i][1][mdi];
Xmpoint[i][ii] = (-((2*a)*(b - ya) - 2*xa) + Math.sqrt(Math.abs(Math.pow(((2*a)*(b - ya) - 2*xa), 2) - 4*(1 + a*a)*(xa*xa + Math.pow((b - ya),2) - Math.pow(dist[mdi]/nkom,2)))))/(2 + 2*a*a);
Ympoint[i][ii] = a*Xmpoint[i][ii] + b;
double xm11 = Xmpoint[i][ii];
double ym11 = Ympoint[i][ii];
int xm1 = (int) xm11;
int ym1 = (int) ym11;
Npoints.addPoint(xm1, ym1);
System.out.println("i:" + ym11 + "...ii:" + ym1 );
xa = Xmpoint[i][ii];
ya = Ympoint[i][ii];
}
mdi++;
}
}
}
//------------------------- Display ---------------------------
private void display() {
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(500, 600));
f.setLocationRelativeTo(null);
f.add(Npoints);
f.add(Nline);
JPanel buttonsPanel = new JPanel();
//-----------------Complete---------------
JButton dcomp = new JButton("Complete");
buttonsPanel.add(dcomp);
dcomp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
createmesh();
}
});
//------------------Clean-------------------
JButton clearButton = new JButton("Clear");
buttonsPanel.setBorder(BorderFactory.createLineBorder(Color.black));
buttonsPanel.setPreferredSize(new Dimension(500, 100));
f.add(buttonsPanel, BorderLayout.SOUTH);
buttonsPanel.add(clearButton);
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Nline.clearLines();
}
});
f.pack();
f.setVisible(true);
f.add(this);
}
//---------------------------------------------------------
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MainFem().display();
}
});
}
}
Class to draw lines:
package fempack;
import java.awt.Graphics;
import java.util.LinkedList;
import javax.swing.JPanel;
public class DrawLines extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public DrawLines() {
}
private static class Line{
final int x1;
final int y1;
final int x2;
final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
private final LinkedList<Line> lines = new LinkedList<Line>();
public void addLine(int x1, int x2, int x3, int x4) {
lines.add(new Line(x1,x2,x3,x4));
repaint();
}
public void clearLines() {
lines.clear();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lines) {
// System.out.println(line);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
}
And class to draw Circles:
package fempack;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.LinkedList;
public class DrawPoints extends JPanel {
private static final long serialVersionUID = 1L;
public DrawPoints() {
}
private static class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
private final LinkedList<Point> points = new LinkedList<Point>();
public void addPoint(int x, int y) {
points.add(new Point(x,y));
// System.out.println(x);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point point : points) {
// System.out.println(point);
g.drawOval(point.x, point.y, 5, 5);
}
}
}
Here is my solution to draw the points added in the createmesh(). I did not modify any handling of the points you got from the mouse position. I just tried to refactor and clean up your code.
Now DrawLine and DrawPoint are no more JPanel's they just hold the data you give them and draw to the Graphics-Object you pass to them in public void draw(Graphics g) method, which is called on paint in the DrawPanel-Class. DrawPanel inherits from JPanel and overrides void PaintComponent(Graphics g); to realize this (Thanks to MadProgrammer ;). Also DrawPanel handels the MouseEvents to put the mouse-positions into DrawLines- and DrawPoints-objects.
MainWindow inherits from JFrame and is the MainWindow. It creates all GUI-elements and calls the DrawPanel if necessary.
MainWindow:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JFrame {
private static final long serialVersionUID = 6755417048009930291L;
// begin gui components
JButton clearButton = null;
JButton dcomp = null;
JPanel buttonsPanel = null;
DrawPanel drawPanel = null;
// end gui components
public MainWindow(){
// Add ButtonPanel
add(getDrawPanel(), BorderLayout.CENTER);
add(getButtonPanel(), BorderLayout.SOUTH);
// Add Buttons
getButtonPanel().add(getDcomp());
getButtonPanel().add(getClearButton());
addMouseListener(getDrawPanel());
}
// begin getters and setters for gui components
private DrawPanel getDrawPanel(){
if(drawPanel == null){
drawPanel = new DrawPanel();
drawPanel.setVisible(true);
}
return drawPanel;
}
private JPanel getButtonPanel() {
if(buttonsPanel == null){
buttonsPanel = new JPanel();
buttonsPanel.setBorder(BorderFactory.createLineBorder(Color.black));
buttonsPanel.setPreferredSize(new Dimension(500, 100));
}
return buttonsPanel;
}
private JButton getClearButton() {
if(clearButton == null){
clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getDrawPanel().clearLines();
}
});
}
return clearButton;
}
private JButton getDcomp() {
if(dcomp == null){
dcomp = new JButton("Complete");
dcomp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getDrawPanel().createmesh();
getDrawPanel().repaint();
}
});
}
return dcomp;
}
// end begin getters and setters for gui components
//as always program entry-point
public static void main(String[] args) {
MainWindow wnd = new MainWindow();
wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wnd.setPreferredSize(new Dimension(500, 600));
wnd.setLocationRelativeTo(null);
wnd.pack();
wnd.setVisible(true);
}
}
DrawPanel:
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = -7726303639184194659L;
// begin members
private DrawLines dlines;
private DrawPoints dpoints;
// dont know what these members do
private Point p1 = new Point(100, 100);
public int Xpoint[][] = new int[500][30];
public int Ypoint[][] = new int[500][30];
private double Xmpoint[][] = new double[500][1000]; // [i
// γραμμή][συντεταγμένη
// Χ]
private double Ympoint[][] = new double[500][1000];
private double Vec[][][] = new double[500][2][500]; // [i γραμμή][0,1][0α
// 1β]
private double dist[] = new double[10000];
private boolean drawing;
private int c1;
private int c2;
// end members
public DrawPanel() {
dlines = new DrawLines();
dpoints = new DrawPoints();
addMouseListener(this);
}
// begin class logic
public void clearLines(){
dlines.clearLines();
repaint();
}
// dont know what this does
public void createmesh() {
int mdi = 0;
for (int j = 0; j <= c2; j++) {
for (int i = 0; i < c1 - 1; i++) {
// Υπολογισμός a και b συνιστωσών της εξίσωσης της γραμμής
Vec[i][0][mdi] = (Ypoint[i + 1][j] - Ypoint[i][j])
/ (Xpoint[i + 1][j] - Xpoint[i][j]);
Vec[i][1][mdi] = Ypoint[i][j] - Xpoint[i][j] * Vec[i][1][mdi];
// Υπολογισμός μέτρου διανύσματος
dist[mdi] = Math.sqrt(Math.pow(Xpoint[i][j] - Xpoint[i + 1][j],
2) + Math.pow(Ypoint[i][j] - Ypoint[i + 1][j], 2));
// Υπολογισμός ενδιάμεσον σημείων
int nkom = 3;
double xa = Xpoint[i][j];
double ya = Ypoint[i][j];
for (int ii = 0; ii < nkom; ii++) {
double a = Vec[i][0][mdi];
double b = Vec[i][1][mdi];
Xmpoint[i][ii] = (-((2 * a) * (b - ya) - 2 * xa) + Math
.sqrt(Math.abs(Math.pow(
((2 * a) * (b - ya) - 2 * xa), 2)
- 4
* (1 + a * a)
* (xa * xa + Math.pow((b - ya), 2) - Math
.pow(dist[mdi] / nkom, 2)))))
/ (2 + 2 * a * a);
Ympoint[i][ii] = a * Xmpoint[i][ii] + b;
double xm11 = Xmpoint[i][ii];
double ym11 = Ympoint[i][ii];
int xm1 = (int) xm11;
int ym1 = (int) ym11;
dpoints.addPoint(xm1, ym1);
System.out.println("i:" + ym11 + "...ii:" + ym1);
xa = Xmpoint[i][ii];
ya = Ympoint[i][ii];
}
mdi++;
}
}
}
// end class logic
// begin MouseListener implementation
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
drawing = false;
c2++;
}
if (SwingUtilities.isLeftMouseButton(e)) {
p1 = e.getPoint();
Xpoint[c1][c2] = p1.x;
Ypoint[c1][c2] = p1.y;
if (c1 > 3) {
for (int j = 0; j < c2 + 1; j++) {
for (int i = 0; i < c1; i++) {
if ((Math.abs(Xpoint[i][j] - Xpoint[c1][c2]) < 10)
&& (Math.abs(Ypoint[i][j] - Ypoint[c1][c2]) < 10)) {
Xpoint[c1][c2] = Xpoint[i][j];
Ypoint[c1][c2] = Ypoint[i][j];
System.out.println(Xpoint[i][j]);
}
}
}
}
if (drawing == true) {
dlines.addLine(Xpoint[c1][c2], Ypoint[c1][c2],
Xpoint[c1 - 1][c2], Ypoint[c1 - 1][c2]);
}
c1++;
drawing = true;
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
// end MouseListener implementation
// beging PAINTING
#Override
protected void paintComponent(Graphics g) {
System.out.println("paintComponent");
super.paintComponent(g);
dlines.draw(g);
dpoints.draw(g);
}
// end PAINTING
}
DrawPoints:
import java.awt.Graphics;
import java.util.LinkedList;
public class DrawPoints {
public DrawPoints() {
}
private static class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
private final LinkedList<Point> points = new LinkedList<Point>();
public void addPoint(int x, int y) {
points.add(new Point(x, y));
}
public void draw(Graphics g){
for (Point point : points) {
g.drawOval(point.x, point.y, 5, 5);
}
}
}
DrawLines:
import java.awt.Graphics;
import java.util.LinkedList;
public class DrawLines{
public DrawLines() {
}
private static class Line {
final int x1;
final int y1;
final int x2;
final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
private final LinkedList<Line> lines = new LinkedList<Line>();
public void addLine(int x1, int x2, int x3, int x4) {
lines.add(new Line(x1, x2, x3, x4));
}
public void clearLines() {
lines.clear();
}
public void draw(Graphics g){
for (Line line : lines) {
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
}
I think its a good idea to handle things like this. You want to paint on a Panel or something so pass it to the object which hold your data and let them draw to their common canvas like I did with the void draw(Graphics g) method in DrawPoints- and DrawLines-class.
I hope this will help you.
Fell free to ask if something is unclear.

Undesirable repaint of a JPanel when dynamically updated

I have a window that dynamically updates the buffered image set on a JPanel using javax.swing.Timer
Everything works as expected but every time I invoke the dynamic update there seems to be another buffered image displayed below the currently updating one.
The image of the window before and after clicking the train button (which triggers the dynamic update) is given below.
Since the image below the dynamically updating image looks like the initial screen. I rechecked the following
Whether I'm adding two dynamic lattice objects to the same panel
Multiple calls of repaint()
Unwanted initialization of the dynamic lattice
I could not find any of these in my code. I cannot post the code since it is huge and whenever I'm creating a minimal set to reproduce the same behavior it is not there. So I'm sure I'm missing something or doing something on my project code which triggers this behavior. Any suggestions on how to debug this or why it is doing something like this?
Thank you
EDIT
SSCCE is give below. If executing, click the load button followed by the train button to get the error.
(MapScreen.java - Main Class)
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import test.DisplayLattice;
import test.SelfOrganizingMap;
public class MapScreen extends JFrame {
private double NUM_ITERATIONS = 0.0;
private double ETA = 0.0;
private double SPREAD_FACTOR = 0.0;
private double RADIUS = 0.0;
private int WIDTH = 0;
private int HEIGHT = 0;
private SelfOrganizingMap SOM = null;
private Timer REFRESH_TIMER = null;
private JPanel pnlMap;
private JButton btnLoadParameters;
private JButton btnTrain;
private DisplayLattice displayScreen;
public MapScreen(double iterations, double learningRate, double spreadFactor, double radius, int option, int width, int height, int mapOption) {
NUM_ITERATIONS = iterations;
ETA = learningRate;
SPREAD_FACTOR = spreadFactor;
RADIUS = radius;
WIDTH = width;
HEIGHT = height;
setType(Type.UTILITY);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Map");
setSize(650, 800);
setLocation(150,150);
getContentPane().setLayout(null);
displayScreen = new DisplayLattice();
pnlMap = displayScreen;
pnlMap.setBounds(6, 130, 600, 600);
getContentPane().add(pnlMap);
btnLoadParameters = new JButton("Load Parameters");
btnLoadParameters.setFont(new Font("Tahoma", Font.PLAIN, 11));
btnLoadParameters.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0)
{
SOM = new SelfOrganizingMap(10000,0,0,13,displayScreen);
}
});
btnLoadParameters.setBounds(192, 46, 126, 23);
getContentPane().add(btnLoadParameters);
btnTrain = new JButton("Train");
btnTrain.setFont(new Font("Tahoma", Font.PLAIN, 11));
btnTrain.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
initialObjectSetUp();
}
});
btnTrain.setBounds(192, 72, 62, 23);
getContentPane().add(btnTrain);
}
private void initialObjectSetUp()
{
SOM.initTrainSOM(null, 100, 0.25);
REFRESH_TIMER = new Timer(100, SOM);
REFRESH_TIMER.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
MapScreen frame = new MapScreen(100,0.25,0.0,0.0,1,100,0,0);
frame.setVisible(true);
}
});
}
}
(SelfOrganizingMap.java)
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SelfOrganizingMap implements ActionListener {
private Node[][] SOM = null;
private double[][] NORM_MAP = null; //holds the L2 norm of each vector in the SOM[][].
#SuppressWarnings("unused")
private int GRID_OPTION = 0;
private int INPUT_DIMENSION = 0;
private int NUMER_OF_ITERATIONS = 0;
private int CURRENT_ITERATION=0;
private int SOM_HORIZONTAL_LENGTH = 0;
private int SOM_VERTICAL_LENGTH = 0;
private double INITIAL_LEARNING_RATE = 0.0;
private double LEARNING_RATE = 0.0;
private double MAX_RADIUS = 0.0; //radius at first epoch (t = 0)
private double RADIUS = 0.0;
private double TIME_STEP = 0.0; //lambda of X(t) = t0 * exp(-t/lambda)
private String INPUT_SAMPLES = null;
private DisplayLattice DISPLAY_SCREEN = null;
public SelfOrganizingMap(int numberOfNodes, int depth, int grid, int inputDimensison, DisplayLattice screen)
{
INPUT_DIMENSION = inputDimensison;
if(grid == 0)
{
int side = (int)Math.sqrt(numberOfNodes);
SOM = new Node[side][side];
NORM_MAP = new double[side][side];
GRID_OPTION = grid;
MAX_RADIUS = side/2;
DISPLAY_SCREEN = screen;
}
RADIUS = MAX_RADIUS;
}
public void initTrainSOM(String input, int iterations, double learningRate)
{
NUMER_OF_ITERATIONS = iterations;
INITIAL_LEARNING_RATE = learningRate;
LEARNING_RATE = INITIAL_LEARNING_RATE;
TIME_STEP = NUMER_OF_ITERATIONS/Math.log(MAX_RADIUS);
INPUT_SAMPLES = input;
}
private void singleCompleteRun()
{
DISPLAY_SCREEN.render();
System.out.println(CURRENT_ITERATION);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(CURRENT_ITERATION <= NUMER_OF_ITERATIONS)
{
singleCompleteRun();
CURRENT_ITERATION++;
}
}
}
(DisplayLattice.java)
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class DisplayLattice extends JPanel {
private BufferedImage img = new BufferedImage(500, 500, 1);
public void paintComponent(Graphics g) {
if (img == null)
super.paintComponents(g);
else
g.drawImage(img, 0, 0, this);
}
public void render() {
float cellWidth = 100;
float cellHeight = 100;
int imgW = img.getWidth();
int imgH = img.getHeight();
float r, g, b;
Graphics2D g2 = img.createGraphics();
g2.setBackground(Color.black);
g2.clearRect(0,0,imgW,imgH);
for (int x=0; x<100; x++) {
for (int y=0; y<100; y++) {
r = (float)Math.random();
g = (float)Math.random();
b = (float)Math.random();
g2.setColor(new Color(r,g,b));
g2.fillRect((int)(x*cellWidth), (int)(y*cellHeight),
(int)cellWidth+1, (int)cellHeight+1);
}
}
g2.setColor(Color.black);
g2.dispose();
repaint();
}
public BufferedImage getImage() {
if (img == null)
img = (BufferedImage)createImage(500, 500);
return img;
}
public void setImage(BufferedImage bimg) {
img = bimg;
}
}
(Node.java - Structure class for the SOM)
package test;
public class Node {
private int DIMENSION = 0;
private int POSITION_X = 0;
private int POSITION_Y = 0;
private double ACTIVATION_VALUE = 0.0;
public Node(int Dimensions, int x, int y)
{
DIMENSION = Dimensions;
setWeightVector();
POSITION_X = x;
POSITION_Y = y;
}
public int getX() {
return POSITION_X;
}
public int getY() {
return POSITION_Y;
}
public double getACTIVATION_VALUE() {
return ACTIVATION_VALUE;
}
public void setPOSITION_X(int x) {
POSITION_X = x;
}
public void setPOSITION_Y(int y) {
POSITION_Y = y;
}
public void setACTIVATION_VALUE(double y) {
ACTIVATION_VALUE= y;
}
private void setWeightVector()
{
double temp[] = new double[DIMENSION];
for(int i = 0; i<temp.length ; i++)
{
temp[i] = Math.random();
}
}
}
The problem is your DiaplyLattice class.
You overrode paintComponent but you invoke super.paintComponents(g). Notice the extra s you have at the end of paintComponents! This of course is unwanted and should be super.paintComponent(g);
I would have you method as follow:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
Now, just as a good advice/tip to give, don't use null layout and rather use LayoutManager's and possibly use several level of nesting. It's always easier.
Also, you missed an important thing in SSCCE: the SHORT part. Meaning that you should remove anything unnecessary and have a single file to copy/paste.

Categories