Jung coloring vertex with value - java

I'm stuck at the moment with the Java library Jung.
I display vertices and edges, only I can not find any functions for vertex coloring that I need with the value of the vertices and not with the mouse.
import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.BasicVisualizationServer;
import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;
public class Design {
public Graph<String, Integer> g;
public Design() {
this.g = ProjectTools.readNet("SmallTown.net");
}
public static <Paint> void main(String[] args) {
Design sgv = new Design();
Layout<Integer, String> layout = new FRLayout(sgv.g);
layout.setSize(new Dimension(800,800));
BasicVisualizationServer<Integer, String> vv =
new BasicVisualizationServer<Integer, String>(layout);
Transformer<Integer,Paint> vertexPaint = new Transformer<Integer,Paint>() {
public Paint transform(Integer i) {
return (Paint) Color.GREEN;
}
};
vv.setPreferredSize(new Dimension(850,850));
vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.green));
vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.white));
vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2.5f)));
vv.getRenderContext().setVertexFillPaintTransformer((Transformer<Integer, java.awt.Paint>) vertexPaint);
vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<Integer>(vv.getPickedVertexState(), Color.green, Color.yellow));
vv.setBackground(Color.gray);
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>());
vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
JFrame frame = new JFrame("Projet Algo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(vv);
frame.pack();
frame.setVisible(true);
}
}
My rendering :

I can see two possible problems; you are calling setVertexFillPaintTransformer twice and BasicVisualizationServer dosn't seem to like DefaultModalGraphMouse.
Try this version:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import javax.swing.JFrame;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;
import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.picking.PickedInfo;
import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;
public class Design {
public Graph<Integer, String> g;
public Design() {
this.g = ProjectTools.readNet("SmallTown.net");
}
private static class VertexPaintTransformer implements Transformer<Integer,Paint> {
private final PickedInfo<Integer> pi;
VertexPaintTransformer ( PickedInfo<Integer> pi ) {
super();
if (pi == null)
throw new IllegalArgumentException("PickedInfo instance must be non-null");
this.pi = pi;
}
#Override
public Paint transform(Integer i) {
Color p = null;
//Edit here to set the colours as reqired by your solution
if ( i % 2 == 0)
p = Color.GREEN;
else
p = Color.RED;
//Remove if a selected colour is not required
if ( pi.isPicked(i)){
p = Color.yellow;
}
return p;
}
}
public static <Paint> void main(String[] args) {
Design sgv = new Design();
Layout<Integer, String> layout = new FRLayout(sgv.g);
layout.setSize(new Dimension(800,800));
VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer, String>(layout);
Transformer<Integer,Paint> vertexPaint = new Transformer<Integer,Paint>() {
#Override
public Paint transform(Integer i) {
if ( i % 2 == 0)
return (Paint) Color.GREEN;
else
return (Paint) Color.RED;
}
};
vv.setPreferredSize(new Dimension(850,850));
vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.green));
vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.white));
vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2.5f)));
vv.getRenderContext().setVertexFillPaintTransformer(new VertexPaintTransformer(vv.getPickedVertexState()));
DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
graphMouse.setMode(edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode.PICKING);
vv.setGraphMouse(graphMouse);
vv.setBackground(Color.gray);
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>());
vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
JFrame frame = new JFrame("Projet Algo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(vv);
frame.pack();
frame.setVisible(true);
}
}
I've repalced your Transformer with a new version VertexPaintTransformer that supports selection, removed the second use of setVertexFillPaintTransformer and swithced you from a BasicVisualizationServer to VisualizationViewer so I can use a picking GraphMouse
I had to mock your ProjectTools#readNet() method but Ihope you can see the Odd, Even and Selected colours.
You can now modify VertexPaintTransformer#transform() as required

Related

Java task not updating jlabel

