I am developing a desktop application in java swing; in which I need to take a bill print on dot matrix printer, the print will be having name, address and table which will be having item, qty, price…etc, which should be printed as per their x, y positions on paper, font stored in database .
But in print there is issue of overlapping/attaching letters if I use the following code:
class BillPrint implements ActionListener, Printable
{
PrintMngt PM=new PrintMngt();
public int print(Graphics gx, PageFormat pf, int page) throws PrinterException {
if (page>0){return NO_SUCH_PAGE;}
Graphics2D g = (Graphics2D)gx; //Cast to Graphics2D object
g.translate(pf.getImageableX(), pf.getImageableY());
Vector<Vector<Object>> data =PM.getvarientDetail(printID);
for (int i = 0; i <data.size(); i++) {
if(data.get(i).get(3).toString().equalsIgnoreCase("DYNAMIC"))
{
String bill_no=textField_Trans.getText();
int TblH,TblL;
Vector<String> Tbl_HL=PM.getTblHieghtNoLline(printID);
//PRINT_ID0, QUERY_STATIC1, OBJECT_NAME2, QUERY_TYPE3, X4, Y5, WIDTH6,
//ALIGN7, FONT8, F_SIZE9, F_STYLE10, SECTION11, LOOPES_NO12, OBJ_FORMAT13, VARIANT_ID14
TblH=Integer.parseInt(Tbl_HL.get(0).toString());
TblL=Integer.parseInt(Tbl_HL.get(1).toString());
int x=Integer.parseInt(data.get(i).get(4).toString());
int y=Integer.parseInt(data.get(i).get(5).toString());
String fName=data.get(i).get(8).toString();
int fSize=Integer.parseInt(data.get(i).get(9).toString());
String fStyle=data.get(i).get(10).toString();
Font font=null;
if(fStyle.equalsIgnoreCase("Plain"))
{
font = new Font(fName,Font.PLAIN, fSize);
}
else if(fStyle.equalsIgnoreCase("Bold"))
{
font = new Font(fName,Font.BOLD, fSize);
}
else if(fStyle.equalsIgnoreCase("Italic"))
{
font = new Font(fName,Font.ITALIC, fSize);
}
else if(fStyle.equalsIgnoreCase("Bold Italic"))
{
font = new Font(fName,Font.BOLD+ Font.ITALIC, fSize);
}
System.out.println("Myqry"+data.get(i).get(1).toString());
Vector<String> Query_Static=PM.getQuery_Static(data.get(i).get(1).toString(),bill_no);
for (int j = NoOfProd; j < Query_Static.size(); j++) {
g.drawString(Query_Static.get(j).toString(),x,y);
y=y+TblH/TblL;
g.setFont(font);
}
}
}
return PAGE_EXISTS; //Page exists (offsets start at zero!)
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
int ProductCnt= PM.getNoProduct(textField_Trans.getText().toString());//no. of products under given billno
int TableLine=PM.getTblNoLline(printID);//no. of lines to print
System.out.println("No of TableLines="+TableLine);
System.out.println("No of Product="+ProductCnt);
for (int i = 0; i <(TableLine/ProductCnt); i++)
{
job.print();
NoOfProd=NoOfProd+TableLine;
}
NoOfProd=0;
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}//end actionPerformed
}//end BillPrint
I have also tried with writing data to .txt file and then printing it. Here output is proper i.e letters are not overlapping , but here in this method I m not able to give proper positions for my data. Following method I used for this:
private void printData(){
File output = new File("E:\\PrintFile1.txt");
output.setWritable(true);
String billNo="B1000", patient = "ABC";
try
{
BufferedWriter out = new BufferedWriter(new FileWriter(output));
out.write(billNo + "\n");
out.write(patient + "\n" );
out.write("\n");
out.write("\n");
out.close();
}
catch (java.io.IOException e)
{
System.out.println("Failed to write Output");
}
FileInputStream textStream = null;
try
{
textStream = new FileInputStream("E:\\PrintFile1.txt");
}
catch (java.io.FileNotFoundException e)
{
System.out.println("Error trying to find the print file.");
}
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
Doc mydoc = new SimpleDoc(textStream, flavor, null);
PrintService printer = PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob printJob = printer.createPrintJob();
try
{
printJob.print(mydoc, null);
}
catch (javax.print.PrintException e)
{
JOptionPane.showMessageDialog(this, "Error occured while attempting to print.", "Error!", JOptionPane.ERROR_MESSAGE);
}
}
Basically for the issue in the letters i just add one space for each character in the string
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
public class Print implements Printable {
/* Just add one space for all charaters */
String numero = "Numero Nro :";
String numeroreplace = numero.replaceAll(".(?=.)", "$0 ");
public Print() {
super();
}
/* The font for you string */
public int print(Graphics g,PageFormat pf, int page) throws PrinterException{
Font textFont = new Font(Font.SANS_SERIF,Font.PLAIN,8);
/* To set the position, you can use for or while if u need it. */
g.setFont(textFont);
g.drawString(numeroreplace,350,150);
}
}
Finally you need to copy all this code just add one space for all characters in code.
Note : you must be call from yor main program.
Related
on Clicking the button, I m loading the function WriteJsonForLevel(). I have placed three GameObject with the tag name "RedCoin" and I want to write the position of the GameObject to a JSON file. I can get the position of the object, but it's all overwritten. I can only see the last GameObject position (i.e the completion of the loop)
public List<GameObject> levelObjects;
public string level;
public Vector3 pos;
// Start is called before the first frame update
void Start()
{
levelObjects = new List<GameObject>();
}
// Update is called once per frame
void Update()
{
}
public void WritejsonForAll()
{
WriteJsonForLevel();
}
public void WriteJsonForLevel()
{
/* FileStream fs = new FileStream(Application.dataPath + "/sample.json",FileMode.Create);
StreamWriter writer= new StreamWriter(fs);*/
GameObject[] coinObjRed = GameObject.FindGameObjectsWithTag("RedCoin");
putAllObjectInList(coinObjRed);
}
public void putAllObjectInList(GameObject[] p)
{
string path = Application.dataPath + "/text.json";
foreach (GameObject q in p)
{
levelObjects.Add(q);
}
for (int i = 0; i < levelObjects.Count; i++)
{
GameObject lvlObj = levelObjects[i];
Vector3 pos = lvlObj.transform.position;
string posOutput = JsonUtility.ToJson(pos);
File.WriteAllText(path,posOutput);
Debug.Log("position:" + posOutput);
}
}
}
You are using WriteAllText which will overwrite the file every time it is called. As it is overwriting each time it is in the loop, it will only write the last object to the file as every other previous write is overwritten. I would consider making a serialized class of data, assigning the data to it, converting it to a JSON string then saving that.
// stores individual locations for saving
[System.Serializable]
public class IndividualLocation
{
public IndividualLocation(Vector3 pos)
{
xPos = pos.x;
yPos = pos.y;
zPos = pos.z;
}
public float xPos;
public float yPos;
public float zPos;
}
// stores all game locations for saving
[System.Serializable]
public class AllGameLocations
{
public List<IndividualLocation> Locations = new List<IndividualLocation>();
}
public void PutAllObjectInList(in GameObject[] p)
{
string path = Application.dataPath + "/text.json";
// create a new object to write to
AllGameLocations data = new AllGameLocations();
// iterate the objects adding each to our structure
foreach(GameObject obj in p)
{
data.Locations.Add(new IndividualLocation(obj.transform.position));
}
// now that the data is filled, write out to the file
File.WriteAllText(path, JsonUtility.ToJson(AllGameLocations));
}
If you need a snippet on how to load the data properly I can add one.
Edit: Here is a load snippet
public void LoadJSONObject()
{
string path = Application.dataPath + "/text.json";
// if the file path or name does not exist
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Debug.LogWarning("File or path does not exist! " + path);
return
}
// load in the save data as byte array
byte[] jsonDataAsBytes = null;
try
{
jsonDataAsBytes = File.ReadAllBytes(path);
Debug.Log("<color=green>Loaded all data from: </color>" + path);
}
catch (Exception e)
{
Debug.LogWarning("Failed to load data from: " + path);
Debug.LogWarning("Error: " + e.Message);
return;
}
if (jsonDataAsBytes == null)
return;
// convert the byte array to json
string jsonData;
// convert the byte array to json
jsonData = Encoding.ASCII.GetString(jsonDataAsBytes);
// convert to the specified object type
AllGameLocations returnedData;
JsonUtility.FromJsonOverwrite<AllGameLocations>(jsonData, AllGameLocations);
// use returnedData as a normal object now
float firstObjectX = returnedData.Locations[0].xPos;
}
}
Let me know if the Load works, just typed it up untested. Added some error handling as well to assure data exists and the load properly works.
I am writing to an Excel file using Apache POI, but I want my output to be formatted as HTML not as literal text.
SXSSFWorkbook workbook = new SXSSFWorkbook();
Sheet sheet0 = workbook.createSheet("sheet0");
Row row0 = sheet0.createRow(2);
Cell cell0 = row0.createCell(2);
cell0.setCellValue("<html><b>blah blah blah</b></html>");
What appears when I open the Excel file is:
"<html><b>blah blah blah</b></html>"
but I want:
"blah blah blah"
essentially I am looking for a piece of code along the lines of:
cell0.setCellFormat(CellFormat.HTML);
Except, that doesn't exist.
here is some info on this topic
http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java
I will try this for now:
public void printPage() throws IOException {
try {
ensureOut();
if (completeHTML) {
out.format(
"<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>%n");
out.format("<html>%n");
out.format("<head>%n");
out.format("</head>%n");
out.format("<body>%n");
}
print();
if (completeHTML) {
out.format("</body>%n");
out.format("</html>%n");
}
} finally {
if (out != null)
out.close();
if (output instanceof Closeable) {
Closeable closeable = (Closeable) output;
closeable.close();
}
}
}
Based on my version for DocX, here is the adapted version for Hssf. As with the other version, you'll have to debug and extend the loop for the various css styles.
Update: I've overlooked yesterday, that you wanted to have a streaming XSSF solution, so I fiddled around, if it's possible to just use the usermodel classes (not really, when it comes to font colors), furthermore I wondered why SXSSF didn't use any of my font setting until I found out, that's currently by design (see Bug 52484)
import java.awt.Color;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.Enumeration;
import javax.swing.text.*;
import javax.swing.text.html.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
public class StyledTextXls {
public static void main(String[] args) throws Exception {
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument)kit.createDefaultDocument();
kit.insertHTML(doc, doc.getLength(), "<p>paragraph <b>1</b></p>", 0, 0, null);
kit.insertHTML(doc, doc.getLength(), "<p>paragraph <span style=\"color:red\">2</span></p>", 0, 0, null);
Workbook wb = new XSSFWorkbook();
// Workbook wb = new HSSFWorkbook();
// Workbook wb = new SXSSFWorkbook(100); // doesn't work yet - see Bug 52484
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
StringBuffer sb = new StringBuffer();
for (int lines=0, lastPos=-1; lastPos < doc.getLength(); lines++) {
if (lines > 0) sb.append("\n");
Element line = doc.getParagraphElement(lastPos+1);
lastPos = line.getEndOffset();
for (int elIdx=0; elIdx < line.getElementCount(); elIdx++) {
final Element frag = line.getElement(elIdx);
String subtext = doc.getText(frag.getStartOffset(), frag.getEndOffset()-frag.getStartOffset());
sb.append(subtext);
}
}
CreationHelper ch = wb.getCreationHelper();
RichTextString rt = ch.createRichTextString(sb.toString());
for (int lines=0, lastPos=-1; lastPos < doc.getLength(); lines++) {
Element line = doc.getParagraphElement(lastPos+1);
lastPos = line.getEndOffset();
for (int elIdx=0; elIdx < line.getElementCount(); elIdx++) {
final Element frag = line.getElement(elIdx);
Font font = getFontFromFragment(wb, frag);
rt.applyFont(frag.getStartOffset()+lines, frag.getEndOffset()+lines, font);
}
}
cell.setCellValue(rt);
cell.getCellStyle().setWrapText(true);
row.setHeightInPoints((6*sheet.getDefaultRowHeightInPoints()));
sheet.autoSizeColumn((short)0);
FileOutputStream fos = new FileOutputStream("richtext"+(wb instanceof HSSFWorkbook ? ".xls" : ".xlsx"));
wb.write(fos);
fos.close();
}
static Font getFontFromFragment(Workbook wb, Element frag) {
// creating a font on each is call is not very efficient
// but should be ok for this exercise ...
Font font = wb.createFont();
final AttributeSet as = frag.getAttributes();
final Enumeration<?> ae = as.getAttributeNames();
while (ae.hasMoreElements()) {
final Object attrib = ae.nextElement();
try {
if (CSS.Attribute.COLOR.equals(attrib)) {
// I don't know how to really work with the CSS-swing class ...
Field f = as.getAttribute(attrib).getClass().getDeclaredField("c");
f.setAccessible(true);
Color c = (Color)f.get(as.getAttribute(attrib));
if (font instanceof XSSFFont) {
((XSSFFont)font).setColor(new XSSFColor(c));
} else if (font instanceof HSSFFont && wb instanceof HSSFWorkbook) {
HSSFPalette pal = ((HSSFWorkbook)wb).getCustomPalette();
HSSFColor col = pal.findSimilarColor(c.getRed(), c.getGreen(), c.getBlue());
((HSSFFont)font).setColor(col.getIndex());
}
} else if (CSS.Attribute.FONT_WEIGHT.equals(attrib)) {
if ("bold".equals(as.getAttribute(attrib).toString())) {
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
}
}
} catch (Exception e) {
System.out.println(attrib.getClass().getCanonicalName()+" can't be handled.");
}
}
return font;
}
}
I'm using this to send a htlm file direclty to printer and it says invalid flavour which means that the printer does not support the formats. Any one have an idea to do this..
/**
* #param args
*/
public static void main(String[] args) {
// Input the file
FileInputStream textStream = null;
try {
textStream = new FileInputStream("./some.html");
} catch (FileNotFoundException ffne) {
}
if (textStream == null) {
return;
}
// Set the document type
DocFlavor myFormat = DocFlavor.INPUT_STREAM.TEXT_HTML_HOST;
// Create a Doc
Doc myDoc = new SimpleDoc(textStream, myFormat , null);
// Build a set of attributes
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(new Copies(1));
//aset.add(MediaSize.NA.LEGAL);
aset.add(Sides.ONE_SIDED);
// discover the printers that can print the format according to the
// instructions in the attribute set
PrintService services = PrintServiceLookup.lookupDefaultPrintService();
//PrintServiceLookup.lookupPrintServices(myFormat, aset);
// Create a print job from one of the print services
//System.out.println("====5======="+service.get);
//if (services.length > 0) {
for (int i = 0; i < services.getSupportedDocFlavors().length; i++) {
System.out.println("====getSupportedDocFlavors======="+services.getSupportedDocFlavors()[i]);
}
DocPrintJob job = services.createPrintJob();
try {
job.print(myDoc, aset);
} catch (PrintException pe) {
System.out.println("====PrintException======="+pe);
}
//}
}
It says
sun.print.PrintJobFlavorException: invalid flavor
You are trying to force printer to handle (render) HTML document onto the paper. It will never work that way. And ofcourse the flavor you are sending is not supported.
First of all you need to render HTML into some graphical representation and then send it to printer. There are no good cross-platform tools for Java that could render modern HTML pages. But there is one in JavaFX and i guess you could use it to handle the task.
About printing the final image you can read here:
http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-Printing.html
or see the code here:
http://www.java2s.com/Code/Java/2D-Graphics-GUI/PrintanImagetoprintdirectly.htm
or just find any other resource - there are a lot about printing.
public class POSPrinter {
private static final Log LOG = LogFactory.getLog(POSPrinter.class);
public POSPrinter(Long billID, String printMode) {
}
/**
*
* This method prints the specified PDF to specified printer under specified
*
* job name
*
*
*
* #param filePath
* Path of PDF file
*
* #param printerName
* Printer name
*
* #param jobName
* Print job name
*
* #throws IOException
*
* #throws PrinterException
*/
public void printPDF(String filePath, String printerName, String jobName,
Integer height, Integer width) throws IOException, PrinterException {
FileInputStream fileInputStream = new FileInputStream(filePath);
byte[] pdfContent = new byte[fileInputStream.available()];
fileInputStream.read(pdfContent, 0, fileInputStream.available());
ByteBuffer buffer = ByteBuffer.wrap(pdfContent);
final PDFFile pdfFile = new PDFFile(buffer);
Printable printable = new Printable() {
public int print(Graphics graphics, PageFormat pageFormat,
int pageIndex) throws PrinterException {
int pagenum = pageIndex + 1;
if ((pagenum >= 1) && (pagenum <= pdfFile.getNumPages())) {
Graphics2D graphics2D = (Graphics2D) graphics;
PDFPage page = pdfFile.getPage(pagenum);
Rectangle imageArea = new Rectangle(
(int) pageFormat.getImageableX(),
(int) pageFormat.getImageableY(),
(int) pageFormat.getImageableWidth(),
(int) pageFormat.getImageableHeight());
graphics2D.translate(0, 0);
PDFRenderer pdfRenderer = new PDFRenderer(page, graphics2D,
imageArea, null, null);
try {
page.waitForFinish();
pdfRenderer.run();
} catch (InterruptedException exception) {
exception.printStackTrace();
}
return PAGE_EXISTS;
} else {
return NO_SUCH_PAGE;
}
}
};
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = PrinterJob.getPrinterJob().defaultPage();
printJob.setJobName(jobName);
Book book = new Book();
book.append(printable, pageFormat, pdfFile.getNumPages());
printJob.setPageable(book);
Paper paper = new Paper();
paper.setSize(width, height);
paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight());
// pageFormat
pageFormat.setPaper(paper);
// PrintService[] printServices = PrinterJob.lookupPrintServices();
//
// for (int count = 0; count < printServices.length; ++count) {
//
// if (printerName.equalsIgnoreCase(printServices[count].getName())) {
//
// printJob.setPrintService(printServices[count]);
//
// break;
//
// }
//
// }
PrintService printService = PrintServiceLookup
.lookupDefaultPrintService();
printJob.setPrintService(printService);
printJob.print();
}
I have to limit the number of rows in a JTable. If I have 100 records I need to display 10 on the initial loading of JTable. I wish to put a button like "next", and after each click it shows another set of 10 records.
I have to limit the number of rows in a JTable. If i have 100 records i need to display 10 on the initial loading of JTable.
Use preferred size (+ an appropriate layout and layout constraint) to fix the size.
I wish to put a button like "next", and after each click it showing another set of 10 records.
Remove the scroll bar on the RHS of the scroll pane. Then use buttons instead for the effect of 'next/previous'.
Like this
FixedRowsTable.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
class FixedRowsTable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String[] columns = {"1","2","3","4","5","6","7"};
Integer[][] data = new Integer[1000][columns.length];
for (int xx=0; xx<data.length; xx++) {
for (int yy=0; yy<data[0].length; yy++) {
data[xx][yy] = new Integer((xx+1)*(yy+1));
}
}
final int rows = 11;
JPanel gui = new JPanel(new BorderLayout(3,3));
final JTable table = new JTable(
new DefaultTableModel(data, columns));
final JScrollPane scrollPane = new JScrollPane(
table,
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
Dimension d = table.getPreferredSize();
scrollPane.setPreferredSize(
new Dimension(d.width,table.getRowHeight()*rows));
JPanel navigation = new JPanel(
new FlowLayout(FlowLayout.CENTER));
JButton next = new JButton(">");
next.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
int height = table.getRowHeight()*(rows-1);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue( bar.getValue()+height );
}
} );
JButton previous = new JButton("<");
previous.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
int height = table.getRowHeight()*(rows-1);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue( bar.getValue()-height );
}
} );
navigation.add(previous);
navigation.add(next);
gui.add(scrollPane, BorderLayout.CENTER);
gui.add(navigation, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
If you use an AbstractTableModel you can display millions of records. The idea is that your model will be loading whatever records are needed for the view, on demand.
Here you have such a Model. It's not my best code, but will do :-) ...
public class SomeTableModel extends AbstractTableModel {
public SomeTableModel(ResultSet rs) {
this.rs = rs;
try {
pos = this.rs.getRow();
System.out.println(String.valueOf(pos));
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
public int getRowCount() {
int cnt = 0;
int apos = 0;
try {
apos = rs.getRow();
rs.last();
cnt = rs.getRow();
if (apos > 0)
rs.absolute(apos);
} catch (SQLException ex) {
System.out.println("getRowCount: " + ex);
}
return cnt;
}
public int getColumnCount() {
return 3;
}
public Object getValueAt(int rowIndex, int columnIndex) {
// make it jump back to pos !!
Object val = null;
Integer intVal;
try {
if (rowIndex == 0) {
pos = rs.getRow();
total = getRowCount();
}
rs.absolute(rowIndex + 1);
switch (columnIndex) {
case 0: intVal = rs.getInt(1); val = intVal; break;
case 1: val = rs.getString(2); break;
case 2: val = rs.getString(3); break;
default: val = "error";
}
rs.absolute(pos);
} catch (SQLException sqle) {
JOptionPane.showMessageDialog(null, "Trouble in model");
}
return val;
}
private ResultSet rs;
private int pos, total;
}
If you are loading the data from a database table, I think the best way to go is to limit the data coming from the database. Then apply a simple algorithm for the next and previous buttons.
Hi I am currently doing my final year project; I need to develop an algorithm visualization tool. I need to cater for user-defined algo; that is animate the algorithm the user types in a text-editor provided in my tool.
I am using the Java Compiler API to compile the code that the user has typed and saved. My tool offers a set of classes that the user can use in his/her algo.
For example:
myArray(this class is provided by my tool)
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
public class myArray extends JComponent {
int size = 0;
int count = 0;
int[]hold;
Thread th;
public myArray(int[]arr)//pass user array as parameter
{
//th = new Thread();
size=arr.length;
hold = arr;//make a copy of the array so as to use later in swap operation
}
public int length()
{
return hold.length;
}
public void setAccessibleContext(AccessibleContext accessibleContext) {
this.accessibleContext = accessibleContext;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
this.setPreferredSize(new Dimension(360,100));
for(int i=1; i<=size; i++)
{
g2d.drawRect((i*30), 30, 30, 50);
}
for(int i=1; i<=size; i++)
{
g2d.drawString(Integer.toString(hold[i-1]), (i*30)+15, 30+25);
}
}
public void set(int i, int j)//position of the two elements to swap in the array
{
try {
th.sleep(2000);//sleep before swapping because else user won't see original array since it would swap and then sleep
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int temp = hold[i];
hold[i] = hold[j];
hold[j] = temp;
hold[i]=j;
this.repaint();//can use eapint with a class that extends JPanel
}
public void swap(int i, int j)//position of the two elements to swap in the array
{
try {
th.sleep(2000);//sleep before swapping because else user won't see original array since it would swap and then sleep
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int temp = hold[i];
hold[i] = hold[j];
hold[j] = temp;
this.repaint();//can use eapint with a class that extends JPanel
}
public int get(int pos)
{
return hold[pos];
}
}
This is a portion of my GUI that will cause the compilation:
JavaCompiler jc = null;
StandardJavaFileManager sjfm = null;
File javaFile = null;
String[] options = null;
File outputDir = null;
URL[] urls = null;
URLClassLoader ucl = null;
Class clazz = null;
Method method = null;
Object object = null;
try
{
jc = ToolProvider.getSystemJavaCompiler();
sjfm = jc.getStandardFileManager(null, null, null);
File[] files = new File[1];
//files[0] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/myArray.java");
//files[1] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/Tool.java");
files[0] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/userDefined.java");
// getJavaFileObjects’ param is a vararg
Iterable fileObjects = sjfm.getJavaFileObjects(files);
jc.getTask(null, sjfm, null, null, null, fileObjects).call();
// Add more compilation tasks
sjfm.close();
options = new String[]{"-d", "C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project"};
jc.getTask(null, sjfm, null, Arrays.asList(options), null, fileObjects).call();
outputDir = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project");
urls = new URL[]{outputDir.toURL()};
ucl = new URLClassLoader(urls);
clazz = ucl.loadClass("userDefined");
method = clazz.getMethod("user", null);
object = clazz.newInstance();
Object ob = method.invoke(object, null);
}
This is an example of a user-defined algo(userDefined.java):
import java.awt.*;
import javax.swing.*;
public class userDefined
{
public void user()
{
int [] numArr = {1,3,1,-1,5,-5,0,7,12,-36};
myArray myArray = new myArray(numArr);
JFrame frame = new JFrame("Rectangles");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(360, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.add(myArray);
for (int i=myArray.length(); i>1; i--)
{
for (int j=0; j<i-1; j++)
{
if (myArray.get(j) > myArray.get(j+1))
{
myArray.swap(j, j+1);
}
}
}
}
}
The problem I am getting is that if I try to use reflection like above; I only get a white window which does not show the animation) but just displays the result at the very end.
However if I use this instead of reflection(and change the method void user() to static void main(string args) in userDefined.java):
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if(compiler.run(null, null, null, "userDefined.java") != 0) {
System.err.println("Could not compile.");
System.exit(0);
}
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("java "+"userDefined");
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
it woks provided that after first compilation I place the myArray class in the same folder as the userDefined.java. In this case I can see the animation take place correctly.
How do I use reflection to invoke the main method instead of using an instance of the class.
Please I really need some help with this. Thanks!
You a violating / missusing the first rule of swing: acces swing components only in the EDT (Event Dispatch Thread).
When you start your program using the main method, you are violating that rule. This happens to work, but might have all kinds of weird effects. This is not a theoretic warning, it happend to me and it is not nice.
When you run it using reflection from your code, you are most likely in the EDT, so your algorithm runs completely before the GUI gets updated again (which also happens on the EDT). Thats why you see only the final result of the algorithm.
The correct way to do this would be:
Run the algorithm in a seperate thread and make sure all changes to your myArray Component happen in the EDT, using SwingUtilities.invokeAndWait or SwingUtilities.invokeLater