I am able to easily print the contents of a JTable mainly through using the statement below. However, this does not work for printing the contents of a textarea component. Is there a simple way of printing the contents of a textarea component? I've seen some pretty confusing examples on the web that use multiple classes. But I'm trying to find a simpler way of doing this.
I ADDED THE SECOND AREA OF CODE ABOUT 24 HOURS AFTER THE ORIGINAL POST. NOTE THAT IT SEEMS TO BE PROMISING BUT PRODUCES THE ERROR "ADD ARGUMENT TO MATCH PRINT(GRAPHICS)". HOW CAN THAT CODE BE FIXED?
table.print(JTable.PrintMode.NORMAL, header, footer);
JButton btnNewButton_7 = new JButton("Print");
btnNewButton_7.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
try{
boolean complete = textArea_2.print();
//The above line reads the error "Add argument to match print(Graphics)"
if(complete){
JOptionPane.showMessageDialog(null, "Printjob Finished", "Report",
JOptionPane.INFORMATION_MESSAGE);
}else{
JOptionPane.showMessageDialog(null, "Printing", "Printer", JOptionPane.ERROR_MESSAGE);
}
}catch(PrinterException e){JOptionPane.showMessageDialog(null, e);
}
}
});
Google and the JavaDocs are your friend
JTextArea#print
A convenience print method that displays a print dialog, and then
prints this JTextComponent in interactive mode with no header or
footer text. Note: this method blocks until printing is done. Note: In
headless mode, no dialogs will be shown.
This method calls the full featured print method to perform
printing.
Returns: true, unless printing is canceled by the user
JTextArea#print(MessageFormat headerFormat, MessageFormat footerFormat)
A convenience print method that displays a print dialog, and then
prints this JTextComponent in interactive mode with the specified
header and footer text. Note: this method blocks until printing is
done. Note: In headless mode, no dialogs will be shown.
This method calls the full featured print method to perform printing.
Parameters: headerFormat - the text, in MessageFormat, to be used as
the header, or null for no header footerFormat - the text, in
MessageFormat, to be used as the footer, or null for no footer
Returns: true, unless printing is canceled by the user
JTextArea#print(MessageFormat headerFormat, MessageFormat footerFormat, boolean showPrintDialog, PrintService service, PrintRequestAttributeSet attributes, boolean interactive) throws PrinterException
...You can look that one yourself, it's to long to post...
JTextArea#getPrintable(MessageFormat headerFormat, MessageFormat footerFormat)
Returns a Printable to use for printing the content of this
JTextComponent. The returned Printable prints the document as it looks
on the screen except being reformatted to fit the paper. The returned
Printable can be wrapped inside another Printable in order to create
complex reports and documents. The returned Printable shares the
document with this JTextComponent. It is the responsibility of the
developer to ensure that the document is not mutated while this
Printable is used. Printing behavior is undefined when the document is
mutated during printing.
Page header and footer text can be added to the output by providing
MessageFormat arguments. The printing code requests Strings from the
formats, providing a single item which may be included in the
formatted string: an Integer representing the current page number.
The returned Printable when printed, formats the document content
appropriately for the page size. For correct line wrapping the
imageable width of all pages must be the same. See
PageFormat.getImageableWidth().
This method is thread-safe, although most Swing methods are not.
Please see How to Use Threads for more information.
The returned Printable can be printed on any thread.
This implementation returned Printable performs all painting on the
Event Dispatch Thread, regardless of what thread it is used on.
Parameters: headerFormat - the text, in MessageFormat, to be used as
the header, or null for no header footerFormat - the text, in
MessageFormat, to be used as the footer, or null for no footer
Returns: a Printable for use in printing content of this
JTextComponent
Works just fine for me...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPrint {
public static void main(String[] args) {
new TestPrint();
}
public TestPrint() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JTextArea ta = new JTextArea(20, 100);
try (FileReader reader = new FileReader(new File("C:/Script.txt"))) {
ta.read(reader, ta);
} catch (IOException ex) {
ex.printStackTrace();
}
JButton print = new JButton("Print");
print.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MessageFormat header = new MessageFormat("Star Wars IV A new Hope");
MessageFormat footer = new MessageFormat("Page {0}");
try {
ta.print(header, footer);
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(ta));
frame.add(print, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Related
I am currently writing a program that enables the user to drag-and-drop some data from a browser into a java swing application. This works as intended for the mime type "text/plain", but when using a custom mime type in the javascript, the java application does not receive the data anymore.
The javascript side is done as described in this answer:
for (const el of document.querySelectorAll('[draggable="true"]')) {
el.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', e.currentTarget.dataset.content);
});
}
The java application looks like this MRE. The MRE just prints out any received drops.
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JTextArea area = new JTextArea();
area.setDropTarget(new DropTarget() {
#Override
public synchronized void drop(DropTargetDropEvent dtde) {
dtde.acceptDrop(TransferHandler.COPY_OR_MOVE);
try {
// For testing
System.out.println(Arrays.toString(dtde.getTransferable().getTransferDataFlavors()));
// Business logic, e.g.
System.out.println(dtde.getTransferable().getTransferData(DataFlavor.stringFlavor));
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
});
frame.add(area);
// Only for MRE, never set size like this for actual programs
area.setPreferredSize(new Dimension(200, 100));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
This works as it should with the jsfiddle from the linked answer. However, the data that should be transferred is not just a plain text but actually a json string. Also, the string should only be dropped in my own application and not into any text editor. Therefore I changed the mime type in the javascript to 'text/json'. On the java side, I replaced
System.out.println(dtde.getTransferable().getTransferData(DataFlavor.stringFlavor));
with
System.out.println(dtde.getTransferable().getTransferData(new DataFlavor("text/json;class=java.lang.String")));
Which leads to an UnsupportedFlavorException in that line:
java.awt.datatransfer.UnsupportedFlavorException: text/json
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:256)
at java.desktop/sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
at java.desktop/java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:386)
at Main$1.drop(Main.java:23)
Additionally, the TransferDataFlavors array is empty, suggesting no DataFlavor is available. I considered to overwrite the FlavorMap to ensure the native mime type is mapped to the correct flavor, but debugging the getFlavorsForFormats method in DataTransferer revealed only the following natives are requested (using chrome):
"DragContext", "chromium/x-renderer-taint", "Chromium Web Custom MIME Data Format", and "DragImageBits", so my custom mime type is not even available as native type.
How do I transfer the data correctly from the browser to the java application? Do I need to register my flavor somewhere? Or is this not possible and I need to stick to text/plain?
It has recently come to my attention that Java text components use line feed characters (LF, \n, 0x0A) to represent and interpret line breaks internally. This came as quite a surprise to me and puts my assumption, that using System.getProperty('line.separator') everywhere is a good practice, under a question mark.
It would appear that whenever you are dealing with a text component you should be very careful when using the mentioned property, since if you use JTextComponent.setText(String) you might end up with a component that contains invisible newlines (CRs for example). This might not seem that important, unless the content of the text component can be saved to a file. If you save and open the text to a file using the methods that are provided by all text components, your hidden newlines suddenly materialize in the component upon the file being re-opened. The reason for that seems to be that JTextComponent.read(...) method does the normalization.
So why doesn't JTextComponent.setText(String) normalize line endings? Or any other method that allows text to be modified within a text component for that matter? Is using System.getProperty('line.separator') a good practice when dealing with text components? Is it a good practice at all?
Some code to put this question into perspective:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextAreaTest extends JFrame {
private JTextArea jtaInput;
private JScrollPane jscpInput;
private JButton jbSaveAndReopen;
public TextAreaTest() {
super();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Text Area Test");
GridBagLayout layout = new GridBagLayout();
setLayout(layout);
jtaInput = new JTextArea();
jtaInput.setText("Some text followed by a windows newline\r\n"
+ "and some more text.");
jscpInput = new JScrollPane(jtaInput);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0; constraints.gridy = 0;
constraints.gridwidth = 2;
constraints.weightx = 1.0; constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
add(jscpInput, constraints);
jbSaveAndReopen = new JButton(new SaveAndReopenAction());
constraints = new GridBagConstraints();
constraints.gridx = 1; constraints.gridy = 1;
constraints.anchor = GridBagConstraints.EAST;
constraints.insets = new Insets(5, 0, 2, 2);
add(jbSaveAndReopen, constraints);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TextAreaTest tat = new TextAreaTest();
tat.setVisible(true);
}
});
}
private class SaveAndReopenAction extends AbstractAction {
private File file = new File("text-area-test.txt");
public SaveAndReopenAction() {
super("Save and Re-open");
}
private void saveToFile()
throws UnsupportedEncodingException, FileNotFoundException,
IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(
new FileOutputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.write(writer);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {
}
}
}
}
private void openFile()
throws UnsupportedEncodingException, IOException {
Reader reader = null;
try {
reader = new InputStreamReader(
new FileInputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.read(reader, file);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
}
}
}
}
public void actionPerformed(ActionEvent e) {
Throwable exc = null;
try {
saveToFile();
openFile();
} catch (UnsupportedEncodingException ex) {
exc = ex;
} catch (FileNotFoundException ex) {
exc = ex;
} catch (IOException ex) {
exc = ex;
}
if (exc != null) {
JOptionPane.showConfirmDialog(
TextAreaTest.this, exc.getMessage(), "An error occured",
JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
}
}
}
}
An example of what this program saves on my windows machine after adding a new line of text (why the single CR? o_O):
Edit01
I ran/debugged this from within Netbeans IDE, which uses JDK1.7u15 64bit (C:\Program Files\Java\jdk1.7.0_15) on Windows 7.
First of all, the real answer is that this is how the designers thought the design should work. You'd really need to ask them to get the real reason(s).
Having said that:
So why doesn't JTextComponent.setText(String) normalize line endings?
I think that the most likely reasons are:
It would be unexpected behaviour. Most programmers would expect1 a 'get' on a text field to return the same string value that was 'set' ... or that the user entered.
If text fields did normalize, then the programmer would have great difficulty preserving the original text's line endings in vases where this was desirable.
The designers might have wanted to change their minds at some point (c.f. the reported behaviour of the read and write methods) bur were unable to for reasons of compatibility.
Anyway, if you need normalization, there's nothing stopping your code from doing this on the value retrieved by the setter.
Or any other method that allows text to be modified within a text component for that matter?
It is reported (see comments) that read and/or write do normalization.
Is using System.getProperty('line.separator') a good practice when dealing with text components? Is it a good practice at all?
It depends on the context. If you know you are reading and writing files to be processed on "this" platform, its probably a good idea. If the file is intended to be read on a different platform (with a different line separators) then normalizing to match the current machine's convention is maybe a bad idea.
1 - The fact that other methods like read and write that may behave differently doesn't affect this. They are not "getters" and "setters". I'm talking about how people expect "getters" and "setters" to behave ... not anything else. Besides, people shouldn't expect everything to behave the same way, unless it is specified that they do. But obviously, the part of the problem here is that the spec ... the javadocs ... is silent on these issues.
The other possibility is that the normalization behaviour that #predi reports is actually happening in the Reader / Writer objects ...
Using the system line separator is questionable. I would only use it to write text files in platform specific format.
When reading, I always simply throw away any '\r', (CR) effectively converting down Windows/Mac/Unix to Unix-style linefeeds. Internally I would never use anything other than plain '\n' (LF) to indicate linefeeds - its a waste of memory and makes processing text only more painful.
i have to do this: i have one JTextField and button. And when i write to that TextField output must show result in JLabel.
Asks the user to provide the name of a class.
Uses Class.forName() to get an access to Java Reflection API.
Creates a new instance (i.e. object) of the class using the default constructor.
Finds and displays all fields of the class in the form including inherited fields:
field_type field_name: (field_value(JTextField))(Set(Button))
field_value must be a textbox, so that the user can change the value by pressing ‘Set’ button. The new value must be updated to the object. If the field contains values of complex types (objects, collections etc.) then the textbox and ‘Set’ button should not be created.
Finds and displays all methods of the class including inherited methods:
return_type method_name (param_type1 (param_value1(JTextField)), param_type2(param_value2(JTextField)) , ..) (Invoke(Button))
If a method has parameters of complex types (objects, collections etc.) then only parameters’ types are displayed, param_values’ textboxes and ‘invoke’ button are skipped.
When the user presses “invoke” button, the application must invoke the method. Make sure that if the method alters the fields’ values these changes are displayed.
and my code here:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.StringBuffer;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ReflectionTest {
private String class_name = "java.lang.StringBuffer";
public ReflectionTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
JLabel jl1 = null, jl2, jl3, jl4;
JFrame jf = new JFrame("New");
JPanel jp = new JPanel();
JTextField jtf = new JTextField(20);
JButton jb = new JButton("Press");
jtf.setVisible(true);
jp.add(jb);
jp.add(jtf);
jf.add(jp);
jf.setVisible(true);
jf.setSize(400, 550);
jf.setResizable(false);
String text = jtf.getText().toString();
Class cs = Class.forName(text);
jb.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// THIS CODE IS EXECUTED WHEN RETURN IS TYPED
}
}
);
for(Constructor c: cs.getConstructors()){
for(Class p: c.getParameterTypes())
System.out.print(p.getName()+" ");
System.out.println();
}
Constructor c = cs.getConstructor(new Class[]{String.class});
Object list = c.newInstance("AA");
Field pub_fields[] = cs.getFields();
Field all_fields[] = cs.getDeclaredFields();
System.out.println("Public fields:");
for(Field f:pub_fields){
//Showing public fields
System.out.println();
jl1 = new JLabel(f.getType().getName() + " " + f.getName());
jp.add(jl1);
jl1.setVisible(true);
}
System.out.println("All declared fields:");
for(Field f:all_fields){
//Showing all declared fields
jl2 = new JLabel(f.getType().getName() + " "+f.getName()+" ");
jp.add(jl2);
jl2.setVisible(true);
f.setAccessible(true);
Object val = f.get(list);
if (val != null){
//System.out.println(val.toString());
jl3 = new JLabel(val.toString());
jp.add(jl3);
jl3.setVisible(true);
System.out.println();
}
else{
System.out.println("NULL");
//f.get(list1);
}
}
}
/**
* #param args
* #throws ClassNotFoundException
*/
public static void main(String[] args) {
try{
// TODO Auto-generated method stub
new ReflectionTest();
}
catch (Exception e){
e.printStackTrace();
}
}
}
and i have error. Eclipse show it in this line:
Class cs = Class.forName(text);
If you test the text String before the exception occurs, for instance by printing it out:
System.out.printf("text = \"%s\"%n", text);
Class cs = Class.forName(text);
Which returns:
text = ""
java.lang.ClassNotFoundException:
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at pkg.ReflectionTest.<init>(ReflectionTest.java:42)
at pkg.ReflectionTest.main(ReflectionTest.java:102)
You'll see that the text String is empty, "". This is because you have no text when you call the Class cs = Class.forName(text); since it's being called before the GUI has been rendered, much less give the user time to enter text. Only call this in code that is called due to a user-generated event of some sort such as an ActionListener's actionPerformed method.
In other words, add the critical code to where in your own commment you state you should add the code:
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// THIS CODE IS EXECUTED WHEN RETURN IS TYPED // *********!!!!
}
});
And I second the comment that you should show any and all information about the exception. Please don't make us guess what the problem is.
Edit
Also you will have a problem with using local variables, including the JLabels and JTextField, inside of the anonymous inner listener class. The easiest and best way to solve this is to make the variables that need to be accessed in this listener private class fields. So remove their declarations from the constructor and instead move them to the class itself.
Is it really an error or a "yellow" line? Class is a parametized type and if you do not use generics then eclipse will show a warning.
To eliminate such a warning, simply do a
Class<?> cs = Class.forName(text);
The wildcard is ok because you really don't know which "type" of Class you're going to load.
I apologize for the long question.
I was browsing a forum the other day and I saw a few pieces of text that were linking to youtube and other sites.
I had to always highlight and then copy and paste or right click "go to" in google chrome browser.
Since I've been playing with Java a little bit, I thought about making my own little program that will give a link to text that has an address . For example if I said "hey, check this video out I saw the other day 'www.youtube.com' " I'd want the youtube part to be clickable.
Could anybody tell me if such a thing is possible and if it is, what libraries would I have to use for this and lastly, how can I find a list of all imports and libraries in java?
Thanks.
Use HTML in JEditorPane and add HyperLinkListener to detect click on URLs.
Than use Desktop API to open default browser with the URL.
Something like:
import java.awt.Desktop;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class Test {
public static void main(String[] argv) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JEditorPane jep = new JEditorPane();
jep.setContentType("text/html");//set content as html
jep.setText("Welcome to <a href='http://stackoverflow.com/'>StackOverflow</a>.");
jep.setEditable(false);//so its not editable
jep.setOpaque(false);//so we dont see whit background
jep.addHyperlinkListener(new HyperlinkListener() {
#Override
public void hyperlinkUpdate(HyperlinkEvent hle) {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
System.out.println(hle.getURL());
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(hle.getURL().toURI());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
JFrame f = new JFrame("HyperlinkListener");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(jep);
f.pack();
f.setVisible(true);
}
});
}
}
Using this question, I created the class below, which handles drag and drop of files to a JTextField. The point of the application is to be able to drag a file into the text field, and have the text field's text set to the file's path (you can see the goal in the code pretty clearly).
My problem is the below code does not compile. The compilation error states Cannot refer to non-final variable myPanel inside an inner class defined in a different method. I haven't worked much with inner classes, so can seomeone show me how to resolve the error and get the code to behave as designed?
Code:
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.util.List;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JTextArea myPanel = new JTextArea();
myPanel.setDropTarget(new DropTarget() {
public synchronized void drop(DropTargetDropEvent evt) {
try {
evt.acceptDrop(DnDConstants.ACTION_COPY);
List<File> droppedFiles = (List<File>) evt
.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
for (File file : droppedFiles) {
/*
* NOTE:
* When I change this to a println,
* it prints the correct path
*/
myPanel.setText(file.getAbsolutePath());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
JFrame frame = new JFrame();
frame.add(myPanel);
frame.setVisible(true);
}
}
As the error message says, myPanel needs to be defined as final.
final JTextArea myPanel = new JTextArea();
This way the inner class can be given one reference pointer to the variable instance without concern that the variable might be changed to point to something else later during execution.
Another option is to declare the variable static.
static JTextArea myPanel = new JTextArea();