Question I have is I am trying to update my gui with a timer(this works and changes the image for mypic but, it will not update mytext label for some weird reason any help would be very much appreciated!
*I should add that mytext isn't showing up at all on my gui since introducing the timer...but mypic does????
package widget;
import com.sun.awt.AWTUtilities;
import com.sun.xml.internal.ws.client.sei.ResponseBuilder;
import javafx.geometry.HorizontalDirection;
import javafx.scene.shape.Ellipse;
import javax.swing.*;
import javax.swing.Timer;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.xml.sax.SAXException;
import widget.weather;
import static java.awt.Color.*;
/**
* Created by xxxxxxzz on 10/19/2016.
*/
public class Widget extends JFrame {
String icon_image = null;
String temp = null;
JLabel myText = null;
JLabel mypic = null;
Timer SimpleTimer = new Timer(5000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try {
icon_image = weather.weather_pic();
temp = weather.temp();
URL url = new URL(icon_image);
ImageIcon img = new ImageIcon(url);
myText = new JLabel(temp);
//Tried setting it like this and still doesn't work
// myText = new JLabel("HOT");
mypic = new JLabel();
myText.setText(temp);
mypic.setIcon(img);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
public Widget() throws IOException, URISyntaxException {
setUndecorated(true);
setSize(150,150);
temp = weather.temp();
icon_image = weather.weather_pic();
URL url = new URL(icon_image);
ImageIcon img = new ImageIcon(url);
myText = new JLabel(temp);
mypic = new JLabel();
myText.setText(temp);
mypic.setIcon(img);
myText.setHorizontalAlignment(JLabel.CENTER);
mypic.setHorizontalAlignment(JLabel.CENTER);
add(myText);
add(mypic);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
Shape shape = new Ellipse2D.Float(0,0,150,150);
AWTUtilities.setWindowShape(this, shape);
SimpleTimer.start();
}
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
new Widget();
}
}
UPDATE with suggestions still isn't working..
package widget;
import com.sun.awt.AWTUtilities;
import com.sun.xml.internal.ws.client.sei.ResponseBuilder;
import javafx.geometry.HorizontalDirection;
import javafx.scene.shape.Ellipse;
import javax.swing.*;
import javax.swing.Timer;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.xml.sax.SAXException;
import widget.weather;
import static java.awt.Color.*;
/**
* Created by jsnow on 10/19/2016.
*/
public class Widget extends JFrame {
String icon_image = null;
String temp = null;
JLabel myText = new JLabel();
JLabel mypic = new JLabel();
Timer SimpleTimer = new Timer(5000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try {
icon_image = weather.weather_pic();
temp = weather.temp();
URL url = new URL(icon_image);
ImageIcon img = new ImageIcon(url);
myText.setText(temp);
mypic.setIcon(img);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
public Widget() throws IOException, URISyntaxException {
setUndecorated(true);
setSize(150,150);
temp = weather.temp();
icon_image = weather.weather_pic();
URL url = new URL(icon_image);
ImageIcon img = new ImageIcon(url);
myText.setText(temp);
mypic.setIcon(img);
myText.setHorizontalAlignment(JLabel.CENTER);
mypic.setHorizontalAlignment(JLabel.CENTER);
add(myText);
add(mypic);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
Shape shape = new Ellipse2D.Float(0,0,150,150);
AWTUtilities.setWindowShape(this, shape);
SimpleTimer.start();
}
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
new Widget();
}
}
Here's a working solution which you can tailor to your use. The cause seemed to be the way you had tried to display the Components rather than the code in your action listener.
Your approach was just replacing myText with myPic when you initially set up the JFrame. Instead you need to use a layout manager. The example I've given is with overlaying using JLayeredPane. You may wish to use a layout manager instead if this is not the desired outcome, see the Oracle Tutorial on using layout managers.
Widget class
package widget;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Widget extends JFrame {
private static final int UPDATE_TICK = 5_000;
private static final int WIDGET_WIDTH = 150;
private static final int WIDGET_HEIGHT = 150;
private JLabel myText = new JLabel();
private JLabel myPic = new JLabel();
private Weather weather = new Weather();
private Timer simpleTimer;
public void createAndShow() {
setUndecorated(true);
setSize(WIDGET_WIDTH, WIDGET_HEIGHT);
Shape shape = new Ellipse2D.Float(0, 0, WIDGET_WIDTH, WIDGET_HEIGHT);
// AWTUtilities.setWindowShape(this, shape);
setShape(shape); // do this instead
myText.setHorizontalAlignment(JLabel.CENTER);
myPic.setHorizontalAlignment(JLabel.CENTER);
JLayeredPane layered = new JLayeredPane();
myText.setBounds(0, 0, WIDGET_WIDTH, WIDGET_HEIGHT);
myPic.setBounds(0, 0, WIDGET_WIDTH, WIDGET_HEIGHT);
layered.add(myPic, 1, 0);
layered.add(myText, 2, 0);
add(layered);
simpleTimer = new Timer(UPDATE_TICK, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
update();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
simpleTimer.start();
}
private void update() {
myText.setText(weather.getTemp());
myPic.setIcon(new ImageIcon(weather.getImage(WIDGET_WIDTH, WIDGET_HEIGHT)));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Widget w = new Widget();
w.createAndShow();;
}
});
}
}
Weather class for demonstration purposes
package widget;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Weather {
private static final Random rand = new Random();
private static final Color[] randColors = {Color.YELLOW,
Color.GREEN,
Color.WHITE};
public String getTemp() {
return Integer.toString(rand.nextInt(100));
}
public BufferedImage getImage(int width, int height) {
int colorIndex = rand.nextInt(randColors.length);
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
img.setRGB(x, y, randColors[colorIndex].getRGB());
}
}
return img;
}
}

