When the text in JLabel is too long there are visible 3 dots at the end of text. Is it possible to put them at the beginning?
You may consider using FontMetrics. class to see the length of your text under the current font.
_________________________________
|
| This is some really long text that I want to fit in the small label
|________________________________
^^^ YOUR LABEL ^^^
Say you want to fit that long text into that label.
Here is what you can do (and this is just a wild guess and I am making this on the fly)
Start with your three dots ... in a String.
Start adding appending characters to it, one by one.
Get the width of your JLabel.
Use FontMetrics to measure the length of your text , in pixels, as you append more characters
Keep adding more characters as long as the pixel length of the text is less than the width of your JLabel
Once it becomes greater than the width of the JLabel, get out of the loop.
Set this newly formed text as the text of your JLabel
You should end up like this:
_________________________________
|
| ...This is some really long tex
|________________________________
^^^ YOUR LABEL ^^^
Here is an easy way to get started with FontMetrics. Avoid the bickering there. Just do what the accepted answer says: Java: Friendlier way to get an instance of FontMetrics
SSCCE is in accordance with what the OP really wants rather than what I explained
package stack;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class BackwardsDots extends JFrame{
JLabel label = new JLabel(){
#Override
public Dimension getPreferredSize(){
return new Dimension(200,100);
}
};
String text = "This is a design requirement and not my whim";
FontMetrics fm;
Font theFontBeingUsed;
//--------------------------------------------------------------------------------
public BackwardsDots(){
getContentPane().add(label);
pack();
theFontBeingUsed = new Font("Ubuntu",Font.BOLD,14);
fm = Toolkit.getDefaultToolkit().getFontMetrics(theFontBeingUsed);
label.setText(trimmedStringCalculator(text));
label.setToolTipText(text);
label.setBorder(BorderFactory.createDashedBorder(Color.RED));
label.addComponentListener(new ComponentListener(){
#Override
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentResized(ComponentEvent arg0) {
label.setText(trimmedStringCalculator(text));
}
#Override
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
});
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//--------------------------------------------------------------------------------
private String trimmedStringCalculator(String inputText){
String ellipses = "...";
String textToBeDisplayed = "";
int widthOfJLabel = label.getWidth();
for(int i = text.length()-1; i >= 0; i--){
if(fm.stringWidth(ellipses + textToBeDisplayed) <= widthOfJLabel){
textToBeDisplayed = text.charAt(i) + textToBeDisplayed;
}
}
String finalText;
if(textToBeDisplayed.equals(inputText)){
finalText = inputText;
}else{
finalText = ellipses.concat(textToBeDisplayed);
}
return finalText;
}
//--------------------------------------------------------------------------------
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
new BackwardsDots();
}
});
}
}
Output
I have another solution, that relies on LabelUI. First the code:
LabelUI labelUI = new MetalLabelUI() {
#Override
protected String layoutCL(JLabel label, FontMetrics fontMetrics, String text, Icon icon, Rectangle viewR, Rectangle iconR, Rectangle textR) {
String clipString = "...";
// Use reversed text, because first characters may be larger or thinner than last ones.
String reversedText = new StringBuilder(text).reverse().toString();
// Let Swing do its magic.
String result = super.layoutCL(label, fontMetrics, reversedText, icon, viewR, iconR, textR);
// Not using .equals is intentional. Previous method will return a different instance
// if and only if a clip operation occurred.
if (result != text) {
// Use the same character count, but starting with the end.
result = clipString
+ text.substring(text.length() - result.length() + clipString.length());
} else {
// Restore the original
result = text;
}
return result;
}
};
The goal is to let Swing compute everything, including its clipped string, and using this as a hint to perform our own left clipping.
The trick is that we have to provide the reversed string to the super method, since our result will clip leading characters, we need to be sure that the computation was right. Characters have different widths.
The main advantage for me is that there is a very little overhead, compared to the current solution that compute a new size before the UI, and the UI will start doing the same.
EDIT: Change code to restore the original string when not clipped.
I think this is rather a system behaviour, more than JLabel's, so you couldn't really do that.
Related
I am a beginner in Java, I am trying to build a chatbot. The query and responses are hard coded in 2D string array chatbot[][].
This is the complete code that I have used, Two objects for JTextArea 'input and dialogue ' has been used. Object input has been attached to JPanel and is used to get the text from the user and then this is searched in the 2D string array.If it is found then the response is thrown from the same array.
Now my requirement is when the response is any URL it should be displayed as a link so that user can directly click and go to the site(http://google.com for the current scenario).Kindly suggest how this can be achieved or any modification in code is required. addText is the method that is defined to add entire conversation to dialogue text area which is non editable.
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.lang.Math;
import java.awt.Color;
import java.awt.Toolkit;
public class test implements KeyListener{
JFrame j=new JFrame("Temenos ChatBot");
JPanel p=new JPanel();
JTextArea dialog=new JTextArea(20,50); //it will contain the whole conversation(non editable)
JTextArea input=new JTextArea(1,50); //where we user input our query(editable)
JScrollPane scroll=new JScrollPane(
dialog,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
String[][] chatbot={
{"hi","hello","hola","ola","howdy"}, //check for query
{"hi","hello","hey"}, //provides output of the query
{"google","provide link for google","www.google.com"}, //Query
{"http://google.com"}, //response
//default
{"we can't find your query",
"(Sorry, we could not understand)"}
};
public static void main(String[]args){
new test();
}
private void icon(){
j.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("dy1MzZ-W.png")));//change the icon, paste the icon in default package
}
public test(){
j.setSize(600,400);
j.setResizable(false);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dialog.setEditable(false);
input.addKeyListener(this);
p.add(scroll);
p.add(input);
p.setBackground(new Color(0,150,255));
j.add(p);
j.setVisible(true);
icon();
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(false);
//-----grab quote-----------
String quote=input.getText(); //takes whatever text user is inputting
input.setText("");
addText("->You:\t"+quote);
quote.trim();
while(
quote.charAt(quote.length()-1)=='!' ||
quote.charAt(quote.length()-1)=='.' ||
quote.charAt(quote.length()-1)=='?'
){
quote=quote.substring(0,quote.length()-1);
}
quote.trim();
byte response=0; //byte is data type that will check for response
/*
0:we're searching through chatBot[][] for matches
1:we didn't find anything
2:we did find something
*/
//-----check for matches----
int j=0;//which group we're checking
while(response==0){
if(inArray(quote.toLowerCase(),chatbot[j*2])){
response=2;
int r=(int)Math.floor(Math.random()*chatbot[(j*2)+1].length);
addText("\n->A.I.sha:\t"+chatbot[(j*2)+1][r]);
}
j++;
if(j*2==chatbot.length-1 && response==0){
response=1;
} //if it has come to end then set response to 1
}
//-----default--------------
if(response==1){
int r=(int)Math.floor(Math.random()*chatbot[chatbot.length-1].length);
addText("\n->A.I.sha:\t"+chatbot[chatbot.length-1][r]);
}
addText("\n");
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(true);
}
}
public void keyTyped(KeyEvent e){}
public void addText(String str){
dialog.setText(dialog.getText()+str);
}//it will add whatever text dialogue box is having
public boolean inArray(String in,String[] str){
boolean match=false;
for(int i=0;i<str.length;i++){
if(str[i].equals(in)){
match=true;
} //Searches for string 'in' in string array,if it finds return true
}
return match;
}
}
If you're making a GUI in swing, you could follow another stack overflow answer, such as this one
How to add hyperlink in JLabel
Or, you could just have java open the browser to that webpage:
// Create Desktop object
Desktop d=Desktop.getDesktop();
// Browse a URL, say google.com
d.browse(new URI("http://google.com"));
You can use the parse static method from Uri
Uri myUri = Uri.parse("http://google.com")
Actually, i have already ask this question in here. But, i'm making mistake. I haven't already get the solution.
First, at the question before, i can get Rectangle with
Rectangle rectangle = textArea.modelToView( textArea.getCaretPostion() );
I'm also get X and Y position.
I'm creating a editor that can add new Text Area each i press Enter key. XY position with code above always give same return in every Text Area. Look my code.
import java.awt.Container;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
public class forquestion extends JFrame {
Container textAreaBox;
LinkedList<JTextComponent> textArea;
int nameTA;
public forquestion() {
int nameTA = 0;
textArea = new LinkedList<>();
textAreaBox = Box.createVerticalBox();
textAreaBox.add(Box.createVerticalGlue());
addLine();
this.add(textAreaBox);
this.setVisible(true);
}
public static void main(String[] args) {
forquestion app = new forquestion();
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void addLine () {
JTextComponent temp_ta = createTextComponent();
textArea.add(temp_ta);
textAreaBox.add(textArea.getLast());
textAreaBox.add(Box.createVerticalGlue());
}
protected JTextComponent createTextComponent() {
JTextArea ta = new JTextArea("test");
/*if (count%2==0)
ta.setForeground(Color.red);
else
ta.setForeground(Color.GREEN);*/
ta.setFont(new Font("Courier New",Font.PLAIN,16));
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setName(Integer.toString(nameTA));
nameTA+=1;
basicKey("ENTER", enter, ta);
ta.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent ev) {
try {
taMousePressed(ev);
} catch (BadLocationException ex) {
Logger.getLogger(forquestion.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
return ta;
}
public void basicKey(String s, Action a, JTextArea ta) {
ta.getInputMap().put(KeyStroke.getKeyStroke(s), s);
ta.getActionMap().put(s, a);
}
Action enter = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
addLine();
}
};
private void taMousePressed(java.awt.event.MouseEvent ev) throws BadLocationException {
int now_focus = Integer.parseInt(ev.getComponent().getName());
int _caret;
_caret = textArea.get(now_focus).getCaretPosition();
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
double x = rectangle.getX();
//int xc = textArea.get(now_focus).getLocation().x;
double y = rectangle.getY();
//int yc = textArea.get(now_focus).getLocation().y;
//double h = rectangle.getHeight();
//double w = rectangle.getWidth();
System.out.println(x);
System.out.println(y);
//System.out.println(xc);
//System.out.println(yc);
//System.out.println(h);
//System.out.println(w);
System.out.println("");
}
}
My code will print XY position each time you press a Text Area. But, the display always same in every text area. (Try to make many Text Area and give some text) Btw, it just simple code. You need change the window frame size for update the new text area after you press enter key..hahaha.
So, my question is: How can i get the XY position of caret (text cursor) in any Text Area. I want to display JPopmenu there. :)
I hope this question clear for you. Thx before.
The Rectangle reported back is relative to the text area, where it's 0x0 position is the top, left corner of the component.
If you use something like...
popup.show(textArea.get(now_focus), rectangle.x, rectangle.y + rectangle.height);
Where popup is a JPopupMenu, it will make the required translations to the screen itself.
Now. Having said that. Personally, I would prefer to use the popup API support provided by Swing. This is going to mean needing to create a custom component that extends from JTextArea to achieve it...
public class MyPopupTextArea extends JTextArea {
/*...*/
public Point getPopupLocation(MouseEvent evt) {
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
Point p = rectangle.getLoction();
p.y += rectangle.height;
return p;
}
}
Then, based on your needs, you can use setComponentPopup to provide a shared instance of the JPopupMenu or, if required, create a custom JPopupMenu for each instance of the custom editor and use setComponentPopup as you see fit...no messing about with mouse listeners ;)
I started doing the assignment number #3 by just adding a basic code to understand how it works. But I can’t get out of this problem. I just added an “if” so that if the input text is equal to “hr”, then the turtle would move 2 squares to the right every time. But when I run the code, it is as if it only checks the first characters. If the first two characters are “hr” then it marks a point, but if not, it never again checks the input. So for example if I write:
re
Fd
hr
It never marks the point even though “hr” is there. What can I do so that the TurtleRenderer reads the line every time a \n is inserted and not only once the code is run?
My code:
package turtle;
public class BoardMaker {
private static int MAX = 100;
private boolean[][] board = new boolean[MAX][MAX];
int previousX = 0;
int previousY = 0;
public boolean[][] makeBoardFrom(String description) {
if(description.contentEquals("hr")){
previousX+=2;
board[previousX][previousY]=true;
}
return board;
}
public boolean[][] initialBoard() {
for(int i=0;i<MAX;i++)
{
for(int j=0;j<MAX;j++)
board[i][j]=false;
}
return board;
}
}
The TurtleRenderer class:
package turtle;
public class TurtleRenderer extends Panel implements DocumentListener {
private static final long serialVersionUID = 1;
static final Dimension WINDOW_SIZE = new Dimension(1150, 1150);
boolean [][] board;
final BoardMaker boardMaker;
public TurtleRenderer() {
boardMaker = new BoardMaker();
board = boardMaker.initialBoard();
}
static public void main(String args[]) throws Exception {
JFrame frame = new JFrame("Display image");
JPanel panel = new JPanel();
TurtleRenderer image = new TurtleRenderer();
image.setPreferredSize(WINDOW_SIZE);
JScrollPane textArea = makeTextArea(image);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(image);
buildRightPanel(panel, textArea);
frame.setSize(WINDOW_SIZE);
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}});
frame.getContentPane().add(panel);
frame.setVisible(true);
}
static void buildRightPanel(JPanel panel,JComponent textArea) {
JLabel label = new JLabel("Your program:");
label.setPreferredSize(new Dimension(150, 20));
JPanel right = new JPanel();
textArea.setPreferredSize(new Dimension(150,500));
right.setLayout(new BoxLayout(right, BoxLayout.Y_AXIS));
right.add(label);
right.add(textArea);
panel.add(right);
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.white);
g.fillRect(0, 0, WINDOW_SIZE.width, WINDOW_SIZE.width);
if(board == null)
return;
g2d.setColor(Color.red);
for(int i=0;i<board.length;i++) {
for(int j=0;j<board.length;j++) {
if(board[i][j])
g2d.fillRect(9*i+1, 9*j+1, 6, 6);
}
}
}
static JScrollPane makeTextArea(TurtleRenderer image) {
JTextArea textArea = new JTextArea();
textArea.getDocument().addDocumentListener(image);
textArea.setVisible(true);
JScrollPane areaScrollPane = new JScrollPane(textArea);
areaScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane.setBorder(BorderFactory.createLineBorder(Color.black));
return areaScrollPane;
}
#Override
public void insertUpdate(DocumentEvent e) {
changed(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
changed(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
changed(e);
}
void changed(DocumentEvent de) {
String description;
Document document = de.getDocument();
try {
description = document.getText(0, document.getLength());
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
try {
board = boardMaker.makeBoardFrom(description);
} catch(ParserException pe) {
board = null;
}
this.repaint();
}
}
Your problem is that you're currently testing if the whole text held by the JTextArea holds "hr". This may be true if hr is the only text in the JTextArea, but once more text is added, this will always be false. What you need to check is if the last line is "hr".
Since this is homework, I won't post a solution, but a pseudo-code logic solution for your DocumentListener could be:
try
get the text String from the document
get the last char from this String
if this last Char == carriage return which is (char)10
split the text into lines using the carriage return as the split's delimiter
get the last line held by this array and check it
if it is hr do something
end if last char == carriage return
end try
catch for BadLocationException
From the Javadocs,
public boolean contentEquals(CharSequence cs)
Compares this string to the specified CharSequence.
The result is true if and only if this String represents the same sequence of char values as the specified sequence.
public boolean contains(CharSequence s)
Returns true if and only if this string contains the specified sequence of char values.
Thus String.contentEquals will function more of a type of String.equals method. There are some differences though.
As with this problem you would require String.contains method to check whether the text contains the String "hr"
One more advice with regards to code efficiency :
You don't have to perform any action in the changedUpdate(DocumentEvent e) method within the DocumentListener. This method is only called when an attribute or a set of attributes has changed, i.e. the style of the document has changed which is not possible in a JTextArea as it does not support styled text.
I hope I have understood your problem correctly.
First, as in a previous comment, the method makeBoardFrom will every time receive
the entire program. If is up to you to split that program into individual commands, and then execute each command. You should not attempt to change the TurtleRenderer class to behave differently.
Second, if you want to move the turtle to the left by two squares you have to mark both
squares as visited, not just the destination square. Right now in your solution, by only using previousX+=2; you only mark the destination square as visited.
Third, in the initialBoard method you also have to actually mark the initial square of the turtle with true. In your case that will be the square at position (0, 0).
Okay, so I am stumped. Does anyone know of a simple method for Java using NetBeans that will draw a graph (preferably a Pie Chart) using a paint component on the jPanel?
I have Googled, and researched and can't find a straight answer. I am still learning and this is the last component of my final for this class. I only need the method, if anyone knows a simple way to do this. It doesn't need to change as the requirement states that I only need a graphic; the program logic parses from the temp.textField. Any help or direction is greatly appreciated.
P.S. Yes, I have tried JFreeCharts.
private void jPanel1ComponentShown(java.awt.event.ComponentEvent evt) {
// Bar graph component and logic.
BorderLayout panelMapLayout = new BorderLayout();
jPanel1.setLayout(panelMapLayout);
jPanel1.add(Graph, BorderLayout.CENTER);
JFrame fr = new JFrame();
final int width = 300;
final int height = 400;
fr.setSize(width, height);
fr.setTitle("Grade Bar Graph");
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setVisible(true);
String str = JOptionPane.showInputDialog("What is the String file name?");
barGraphComponent component = new barGraphComponent();
fr.setVisible(true);
}
Above is my code - only a portion, but I think this will work. Anyone have any ideas how I can add logic to it? If need be I will throw the whole code up. I do not need it to change, only display an initial set of integers; but how do I get those integers into my graph?
Use JCommon & JFreechart jars.
I hope u can go with it..!
import java.io.File;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
public class JavaApplication3 {
DefaultCategoryDataset categoryDataset;
private String YaxisXaxis = "Hospital mortality rate";
private String Xaxis[] = {"2009APR-2010MAR", "2010APR-2011MAR", "2011APR-2011NOV"};
double val[] = {1.7879989, 1.6252073, 1.5941324};
JFreeChart chart ;
public void getinput() {
}
void setinp() {
categoryDataset = new DefaultCategoryDataset();
for (int i = 0; i < val.length; i++) {
categoryDataset.setValue(val[i], YaxisXaxis, Xaxis[i]);
}
}
void drawcharts(){
chart = ChartFactory.createBarChart3D("XYZ HOSPITALS", // Title
"Year", // X-Axis label
"Number of Students",// Y-Axis label
categoryDataset, // Dataset
PlotOrientation.VERTICAL,
true, // Show legend
true,
false
);
}
void savechart()
{
String fileName="d:/sp.jpg";
try {
/**
* This utility saves the JFreeChart as a JPEG
* First Parameter: FileName
* Second Parameter: Chart To Save
* Third Parameter: Height Of Picture
* Fourth Parameter: Width Of Picture
*/
ChartUtilities.saveChartAsJPEG(new File(fileName), chart, 800, 600);
} catch (IOException e) {
System.err.println("Problem occurred creating chart.");
}
}
public static void main(String[] args) {
// TODO code application logic here
JavaApplication3 obj =new JavaApplication3();
obj.setinp();
obj.drawcharts();
obj.savechart();
}
}
Try this sample... U can get easily...
i have written an application, but for some reason it keeps peaking at 100%. I ran a profile r on a few of the classes and a report show that isReset() and isRunning() seems to be called alot of times. Do you see anything wrong please inform me. thanks
Class 1 is the only class that uses the isReset() code so i hope this helps u guys in detecting the error
Class 1
package SKA;
/*
* ver 0.32 June 2009
*
* Bug Fix Release:
*
* Fixed Array resize
* Fixed Red Black Tree delete method
* Fixed Red Black Tree save/read option
* Update help file
*
*/
/*
* Additions:
* ver 0.30 May 2009
*
* Added Red Black Tree structure
* Added Delete method for canvases
* Added Array structure
* Added ability to recolor nodes.
* Added Bubble Sort Algorithm
* Added Insertion Sort Algorithm
* Added Shell Sort Algorithm
* Added Selection Sort Algorithm
* Added Quick Sort Algorithm
* Added Red Black Tree Search Algorithm
* Added Black Height Check Algorithm
* Bug fix in canvas - could not delete canvas properly
*/
// Additions:
/* ver 0.25 August 2004
* Added recursion in SkaExecutionPanel by adding SkaFunction
* and using desktop internal panes.
*
* Added binary tree node annotation - text and drawn
* Added subtree highlight feature to VizBinaryTreeNode using SkaRectangle
* Improved node highlighting and selection scheme in VizBinaryTrees/VizDS
* Added Binary tree save and read methods
* Added visual subtree deletion (has bug)
*
* Added ability to set breaks from within algorithm
* Added tooltip messages to SkaProgram/SkaFunction to show variable values
* Added simple value input and output methods to SkaProgram/SkaFunction
* Added SkaTriangle.
* Added Font Adjustment and Color scheme options to show on overhead projectors
*
* Found bug in SkaGraph deleteVertex (with edges)
*/
/* ver 0.16 October 15, 2001
Added Graph save and read methods.
Save is an instance method, while read is a class method.
Added circular layout for graphs,
Added fit/adjust graph layout to plate size method.
Added label editing for Binary Trees and Graphs.
SkaLabels (glyphs) now truncate the string displayed to the width specified
in the constructor.
*/
/* ver 0.15 July 21, 2001
Fixed Reset function in Execution using exceptions so that Ska Algorithms
can be run repeatedly without quitting the entire Ska System.
This also allows trying the same program on different data structures.
Problems with reset so far:
1. Reset message to user can appear much later.
I think this is an I/O sequencing problem and it should go away if
a message status GUI area is used.
2. Bound variable names remain afterwards,
e.g. Graph bound to G will still show name as G after
algorithm is interrupted.
Fixed problem with multiple input requests in 0.14 - by adding another
wait call which waits on before asking for input.
Also introduced trial orderly layout of canvas and program windows ,
which fixes problem in 0.14
*/
/* ver 0.14 July 18, 2001
Added subclasses of SkaProgram, so that multiple programs
can run simultaneously.
Problem - when multiple programs start, their windows overlay each other
Problem - Send DS to algorithm can get confused, if an algorithm
requests input while another is waiting on input or if
two algorithms request input at the same time
*/
/* ver 0.13
Added BinaryTree - does not have node value display yet.
Added arrows on edges of directed graphs
*/
/* ver 0.12
Added VizElementListener - separated from VizElement
Element Input menu item only highlights when input for that DS is requested
DS Input has been cleaned up
*/
/* ver 0.11
can ask user to select individual elements, e.g. vertices
removed standard java cloning code which wasn't being used anyway
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.border.BevelBorder;
import javax.swing.border.SoftBevelBorder;
// TimerQueue
public class SkaTest {
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
public static final int CANVAS_X = 100;
public static final int CANVAS_Y = 100;
public static final int CANVAS_FRAME_WIDTH = WIDTH+100;
public static final int CANVAS_FRAME_HEIGHT = HEIGHT + 100;
public static final int EXEC_WIDTH = 550;
public static final int EXEC_HEIGHT = 400;
static VizDSList dsList = new VizDSList();
static SkaCanvas canvas = new SkaCanvas(dsList);
static JFrame canvasFrame = new JFrame("Data Structure Canvas");
static JMenuBar menuBar = new JMenuBar();
static JMenu algorithmMenu = new JMenu("Algorithm");
static JMenu dsMenu = new JMenu("Create");
static JMenu helpMenu = new JMenu ("Help");
static JLabel status = new JLabel(" ");
static SkaProgram[] alg;
static JFrame execFrame[];
static SkaExecutionPanel execPanel[];
public static void setupFrames(int nAlgs) {
int i;
for (i=0; i < nAlgs; i++) {
// execFrame[i] = new JFrame("Execution Control Panel "+(i+1));
execFrame[i] = new JFrame();
execPanel[i] = new SkaExecutionPanel(execFrame[i]);
}
canvas.setMinimumSize(new Dimension(WIDTH, HEIGHT));
canvasFrame.setSize(CANVAS_FRAME_WIDTH, CANVAS_FRAME_WIDTH);
canvasFrame.getContentPane().setLayout(new BorderLayout(10,7));
// canvasFrame.getContentPane().setPreferredSize(new Dimension(WIDTH, HEIGHT));
canvasFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// canvas.setMinimumSize(new Dimension(WIDTH, HEIGHT));
for (i=0; i < nAlgs; i++) {
execFrame[i].setSize(EXEC_WIDTH, EXEC_HEIGHT);
// execFrame[i].getContentPane().setLayout(new BorderLayout(10,7));
execFrame[i].addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
execPanel[i].setBorder(new SoftBevelBorder(BevelBorder.RAISED));
// execFrame[i].setContentPane(execPanel[i]);
execFrame[i].getContentPane().add("Center", execPanel[i]);
// execFrame[i].setLocation(CANVAS_X +CANVAS_FRAME_WIDTH, CANVAS_Y + i*EXEC_HEIGHT);
execFrame[i].setLocation(CANVAS_X +CANVAS_FRAME_WIDTH + i*30, CANVAS_Y + i*50);
}
canvas.setBorder(new SoftBevelBorder(BevelBorder.RAISED));
canvasFrame.getContentPane().add("Center", new JScrollPane(canvas) );
// canvasFrame.getContentPane().add("Center", new JScrollPane(canvas, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS) );
canvasFrame.getContentPane().add("South", status);
canvasFrame.setLocation(CANVAS_X, CANVAS_Y);
JMenu fileMenu = new JMenu("File");
JMenuItem quitItem = new JMenuItem("Quit");
//TODO Add quit listener
quitItem.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent arg0) {
//System.exit(0);
int again = JOptionPane.showConfirmDialog(null, "Are you sure you want to exit system", "Exiting", JOptionPane.YES_NO_OPTION);
if (again == JOptionPane.YES_OPTION)
{
System.exit(0);
}
}
}
);
fileMenu.add(quitItem);
menuBar.add(fileMenu);
menuBar.add(algorithmMenu);
// menuBar.add(dsMenu);
menuBar.add(helpMenu);
JMenuItem help = new JMenuItem ("Help Contents");
//help.setMnemonic(KeyEvent.VK_H);
//TODO Fix this method
help.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, ActionEvent.CTRL_MASK));
help.addActionListener(new ActionListener()
{
/*
#Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Alot of the functionality have not yet been included in this version\nCurrently working on the automation features now!", "SKA 0.2 Beta", JOptionPane.WARNING_MESSAGE);
}
*/
public void actionPerformed(ActionEvent arg0) {
try {
Runtime.getRuntime().exec("hh.exe C:/ska.chm");
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "File not found", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
JMenuItem about = new JMenuItem ("About SKA");
about.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "SKA Version 0.1 Beta");
}
});
helpMenu.add(help);
helpMenu.add(about);
canvasFrame.setJMenuBar(menuBar);
}
/** The create menu item */
public static void createProgram(int i) {
JMenuItem algItem;
switch (i) {
case 0 :
alg[0] = new RedBlackValidate(canvas, execPanel[0]);
execFrame[0].setTitle("Validate Algorithm");
System.out.println("Validate Algorithm");
algItem = new JMenuItem("Validate Algorithm");
algorithmMenu.add(algItem);
break;
/* case 0 :
alg[0] = new BreadthFirstSearch(canvas, execPanel[0]);
execFrame[0].setTitle("BFS Graph Algorithm");
// System.out.println("BreadthFirstSearch");
algItem = new JMenuItem("BFS Graph Algorithm");
algorithmMenu.add(algItem);
break;
case 1:
alg[1] = new LevelOrderAlgorithm(canvas, execPanel[1]);
execFrame[1].setTitle("Level Order Tree Algorithm");
System.out.println("LevelOrderAlgorithm");
algItem = new JMenuItem("Level Order Tree Algorithm");
algorithmMenu.add(algItem);
break;
case 2:
alg[2] = new BinarySearchTreeAlgRecursive(canvas, execPanel[2]);
execFrame[2].setTitle("BinaryTreeSearchRec Algorithm");
System.out.println("BinaryTreeSearchRec Algorithm");
algItem = new JMenuItem("BinaryTreeSearchRec Algorithm");
algorithmMenu.add(algItem);
break;
case 3:
alg[3] = new BinarySearchTreeAlgIterative(canvas, execPanel[3]);
execFrame[3].setTitle("BinaryTreeSearchIter Algorithm");
System.out.println("BinaryTreeSearchIter Algorithm");
algItem = new JMenuItem("BinaryTreeSearchIter Algorithm");
algorithmMenu.add(algItem);
break;
case 4:
alg[4] = new RebBlackTreeSearch (canvas, execPanel[4]);
execFrame[4].setTitle("Red Black Search Algorithm");
System.out.println("Red Black Search Algorithm");
algItem = new JMenuItem("Red Black Search Algoithm Algorithm");
algorithmMenu.add(algItem);
break;
case 5:
alg[5] = new ArrayInsertionSortAlg (canvas, execPanel[5]);
execFrame[5].setTitle("Array Insertion Sort Algorithm");
System.out.println("Array Insertion Sort");
algItem = new JMenuItem("Array Insertion Sort Algorithm");
algorithmMenu.add(algItem);
break;
case 6:
alg[6] = new ArraySelectionSortAlg (canvas, execPanel[6]);
execFrame[6].setTitle("Array Selection Sort Algorithm");
System.out.println("Array SelectionSearch");
algItem = new JMenuItem("Array Selection Sort Algorithm");
algorithmMenu.add(algItem);
break; */
default:
break;
}
}
public static void main(String args[]) {
int i, nAlgs = 1; //nAlgs = 7;
alg = new SkaProgram[nAlgs];
execPanel = new SkaExecutionPanel[nAlgs];
execFrame = new JFrame[nAlgs];
// canvas.setDebugGraphicsOptions(DebugGraphics.BUFFERED_OPTION);
setupFrames(nAlgs);
canvasFrame.setVisible(true);
for (i=0; i < alg.length; i++) {
createProgram(i);
execFrame[i].setVisible(true);
alg[i].start();
alg[i].displayAlgorithm();
}
while (true) {
for (i=0; i < alg.length; i++)
if (execPanel[i].isReset()) {
alg[i].terminate();
createProgram(i);
alg[i].start();
execPanel[i].unreset();
}
}
}
} // End class SkaTest
Class 2
package SKA;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Stack;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
#SuppressWarnings("serial")
public
class SkaExecutionPanel extends JDesktopPane {
public static final int EXEC_WIDTH = SkaTest.EXEC_WIDTH-100;
public static final int EXEC_HEIGHT = SkaTest.EXEC_HEIGHT-50;
boolean run = false, pause = true, step = false, reset = false;
JToolBar toolbar = new JToolBar();
JTextArea textOutputArea = new JTextArea();
SkaProgram prog;
Stack<SkaFunction> functionStack = new Stack<SkaFunction>();
SkaFunction currentFunction = null;
int level = 0, in = 30;
public void doCall(String[] subAlg, String subAlgName) {
doCall(subAlg, subAlgName, false); // make non-icon default
}
public void doCall(String[] subAlg, String subAlgName, boolean iconify) {
if (currentFunction != null)
functionStack.push(currentFunction);
currentFunction = new SkaFunction(this, subAlg, subAlgName, iconify);
add(currentFunction, new Integer(1));
currentFunction.setBounds(level*in,level*in,EXEC_WIDTH, EXEC_HEIGHT);
// currentFunction.setBounds(level*in,level*in,EXEC_WIDTH-(level+1)*in, EXEC_HEIGHT-(level+1)*in);
currentFunction.setVisible(true);
level++;
}
public void doReturn() {
if (currentFunction == null)
return;
if (currentFunction.makeIconWhenDone()) {
getDesktopManager().iconifyFrame(currentFunction);
// currentFunction.setIcon(true);
currentFunction.setIconifiable(true);
}
else
currentFunction.setVisible(false);
currentFunction = (SkaFunction) functionStack.pop();
level--;
}
public void displayAlgorithm(String[] a) {
doCall(a, "main");
}
public void displayAlgorithm(String[] a, String aname) {
doCall(a, aname);
}
public void setControlsEnabled(boolean b) {
toolbar.setEnabled(b);
}
class RunAction extends AbstractAction {
RunAction() {
super("run");
}
public void actionPerformed(ActionEvent e) {
run = true; pause = false; step = false;
}
}
class StepAction extends AbstractAction {
StepAction() {
super("step");
}
public void actionPerformed(ActionEvent e) {
run = false; pause = false; step = true;
}
}
class PauseAction extends AbstractAction {
PauseAction() {
super("pause");
}
public void actionPerformed(ActionEvent e) {
pause = true;
// System.out.print("breaks");
// for (int i=0; i<breaks.length; i++)
// System.out.print("[" +i+ "]=" + breaks[i].toString() + " ");
// System.out.println("");
}
}
class ResetAction extends AbstractAction {
ResetAction() {
super("reset");
putValue(Action.SHORT_DESCRIPTION, "stop program and reset state to begining");
}
public void actionPerformed(ActionEvent e) {
run = false; pause = true; step = false;
// should also restart SkaProgram
reset = true;
if (currentFunction != null) currentFunction.reset();
/*
JInternalFrame[] frames = getAllFrames();
for (int i = 0; i < frames.length; i++) {
// frames[i].dispose();
if (frames[i].isIcon())
frames[i].dispose();
}
*/
}
}
JComboBox speedControl;
String speedNames[] = { "slow", "normal", "fast", "very fast" };
int speeds[] = {4000, 2000, 1000, 500} ; // milliseconds
int speed = speeds[1];
private void initSpeedMenu() {
speedControl = new JComboBox(speedNames);
// speedControl.setMaximumRowCount(3);
speedControl.addItemListener(
new ItemListener() {
public void itemStateChanged( ItemEvent e) {
speed = speeds[speedControl.getSelectedIndex()];
}
}
);
speedControl.setSelectedIndex(1);
speedControl.setMaximumSize(speedControl.getPreferredSize());
speedControl.setToolTipText("execution speed");
}
SkaExecutionPanel(JFrame frame) {
initSpeedMenu();
toolbar.add(new RunAction());
toolbar.add(new StepAction());
toolbar.add(new ResetAction());
toolbar.add(new PauseAction());
toolbar.addSeparator();
toolbar.add(speedControl);
// frame.getContentPane().setLayout(new BorderLayout(10,7));
// makeTable();
frame.getContentPane().add("North", toolbar);
Font f = new Font("SansSerif", Font.BOLD, 14);
textOutputArea.setFont(f);
frame.getContentPane().add("South", new JScrollPane(textOutputArea));
// frame.getContentPane().add(this, BorderLayout.CENTER)
// frame.getContentPane().add("Center", toolbar, BorderLayout.NORTH);
// setSize(300,250);
// add toolbar, table, set layout, sizes
}
// public void setAlgorithm(SkaProgram p) {
// prog = p;
// sendAlgorithm(p.getPseudocode());
// }
public int getSpeed() { return speed;
}
public boolean isRunning() { return run;
}
public boolean isPaused() { return pause;
}
public boolean isStepping() { return step;
}
public boolean isReset() { return reset;
}
public void pause() { pause = true;
}
public void unreset() { reset = false;
}
public void aboutToWait() {
currentFunction.aboutToWait();
}
public void doneWait() {
currentFunction.doneWait();
}
public void showToolTipValue(String s) {
currentFunction.showToolTipValue(s);
}
public void showAlgLineBreak(int i) {
currentFunction.showAlgLineBreak(i);
}
public void showAlgLine(int i) {
currentFunction.showAlgLine(i);
}
public void displayText(String s) {
textOutputArea.append(s); // +"\n" add newline?
}
} // End class SkaExecutionPanel
The problem doesn't seem to be in the methods which are being used a lot, it's how frequently you call them which appears to be why they are showing up so frequently. I'd check for all of the calls, see if any are superfluous then go to the third most time consuming method. After that, I would check my algorithms for being particularly intensive. Also, check all method calls and make sure they're not being run without need.
I know this isn't solving the problem itself, but its a start with the information given.
EDIT: The while loop is an infinite loop causing a for loop to run in which every item in an array has been checked to see if its been reset. You can replace this with an observer pattern where when an object is reset, it notifies the observing object which then performs that set of steps. This way you don't have an infinite loop and you cut down on the usage of .isReset(). This is in the main method of Class 1.
Edit 2: Here's the example of an implementation of the observer pattern which is on wikipedia.
"How do I start optimising my Java code?"
You start by profiling it first.
Start with the most intensively used method in your readout and move to less and less intense methods until you find one with a loop construct (for, while). Check the loop construct to see if it is doing too much work, and see if the functions that call this function call it often.
i.e (pseudocode)
dotProduct(vector a, vector b)
{
//create vector dot product here
maths maths maths
}
calc(data)
{
for obj in data:
dotproduct(obj, foo)
}
dotProduct will use the most CPU time, but calc is the place to start - can we cache results? are we recalculating data? Are we iterating through data in a stupid way?
Judging by the function names "isReset()" and "isRunning()" being called a lot, I would guess that you're wasting CPU time polling for a condition/event. Java should have some sort of semaphore/signalling system that you can use to let the do-er notify the wait-er exactly when the event occurs.
First things first. you have a warning in you code somewhere, as that you have used the annotation
#SuppressWarnings("serial"). While this very well may have nothing to with your cpu maxing out. Fix this first and you very well may stumble on the problem.