How I can get html-page code to String using SWT Broser?
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(100, 100);
Browser browser = new Browser(shell, SWT.NONE);
browser.setBounds(5, 75, 100, 100);
shell.open();
browser.setUrl("https://google.com");
String html = browser.getText(); //NOTHING!
while (!shell.isDisposed()) {
if (!display.readAndDispatch() && html == null) {
display.sleep();
}
}
display.dispose();
Syste.out.println(html); ////NOTHING!
So, how I can take html? And best way, when after html-code getting the display window will close?
The method you are searching for is: Browser#getText(). Here is the important part of the javadoc:
Returns a string with HTML that represents the content of the current page.
So this would do the job:
String html = browser.getText();
System.out.println(html);
For your second question: You can close the shell by calling Shell#close(). Here is the Javadoc:
Requests that the window manager close the receiver in the same way it would be closed when the user clicks on the "close box" or performs some other platform specific key or mouse combination that indicates the window should be removed.
Related
I am facing the following problem for which i haven't found any solution yet. I am implementing a platform for a medical laboratory. They want for every incident to write the report to the system and then generate and print it from the system. I am using itext 7 to accomplish this. However i am facing the following problem.
They have a very strange template. On the first page in the beginning they want to print a specific table, while in the beginning of every other page they want to print something else. So i need to know when pages change in order to print in the beginning of the page the corresponding table.
After reading various sources i ended up creating the first page normally and then adding a header event handler that checks the page number and gets executed always except page 1.
public class VariableHeaderEventHandler implements IEventHandler {
#Override
public void handleEvent(Event event) {
System.out.println("THIS IS ME: HEADER EVENT HANDLER STARTED.....");
PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = documentEvent.getDocument();
PdfPage page = documentEvent.getPage();
Rectangle pageSize = page.getPageSize();
int pageNumber = pdfDoc.getPageNumber(page);
if (pageNumber == 1) return; //Do nothing in the first page...
System.out.println("Page size: " + pageSize.getHeight());
Rectangle rectangle = new Rectangle(pageSize.getLeft() + 30, pageSize.getHeight()-234, pageSize.getWidth() - 60, 200);
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
pdfCanvas.rectangle(rectangle);
pdfCanvas.setFontAndSize(FontsAndStyles.getRegularFont(), 10);
Canvas canvas = new Canvas(pdfCanvas, pdfDoc, rectangle);
Div header = new Div();
Paragraph paragraph = new Paragraph();
Text text = new Text("Διαγνωστικό Εργαστήριο Ιστοπαθολογίας και Μοριακής Παθολογοανατομικής").addStyle(FontsAndStyles.getBoldStyle());
paragraph.add(text);
paragraph.add(new Text("\n"));
text = new Text("Μοριακή Διάγνωση σε Συνεργασία με").addStyle(FontsAndStyles.getBoldStyle());
paragraph.add(text);
paragraph.add(new Text("\n"));
text = new Text("Γκούρβας Βίκτωρας, M.D., Ph.D.").addStyle(FontsAndStyles.getBoldStyle());
paragraph.add(text);
paragraph.add(new Text("\n"));
text = new Text("Τσιμισκή 33, Τ.Κ. 54624, ΘΕΣΣΑΛΟΝΙΚΗ").addStyle(FontsAndStyles.getNormalStyle());
paragraph.add(text);
paragraph.add(new Text("\n"));
text = new Text("Τήλ/Φάξ: 2311292924 Κιν.: 6932104909 e-mail: vgourvas#gmail.com").addStyle(FontsAndStyles.getNormalStyle());
paragraph.add(text);
header.add(paragraph);
// =============Horizontal Line BOLD============
SolidLine solidLine = new SolidLine((float) 1.5);
header.add(new LineSeparator(solidLine));
// ========Horizontal Line BOLD End==========
text = new Text("ΠΑΘΟΛΟΓΟΑΝΑΤΟΜΙΚΗ ΕΞΕΤΑΣΗ").addStyle(FontsAndStyles.getBoldStyle());
paragraph = new Paragraph().add(text);
header.add(paragraph);
header.setTextAlignment(TextAlignment.CENTER);
canvas.add(header);
canvas.close();
}
However the problem i am facing now is that header overlaps content and i can't figure out how to set different margins per page. For example form page 2 and beyond i would like different topMargin.
Has anyone faced these problems before and have found a working solution? Am I implementing correct? Is there a better way of accomplishing the same result?
Thanks in advance,
Toutoudakis Michail
You should create your own custom document renderer and decrease the area which would be used to place content for each page except for the first one.
Please look at the snippet below and updateCurrentArea method in particular.
class CustomDocumentRenderer extends DocumentRenderer {
public CustomDocumentRenderer(Document document) {
super(document);
}
#Override
public IRenderer getNextRenderer() {
return new CustomDocumentRenderer(this.document);
}
#Override
protected LayoutArea updateCurrentArea(LayoutResult overflowResult) {
LayoutArea area = super.updateCurrentArea(overflowResult);
if (currentPageNumber > 1) {
area.setBBox(area.getBBox().decreaseHeight(200));
}
return area;
}
}
Then just set the renderer on your document:
Document doc = new Document(pdfDoc);
doc.setRenderer(new CustomDocumentRenderer(doc));
The resultant pdf which I get for your document looks as follows:
There is another solution however. Once you've added at least one element to your document, you can change the default document's margins. The change will be applied on all pages created afterwards (and in your case these are pages 2, 3, ...)
doc.add(new Paragraph("At least one element should be added. Otherwise the first page wouldn't be created and changing of the default margins would affect it."));
doc.setMargins(200, 36, 36, 36);
// now you can be sure that all the next pages would have new margins
I have a problem with the integration of an image in a text/html JTextPane.
The JTextPane is initialized with the following text:
<html>
<head>
<style type="text/css">
</style>
</head>
<body>
</body>
</html>
I insert text with:
kit.insertHTML(doc, doc.getLength(), "<b>" + string + "</b><br>" , 0, 0, HTML.Tag.B);
All the text inserted this way is displayed correctly, but when I tried inserting a base64-encoded image with:
kit.insertHTML(doc,doc.getLength(), "<img src=\"data:image/jpeg;base64," + base64Code + "\"/>", 0, 0, HTML.Tag.IMG);
I only got a placeholder image. When trying with a normal source path, it worked. However, getting the base64 code online and using that got me a placeholder image too, while the exact same code worked on w3school.com's HTML tryit editor.
When a JTextPane sees an <img> tag, it will check if the image exists in a cache, and if not, it will try to read the image from the url. The html library used by JTextPane does not support base64 encoded image data in the <img> tag, so we will need to do it in a different way.
It turns out that we can manually add images to the image cache. This can be utilized to pick some otherwise invalid url and assign it an image.
Let's add the image to the cache and show it in a JTextPane!
First you want to convert the image into a BufferedImage. This can be done using the ImageIO class.
byte[] imgBytes = decodeBase64(base64Code);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));
Note that here we need the raw image bytes, not the base64 encoding. If you are reading the image from a file, you can pass a File to the read function instead of the input stream.
Now that we have the image as a BufferedImage, we can write a function that adds it to the cache.
#SuppressWarnings({ "rawtypes", "unchecked" })
public static String saveImageToCache(JTextPane pane, BufferedImage img, String name) throws MalformedURLException {
Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
if (cache == null) {
// No cache exists, so create a new one.
cache = new Hashtable();
pane.getDocument().putProperty("imageCache", cache);
}
String url = "http:\\buffered/" + name;
cache.put(new URL(url), img);
return url;
}
Note that I suppress some warnings about type parameters on Dictionary and Hashtable. Normally this should be avoided, but in this case we are dealing with Swing nonsense in a way where it's ok to suppress the warnings.
This method essentially picks some invalid url and stores the image at that url.
Notice the name argument. This will be part of the url, and if you try to store an image to the cache with the same name as a previous image, this will replace that previous image. Avoid using crazy characters in this name, as new Url(url) may throw a MalformedURLException if it is not a valid url.
We can now use it with JTextPane.
BufferedImage img = ...;
JTextPane pane = new JTextPane();
pane.setContentType("text/html");
String url = saveImageToCache(pane, img, "image1");
pane.setText("<html><body><img src=\"" + url + "\"></body></html>");
JFrame frame = new JFrame("image test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.setSize(img.getWidth(), img.getHeight());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Note that you must call setContentType before adding the image to the cache, as the method clears the cache. Furthermore it is important that an image is added to the cache before setText is called, to ensure that images are added before swing needs it.
If the image in the cache is changed by using saveImageToCache with a previously known name, you will need to update the JTextPane in some way, such as calling setText.
If you have a lot of images, you might want to remove them from the cache when they are no longer needed, in order to avoid excessive memory usage. One way to do this would be to define a function as the one below, which removes the image from the cache.
#SuppressWarnings({ "rawtypes" })
public static void removeImageFromCache(JTextPane pane, String name) throws MalformedURLException {
Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
if (cache == null) {
// There is no cache, so the image is not in the cache.
return;
}
String url = "http:\\buffered/" + name;
cache.remove(new URL(url));
}
You can also clear the cache by calling setContentType or by replacing the JTextPane with a new object. This works as the cache is stored in the JTextPane.
I've been making a chat program for a few days now and I'm completely stumped on how to create a nice looking clickable text without the use of HTML. I tried to use HTML, but had extremely weird results (see below). So I am now just using
basic text rather then text/html.
My first attempt to add clickable text was to use JTextPane's ability to insert Components along with the text. It inserted and worked perfectly, but it was vertically offset and looked very bad. I tried to mess with setAlignmentY, but had no luck aligning the components with the text.
JLabel l = new JLabel(test);
l.setFont(this.getFont());
l.setCursor(new Cursor(Cursor.HAND_CURSOR));
l.setBackground(Color.RED); //Just so i could see it better for testing
l.addMouseListener(new FakeMouseListener());
this.insertComponent(l);
I'm using JTextPane and inserting text using doc.insertString. I skip lines using the systems line separator, so a single line can contain multiple doc.insertStrings (Which is were I ran into trouble when attempting to use text/html).
This inserts HTML without any alignment problems. I think ("think" because I don't have enough of your code to know) that you had issues because of Document.insertString while I use HTMLEditorKit.insertHTML.
public class Example extends JFrame {
Example() {
JEditorPane pane = new JEditorPane();
pane.setEditable(false);
pane.setContentType("text/html");
HTMLDocument doc = (HTMLDocument) pane.getDocument();
HTMLEditorKit editorKit = (HTMLEditorKit) pane.getEditorKit();
try {
editorKit.insertHTML(doc, doc.getLength(), "clickable1", 0, 0, null);
editorKit.insertHTML(doc, doc.getLength(), "clickable2", 0, 0, null);
editorKit.insertHTML(doc, doc.getLength(), "clickable3", 0, 0, null);
} catch (BadLocationException | IOException e) {
e.printStackTrace();
}
pane.addHyperlinkListener(new HyperlinkListener() {
#Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
System.out.println(e.getSourceElement());
if (e.getURL() != null)
System.out.println(e.getURL());
else
System.out.println(e.getDescription());
System.out.println("-----");
}
}
});
add(pane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
}
Notes:
setEditable(false) must be called for this to work properly (probably there is some convoluted way to make it work otherwise).
The HyperlinkListener is just to prove that the links work, along with some demonstration of how to get the link string (getURL will only work if the link is a valid URL).
You don't need to set the cursor, with or without the HyperlinkListener.
Turns out i put setAlignmentY(0.85f); for the JTextPane instead of the JLable.
If you have an offset component you're attempting to insert into JTextPane, mess around with it's Y alignment. 0.85f works for me.
I am using RowLayout for thumbnails of images. All the thumbnails are being displayed in one row only. How can I make them to display efficiently in multiple rows upon resizing?
You can easily find it in the documentation of RowLayout.
What you're looking for is RowLayout#wrap:
wrap specifies whether a control will be wrapped to the next row if there is insufficient space on the current row. The default value is true.
Since the default is true, it should already wrap...
public static void main(String[] args)
{
final Display display = new Display();
final Shell shell = new Shell();
shell.setText("StackOverflow");
RowLayout layout = new RowLayout();
layout.wrap = true;
shell.setLayout(layout);
Image image = new Image(display, "star.png");
for(int i = 0; i < 10; i++)
new Label(shell, SWT.NONE).setImage(image);
shell.pack();
shell.setSize(200, 100);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
image.dispose();
}
Looks like this before resizing:
And after resizing:
Am developing an eclipse plugin which has few wizard pages. I need the wizard window size to be constant, with "BOTH MAXIMISE and MINIMISE disabled", "window RESIZE disabled".
The point is I am not using SHELL. I am using COMPOSITE instead, which doesn't have any style bits.
How can I do that? I am just providing a part of my entire code:
public void createControl(Composite parent)
{
// TODO Auto-generated method stub
composite = new Composite(parent, SWT.NONE );
composite.setLayout(new GridLayout());
Composite selectAdapterComposite = new Composite(composite, SWT.NONE);
FormLayout reportOptionsCompositeLayout = new FormLayout();
reportOptionsCompositeLayout.marginHeight = 1;
reportOptionsCompositeLayout.marginWidth = 1;
selectAdapterComposite.setLayout(reportOptionsCompositeLayout);
buttonInterfaceSelection = new Button(selectAdapterComposite,SWT.RADIO);
//SWT.CHECK);
buttonInterfaceSelection.setText("Generate adapter using interface !");
buttonInterfaceSelection.setSelection(true);
buttonInterfaceSelection.addListener(SWT.Selection, this);
FormData exportInToExcelButtonData = new FormData();
exportInToExcelButtonData.left = new FormAttachment(null, 5);
buttonInterfaceSelection.setLayoutData(exportInToExcelButtonData);
// One Text Box
Label searchBoxLabel = new Label(selectAdapterComposite, SWT.None);
searchBoxLabel.setText("Search to select [Type to get the results below]");
FormData destinationLabelData = new FormData();
destinationLabelData.top = new FormAttachment(buttonInterfaceSelection, 10);
destinationLabelData.left = new FormAttachment(null, 5);
searchBoxLabel.setLayoutData(destinationLabelData);
searchTextBox = new Text(selectAdapterComposite, SWT.BORDER);
searchTextBox.setSize(20, 2);
FormData searchTextBoxData = new FormData();
searchTextBoxData.top = new FormAttachment(searchBoxLabel, 8);
searchTextBoxData.left = new FormAttachment(null, 5);
// destinationFolderPathData.left = new
// FormAttachment(destinationLabel,15);
searchTextBoxData.width = 400;
searchTextBox.addListener(SWT.Modify, this);
searchTextBox.setEnabled(true);
searchTextBox.setLayoutData(searchTextBoxData);
.
.
.
.
.
setControl(composite);
}
Please help me out.
Your code snippet is irrelevant to your question. The key word is wizard. When you create that wizard, it requires a Shell, so you can set its style bits there.
A WizardDialog's constructor:
public WizardDialog(Shell parentShell, IWizard newWizard)
Example of shell style bits:
parentShell.setShellStyle(parentShell.getShellStyle() | (~SWT.RESIZE));
Thanks for your reply... am a newbie to swt and your answer gave me an important info which I dint know before. Now then, I just took some time to go through widgets documentation and found something.
Composite : Instances of this class are controls which are capable of containing other controls.
Shell : Instances of this class represent the "windows" which the desktop or "window manager" is managing.
I realised that my understanding of SHELL and COMPOSITE was wrong.
Conclusion: So I have to depend upon SHELL to give window resizing controls and using a COMPOSITE does not give me any resizing option...
Correct me if am wrong please.. hope this will be useful to other noobs too...
Thanks.
P.S.: now i understoood, my code segment is irrelevant to my question cos, I am working on someone else's code and trying to make some changes to it. instead of making changes in SHELL (which is created in some other class) i am doing it in COMPOSITE.