Outofmemory exception loading image files in Java

i have a problem loading image files.
There are 2 cases, i've tested. The problem occures only in the first one. In both cases a JDialog-window apears that displays a
downscaled image. After 300ms this window closes automatically (there is a timer in the constructor of ImageDialog and CardPrinter; this is only for debugging).
In the production version, the programm must be able to load 30-40 images (one by one) in a JDialog. The user types some text, and clicks on a button to show the next image.
To load the images i use ImageIO.read() in both cases. Alternatively i used CMYKJPEGImage (http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/)
but it also produces the exception.
In Main there is myTimer that continusly opens the JDialog with an image-file (listFilesRecurse() should be called with an absolute path by setting the variable pathtofiles).
Case 1)
Loading images in JDialog with overlay layout manager (Main.java, CardPrinter.java, IDCardLayout.java).
For this, the lines from 'CardPrinter cp=null;' to 'cp.dispose();' in Main.java must be uncommented. The tricky part is in addIDCard()#CardPrinter.
Here will be the layout built up. After this paintComponent()#IDCardLayout will be called, if the content of the dialog-window should be actualised.
It seems, that the loaded images won't be destroyed, and the memory gets full (in Window's Taskmanager the memory usage can be seen).
Case 2)
Loading images in a JDialog with no layout manager (Main.java, ImageDialog.java).
(Uncomment the line 'mn.showDialog(mn.frame, file);').
Works perfect. No exceptions!
The function ImageIO.read() should be ok, because in the 2. case, there was no errors (even if the code runs for 20 minutes).
It's strange, it seems in the first case the layoutmanager prevents GC to unload the unused images...
The problem in the 1.case should be in CTR#CardPrinter and addIDCard()#CardPrinter. In CTR i use the OverlayLayout. In the 2.case, there is no Layoutmanager at all.
The Java version is: 1.7.0_80 on Windows7 SP1.
Can somebody help me please?
Thank you in advance,
Daniel
The exception:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferByte.(DataBufferByte.java:92)
at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:415)
at java.awt.image.Raster.createWritableRaster(Raster.java:941)
at javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1073)
at javax.imageio.ImageReader.getDestination(ImageReader.java:2896)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1066)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1308)
at test.IDCardLayout.loadPicture(IDCardLayout.java:128)
at test.CardPrinter.addIDCard(CardPrinter.java:142)
at test.CardPrinter.(CardPrinter.java:62)
at test.CardPrinter.createDialog(CardPrinter.java:91)
at test.Main$1.actionPerformed(Main.java:69)
at javax.swing.Timer.fireActionPerformed(Timer.java:312)
at javax.swing.Timer$DoPostEvent.run(Timer.java:244)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
package test;
/*Main.java*/
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
JFrame frame;
//list files recursively, using a filter (pattern). If pattern=*, all files will be listed.
public static void listFilesRecurse(String fullpath, String pattern[], Vector<File> foundFiles) throws IOException {
File dir = new File(fullpath);
File list[] = dir.listFiles();
for(File f: list) {
if( !f.isDirectory() ) {
for(String pt: pattern) {
if(pt.equals("*")) {
foundFiles.add(f);
break;
}
else if( f.getAbsolutePath().toUpperCase().endsWith(pt.toUpperCase()) ) {
foundFiles.add(f);
break;
}
}
} else {
listFilesRecurse(f.getAbsolutePath(), pattern, foundFiles);
}
}
}
public static void main(String[] args) {
final Main mn = new Main();
final String pathtofiles = "\\path\\to\\files\\";
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Vector<File> list = new Vector<File>();
System.out.println("\nListing files ...");
try {
listFilesRecurse(pathtofiles, new String[]{"jpg", "png", "jpeg"}, list);
} catch (IOException e) {
e.printStackTrace();
}
for(int index=0; index<list.size(); index++) {
String file = list.get(index).getAbsolutePath();
System.out.println("\nLoading image - " + index + ": " + file);
//mn.showDialog(mn.frame, file);
CardPrinter cp=null;
try {
cp = CardPrinter.createDialog(mn.frame, "Max",
"Muster", "1122", "12345678", "01/2018", file);
} catch (Exception e) {
e.printStackTrace();
continue; //break; //return;
}
cp.setVisible(true);
cp.dispose();
}
}
};
final Timer myTimer = new Timer(100, task);
myTimer.setRepeats(true);
JFrame frame = new JFrame("JFrame Example");
mn.frame = frame;
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JLabel label = new JLabel("This is a label!");
JButton button = new JButton();
button.setText("Press me");
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
myTimer.start();
}
});
panel.add(label);
panel.add(button);
frame.add(panel);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//opens the dialog that display an image (file).
public void showDialog(JFrame fr, String file) {
ImageDialog imgd = new ImageDialog(fr, "Testdialog", file);
imgd.setSize(300, 300);
imgd.setModal(true);
imgd.setLocation(250, 250);
imgd.setVisible(true);
}
}
package test;
/*ImageDialog.java*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.Timer;
import org.monte.cmykdemo.CMYKJPEGImage;
public class ImageDialog extends JDialog {
String file;
public ImageDialog(JFrame frame, String title, String file) {
super(frame, title);
this.file = file;
//######For debugging only. This will close the dialog window after 300 ms (by calling ImageDialog.this.setVisible(false);).
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
ImageDialog.this.dispose();
}
};
Timer cl = new Timer(300, task);
cl.start();
//#######
}
//renders the picture on screen.
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
setRenderingHints(g2d);
BufferedImage img=null;
try {
img = loadPicture(this.file);
} catch (IOException e) {
e.printStackTrace();
}
g2d.setColor(Color.BLUE);
g2d.drawRect(0, 0, this.getWidth(), this.getHeight());
g2d.drawImage(img, 10, 10, 80, 80, null, null);
}
void setRenderingHints(Graphics2D g2) {
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
}
public static BufferedImage loadPicture(String fullpath) throws IOException {
System.out.println("\nloadPicture(): " + fullpath);
//BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( fullpath );
BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );
return img;
}
}
package test;
/*CardPrinter.java*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BorderFactory;
import javax.swing.JButton;
public class CardPrinter extends JDialog /*implements Printable*/ {
protected JPanel jp;
protected JTextField tx;
protected JLabel lblCounter;
protected IDCardLayout idcard;
protected String vorname, nachname, id, gueltig, bild;
protected String chipid;
protected CardPrinter(Window owner, String vorname, String nachname, String id, String chipid,
String gueltig, String bild /*, DataReceiver drv*/) throws IOException {
super((Window)owner, "Assign_ChipID_DialogObject");
this.bild = bild;
//this.datareceiver = drv;
setTitle("Assign ID");
setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
setResizable(false);
jp = new JPanel();
jp.setLayout(null);
jp.setOpaque(false);
addIDCard();
//setupButtons();
//setSize(this.getPreferredSize().width, this.getPreferredSize().height);
setSize(250, 250); //+++
setLocation(300, 300); //+++
//Overlay components: tx overlaps idcard
JPanel cnt = new JPanel();
cnt.setLayout(new OverlayLayout(cnt));
cnt.add(jp);
getContentPane().add(cnt);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//######For debugging only. This will close the dialog window after 300 ms (by calling CardPrinter.this.setVisible(false);).
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
CardPrinter.this.setVisible(false);
}
};
Timer closeWnd = new Timer(300, task);
closeWnd.start();
//######
}
//use this to create an instance of this class.
public static CardPrinter createDialog(Window owner, String vorname,
String nachname, String id, String chipid, String gueltig, String bild /*, DataReceiver drv*/) throws IOException {
return new CardPrinter(owner, vorname, nachname, id, chipid, gueltig, bild /*, drv*/);
}
protected void addIDCard() throws IOException {
int idcard_move_vert=15, idcard_move_hor=76;
tx = new JTextField(this.chipid, 8);
jp.add(tx);
tx.setBounds(idcard_move_hor+130, idcard_move_vert+6, 70, 20);
Border border = BorderFactory.createLineBorder(Color.RED);
tx.setBorder(border);
tx.requestFocus();
lblCounter = new JLabel("");
lblCounter.setBounds(idcard_move_hor+270, idcard_move_vert-6, 40, 30);
jp.add(lblCounter);
lblCounter.requestFocus();
System.out.println("\naddIDCard() ...");
BufferedImage picture = IDCardLayout.loadPicture(this.bild);
idcard = new IDCardLayout(/*this.vorname, this.nachname, this.id,*/ picture, this.bild /*, this.gueltig*/);
idcard.setLayout(null);
//idcard.setBounds(idcard_move_hor, idcard_move_vert, idcard.getPreferredSize().width, idcard.getPreferredSize().height);
idcard.setBounds(idcard_move_hor, idcard_move_vert, 50, 60);
idcard.setBorder( new LineBorder(Color.BLACK) );
jp.add(idcard);
//repaint();
}
}
package test;
/*IDCardLayout.java*/
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import org.monte.cmykdemo.CMYKJPEGImage;
public class IDCardLayout extends JPanel {
private BufferedImage bild;
private String bildfile;
public IDCardLayout(BufferedImage photo, String bildfile) {
this.bild = photo;
this.bildfile = bildfile;
}
/**
* Render graphics to the screen.
*/
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
System.out.println("\npaintComponent() ...");
prepareGraphics(g2d);
}
public static BufferedImage loadPicture(String fullpath) throws IOException {
//BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( f.getAbsolutePath() );
BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );
return img;
}
//changing the rendering hints has no effect on Outofmemory-exception.
protected void setRenderingHints(Graphics2D g2, boolean normalText) {
if(true) {
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
}
}
/**
* Renders graphics to the screen.
*/
protected void prepareGraphics(Graphics2D g2) {
setRenderingHints(g2, true);
double newHeight = 60;
double scwidth = ( ((double)newHeight / (double)this.bild.getHeight()) ) * (double)this.bild.getWidth();
System.out.println("\nprepareGraphics() ..." + this.bildfile);
g2.drawImage(this.bild, 5, 5,
(int)scwidth,
(int)newHeight,
null, null);
}
}
The problem is solved. I don't use the class OverlayLayout anymore. The layout looks quite different, but now it works.

Stepped ComboBox refresh

A Stepped ComboBox is very useful to make the drop-down pop-up wider than the text field. However when new content is added to the list, the pop-up gets its initial width back.
By default
After refresh (new element)
SSCCE
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
public class SteppedComboBoxRefresh extends JFrame {
private List<String> list;
private final SteppedComboBox combo;
public SteppedComboBoxRefresh() {
super("SteppedComboBox Refresh");
this.list = new ArrayList<String>(Arrays.asList(new String[]{
"AAA", "AAAAAA"
}));
this.combo = new SteppedComboBox(this.list.toArray());
this.combo.setDimensions(50);
JButton addButton = new JButton("Add longer string");
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
list.add(list.get(list.size()-1) + "AAA");
combo.setModel(new DefaultComboBoxModel(list.toArray()));
combo.setDimensions(50);
}
});
getContentPane().setLayout(new FlowLayout());
getContentPane().add(this.combo);
getContentPane().add(addButton);
}
public static void main (String args[]) {
SteppedComboBoxRefresh f = new SteppedComboBoxRefresh();
f.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize (300, 100);
f.setVisible(true);
}
}
class SteppedComboBoxUI extends MetalComboBoxUI {
#Override
protected ComboPopup createPopup() {
BasicComboPopup popup = new BasicComboPopup( this.comboBox ) {
#Override
public void show() {
Dimension popupSize = ((SteppedComboBox)this.comboBox).getPopupSize();
popupSize.setSize( popupSize.width,
getPopupHeightForRowCount( this.comboBox.getMaximumRowCount() ) );
Rectangle popupBounds = computePopupBounds( 0,
this.comboBox.getBounds().height, popupSize.width, popupSize.height);
this.scroller.setMaximumSize( popupBounds.getSize() );
this.scroller.setPreferredSize( popupBounds.getSize() );
this.scroller.setMinimumSize( popupBounds.getSize() );
this.list.invalidate();
int selectedIndex = this.comboBox.getSelectedIndex();
if ( selectedIndex == -1 ) {
this.list.clearSelection();
} else {
this.list.setSelectedIndex( selectedIndex );
}
this.list.ensureIndexIsVisible( this.list.getSelectedIndex() );
setLightWeightPopupEnabled( this.comboBox.isLightWeightPopupEnabled() );
show( this.comboBox, popupBounds.x, popupBounds.y );
}
};
popup.getAccessibleContext().setAccessibleParent(this.comboBox);
return popup;
}
}
class SteppedComboBox extends JComboBox {
protected int popupWidth;
public SteppedComboBox(ComboBoxModel aModel) {
super(aModel);
setUI(new SteppedComboBoxUI());
this.popupWidth = 0;
}
public SteppedComboBox(final Object[] items) {
super(items);
setUI(new SteppedComboBoxUI());
this.popupWidth = 0;
}
public SteppedComboBox(Vector items) {
super(items);
setUI(new SteppedComboBoxUI());
this.popupWidth = 0;
}
public void setPopupWidth(int width) {
this.popupWidth = width;
}
public Dimension getPopupSize() {
Dimension size = getSize();
if (this.popupWidth < 1) {
this.popupWidth = size.width;
}
return new Dimension(this.popupWidth, size.height);
}
public void setDimensions(int width) {
Dimension d = getPreferredSize();
setPreferredSize(new Dimension(width, d.height));
setPopupWidth(d.width);
}
}
The ComboBox still uses its previous PreferredSize. It's needed to set the preferred size back to null, so that we get the size which is preferred by the new content in the list.
void javax.swing.JComponent.setPreferredSize(Dimension preferredSize)
Sets the preferred size of this component. If preferredSize is null, the UI will be asked for the preferred size.
public void setDimensions(int width) {
setPreferredSize(null);
Dimension d = getPreferredSize();
setPreferredSize(new Dimension(width, d.height));
setPopupWidth(d.width);
}
Result
You could use the Combo Box Popup.
It is a more flexible version of the Stepped Combo Box. Best of all it can be used on any combo box since the logic is implemented in a `PopupMenuListener'.
You can control the maximum width of the popup. You can even have the popup display above the combo box instead of below.

Dynamic Time Series Stacked Area Chart in Java

My requirement is to create a dynamic time series stacked area chart in a java desktop app. Something like this example, but i want Stacked Area chart. I have found lot of examples of stacked area chart but they all are based on static data.
Here is the modified version of this example for dynamic time series stacked area chart.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.SeriesRenderingOrder;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYAreaRenderer;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class DTSCTest extends ApplicationFrame {
private static final String TITLE = "Dynamic Series";
private static final String START = "Start";
private static final String STOP = "Stop";
private static final float MINMAX = 100;
private static final int COUNT = 15;
private static final int FAST = 1000;
private static final int SLOW = FAST * 5;
private static final Random random = new Random();
private Timer timer;
private static final String SERIES1 = "Positive";
private static final String SERIES2 = "Negative";
public DTSCTest(final String title) {
super(title);
final TimeTableXYDataset dataset = new TimeTableXYDataset();
JFreeChart chart = createAreaChart(dataset);
final JButton run = new JButton(STOP);
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (STOP.equals(cmd)) {
timer.stop();
run.setText(START);
} else {
timer.start();
run.setText(STOP);
}
}
});
final JComboBox combo = new JComboBox();
combo.addItem("Fast");
combo.addItem("Slow");
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ("Fast".equals(combo.getSelectedItem())) {
timer.setDelay(FAST);
} else {
timer.setDelay(SLOW);
}
}
});
this.add(new ChartPanel(chart), BorderLayout.CENTER);
JPanel btnPanel = new JPanel(new FlowLayout());
btnPanel.add(run);
btnPanel.add(combo);
this.add(btnPanel, BorderLayout.SOUTH);
timer = new Timer(FAST, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
TimePeriod period = new Second();
dataset.add(period, randomValue(), SERIES1);
dataset.add(period, randomValue(), SERIES2);
if(dataset.getItemCount() > COUNT) {
TimePeriod firstItemTime = dataset.getTimePeriod(0);
dataset.remove(firstItemTime, SERIES1);
dataset.remove(firstItemTime, SERIES2);
}
}
});
}
private float randomValue() {
float randValue = (float) (random.nextGaussian() * MINMAX / 3);
return randValue < 0 ? -randValue : randValue;
}
private JFreeChart createAreaChart(final TimeTableXYDataset dataset) {
final JFreeChart chart = ChartFactory.createStackedXYAreaChart(
"Live Sentiment Chart", "Time", "Sentiments", dataset, PlotOrientation.VERTICAL, true, true, false);
final StackedXYAreaRenderer render = new StackedXYAreaRenderer();
render.setSeriesPaint(0, Color.RED);
render.setSeriesPaint(1, Color.GREEN);
DateAxis domainAxis = new DateAxis();
domainAxis.setAutoRange(true);
domainAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss"));
domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.SECOND, 1));
XYPlot plot = (XYPlot) chart.getPlot();
plot.setRenderer(render);
plot.setDomainAxis(domainAxis);
plot.setSeriesRenderingOrder(SeriesRenderingOrder.FORWARD);
plot.setForegroundAlpha(0.5f);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setNumberFormatOverride(new DecimalFormat("#,###.#"));
rangeAxis.setAutoRange(true);
return chart;
}
public void start() {
timer.start();
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DTSCTest demo = new DTSCTest(TITLE);
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
demo.start();
}
});
}
}

MVC with several identical views

for the purpose of my application i need to create several identical views that should behave and response to the same events. Should i instanciate each identical views that i need and hold this list of views in my controller, or there are better ways of handling this ? Thanks.
From what I understand... You should follow your thinking.
Have a list of views that you install to a controller. And if the event occurs go through the list of views and update all of them.
EDIT1: Here is a very simple example showing how it might be done.
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ManyViewsTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
View v1 = new View();
View v2 = new View();
View v3 = new View();
View v4 = new View();
View v5 = new View();
JPanel contentPane = new JPanel();
contentPane.add(v1);
contentPane.add(v2);
contentPane.add(v3);
contentPane.add(v4);
contentPane.add(v5);
JFrame f = new JFrame();
f.setContentPane(contentPane);
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Controller c = new Controller(f);
f.setVisible(true);
}
});
}
}
class Controller
{
private List<View> views;
public Controller(JFrame f)
{
this.views = new ArrayList<View>();
f.addMouseListener(mL);
for(Component c: f.getContentPane().getComponents())
{
if(c instanceof View)
views.add((View)c);
}
}
public void updateView(String text)
{
for(View v: views)
v.setLabelText(text);
}
private MouseListener mL = new MouseAdapter()
{
int pressCounter = 0;
#Override
public void mousePressed(MouseEvent e)
{
super.mousePressed(e);
updateView("mousePressed, pressCounter="+(++pressCounter));
}
};
}
class View extends JPanel
{
private static final long serialVersionUID = 1L;
private JLabel label;
public View()
{
this.label = new JLabel("Initialized");
label.setBorder(BorderFactory.createLineBorder(Color.GREEN));
add(label);
}
public void setLabelText(String text)
{
label.setText(text);
}
}

Categories