Before I start, similar question (of mine) exists, I'd like that one to be deleted since I didn't explain my point well there, but not this one. Thank you.
First of all, I have no code, this is only a concept that I can't figure out. But it's interesting (at least to me).
You all know how MSWord works. You write stuff. Then, when you fill a page it will create a new page and start writing on that page. If you paste some more text to the first page, everything will be pushed down. If you delete a large chunk of text on a page, it will suck up some of the text on the previous page. If you're dealing with e.g. pictures and you have one on top of a page, reducing it's size my cause it to get sucked up to the previous page, if there is enough room for the reduced version of the picture.
Now that you're thinking this way, I want to transfer that concept into Java Swing. Pages are JPanels, and pictures and chunks (or lines) of text are JPanels fitted onto the page JPanel.
I have come up (okay, I lied, I have some code, but it's a mess and it doesn't work anyway) with a method using a Filler, which doesn't work in all cases. If you want to know why, read between the two lines, otherwise just skip it.
So, the structure itself is easy to replicate, but maintaining it is a pain in the neck. You see, there are two main types of events that can occur:
a) height of the page content has increased
b) height of the page content has decreased
By using a Filler as the last component of a page, and having a componentAdapter (componentResized) attached to it, you can monitor those changes.
These changes can further be dividet into:
a) element is added/removed to/from page
b) height of the element has increased/decreased
Taking those events into consideration many things can happen. Skipping the simple cases, look at this example:
Page 1:
{element 1
blabla
blabla}
{element 2
blabla}
{element 3}
{element 4
blabla
blabla
blabla
blabla}
{free space
---
---
---}
/
Page 2:
{element 1
blabla
blabla
blabla
blabla}
{element 2
blabla
blabla
blabla
blabla}
{element 3}
{element 4
blabla
blabla
blabla}
/
Page 3:
{element 1}
{element 2}
{element 3}
{element 4}
{element 5}
{free space
---
---
---
---
---
---
---
---
---}
Each page has a height of 15 rows. Look now what happens if you reduce the height of the element 1 of the second page by one row. It will become 4 rows high, making it fit to the previous page, being sucked up. That will create 5(1 deleted row + 4 sucked up rows) rows worth of free space on the second page. That will suck up all the five elements on the third page and leave the third page blank (which should now be deleted).
The reason this wouldn't work is because upon deletion, a listener is triggered for the second page and it has to both push the top element up, and suck up the elements from the previous page. Since it's all done in a listener, I have to wait for it to execute in order to register visual change in my program. Since it has to change two thing on a page, it comes to somekind of listener chaos. Page height is reduced twice but is registered only once and in the end I can fully move only thr top part or the bottom part, or a single component on each side. This isn't really a good explenation, but if you understand how swing works, you should be able to connect the dots yourself.
As I mentioned before, I have written the code for that, but it's long and hard to follow, and I can post it here, if anyone shows the desire to see it. And I'm talking about SSCCE itself. It really can't be shortened into couple of 10s of rows of code.
What I would want is to skip writting an algorithm that would maintain the structure of the "document" and move all the elements around, since it's a really complicated thing to do, taking all the numerous cases.
What I want is an alternative and I'm asking you if you have any ideas. One thing that came to my mind is having a component similar to JPanel. It would have fixed height-parts that can be populated with other components, and between them fixed height-parts that are unpopulable(?) or "solid".
Way it would work would be that everytime you add something to populable(?) parts, they would be automatically rearanged. If something doesn't fit to the current populable part, it's just moved to the next one (similar to how verticall box layout works, adding one thing to a spot pushes all the others down), but skiping the solid part.
Since I would also have to be able to tell in which populable part a certain component is, I don't know if creating a such structure is possible in Java swing.
Well, any advice is welcome, external libaries included.
Just keep in mind that this whole document is document with pages that would be placed one after another in a JScrollPane's viewport, and that is the only limit to what it should look like.
Let the layout do the work: add() instances of JPanel, each having its own preferred size based on content, to a Box having a vertical layout. Put the Box in a JScrollPane, optionally implementing Scrolable. Use the scroll pane's row and column headers as needed; JTable is an example. You can remove() a panel from the Box, revalidate() and repaint() as required.
Addendum: The initial answer addressed only the view aspect of the problem. It may help to separate the model and view more rigorously, as the text components do; remove content from the model and signal the view to update itself accordingly. To achieve this, several common approaches to implementing the observer pattern are mentioned here.
Related
I´m building a simple word-editor in java. Currently, everything´s working fine. Now I want to create "Pages", like in word. The JTextPane representing a Page is supposed to check if it´s full and then create a new JTextpane under it. With a scrollbar I would be able to scroll between them. So far this wouldn't be problematic. However, all the pages should belong to a single document, and if I were to delete a line on let´s say page 2, every line on every other page will be moved up. (For example) Is there an easy way to do this, or will I have to create DocumentListeners for each JTextPane, changing everything on each change? Also, is there a way to extend selections over multiple pages?
Personally I havn't tried anything as of yet, since I want some tips before writing myself into a corner. I thought that I could make the pages uneditable, and instead use a caretListener to check the position the user clicks on, to edit an invisible infinite JTextPane containing the actual document, which would write it´s content to the visible pages.
Lots of unknowns, but maybe the following will give you something to think about.
all the pages should belong to a single document,
Agreed.
The JTextPane representing a Page is supposed to check if it´s full and then create a new JTextpane under it
Maybe add each text pane to a JScrollPane, but don't display the scrollbars or Border of the scroll pane.
if I were to delete a line on let´s say page 2, every line on every other page will be moved up
You would need to manually control the viewport of each scroll pane. The first page would position the viewport at offset 0. The next page would position the viewport at the offset that represents your page height.
Then any changes to the Document should be automatically reflected in all the text panes.
You would also probably need to use setAutoScrolls(false) to prevent the viewport from scrolling as you drag the mouse.
is there a way to extend selections over multiple pages?
Selection is a property of the text pane, not the Document.
Not sure what will happen as you try to drag the mouse from one text pane to another.
I'm guessing you might need some special logic. Maybe using mouseEntered/Exited events to trigger this type of processing.
I want to make an app, which will work as interface to several servers.
Why: In web iface provided by default (and we cannot change it) are few things we miss, few could be done better and for sure automation of some stuff would make the job easier.
What do I have: almost finished classes for communication with web interface of a server app.
GUI description:
For some kind of version 0.1: text field for username, radio button to select server and one "go" button. Then several (4-12) action buttons to operate on data, 2x text area with results, one label with some text data - I can manage this.
Then I need to view the data - grid MxN which will load the data, expected size: 7-15 columns, usually 10 rows or less, but rarely it can go over 1k (or even more, but I don't need all to be visible to the user in that case).
What I need: simply an advice.
I wish to start with a simple version (and I'm working on that already, but I'm stuck on too many things - 95% cos and absolutely new to GUI and 5% cos I'm new to java).
I've checked many tutorials, but they're all simple.
Real questions:
1) Verify. In MVC controller should handle all user actions - is it done by view's method which is something like button.addActionListener(param); anotherButton.addActionListener(paramp; ...?
1b) I've seen all implemented via one (nested) class, which was then checking source or smth - is that ok? There will be a lots of buttons etc.
2) How to implement the data grid, when I need to take actions on click / dbl click?
4) First row is header, the rest should be scroll able - should it be in the grid or outside (its own grid):
4a) How to make sure header's size (width) will be the same as in data (I don't want to set up straight size)
4b) I failed to create anything scrollable so far, but thats my bad I guess. How to ensure header will hold on a place and the rest can be scrolled?
5) How should be "data update" implemented? I've got JPanel from which I remove grid component and then I make new one and add data into it (simple, but perhapss there is another way). One of first enhancements will be sorting - use the same way I used for new content?
Thanks a lot for any answer, I know this is not very specific, but example I've found are too simple.
I plan a lots of enhancements, but thats in the future and I don't mind to rework GUI/Controller several times, at least, I'll practise, but I don't want to finish one part of the code and realise I've got to rewrite half of a controller and 1/4 of a view to make it possible.
Note: I plan to use this at work as my tool (if things go right, I could make 25-50% of my work by few clicks :-)
So I really mean this).
Note#2: I'm not new to programing, but I've never created GUI (which is why I've got GUI with menu bar with 2 items and 3 components and almost done web-iface connections).
Note#:3 dragable data header, tabbed data view - thats the plan for the future :-)
MVC in Swing is examined here; use nested classes for ease in prototyping and creating an mcve for future questions; as the need arises, nested classes can be promoted to separate classes having package-private access.
Use JTable; its flyweight implementation of renderers is good for organizing data by row and column.
Item three does not exist, but "always remember to translate cell coordinates" if you plan to drag columns or sort rows.
Use a JScrollPane to keep the table header stationary.
Update the TableModel, and the listening view will update itself in response.
If you are interested not only from the event/messaging architecture, but also on handling mouse/keyboard input, hovering detection, widgets, temporary menus, form re-sizing with widget alignment, dragging and dropping etc. I can advice you to look at this question and my answer with helpful resources.
I'm trying to figure out how to manage this layout in order for it to work. I have some ideas, but rehauling the whole thing is quite a bit of work to do.
This is how it looks like (in JTextAreas: "component name (parent (parent))"):
I have explaind the structure at the end of the question, if you feel the need to know.
This GUI is supposed to be very dynamic. You should be able to add and remove chapters, pages, questions and answers.
The GUI in the image above is made using nested JPanels (up to six layers on the thickest parts!) which most don't have thier size specified so they can adjust to the changes in the document. However, a lot of time is consumed (about a second per page) when drawing the document because the program keeps recalculating sizes of all the JPanels until they fit. So, unless I can specify the initial size (MigLayout) of a component, this method won't cut it for me.
Only alternative I have come up with is trying to put it all in one layer using MigLayout, which is doable, but I don't know how well does it work with the dynamic part of the whole thing. Removing and readding all the components (document could have over a hundred pages!) doesn't really seem as an option. Since most of the components are nested one onto another and are to move as one, this makes this solution even more difficult.
Also, all widths are fixed, while all of the heights within a page are flexible.
I really don't know how to go about this. Should I modify one of the existing ideas to work, or are there maybe libraries which are used in this type of situations? Is there another way?
Any ideas?
Also, as promised, this is the structure explained:
So, the thing important here is the JPanel inside a tab. It contains the DOCUMENT.
Document itself is made up out of random number of CHAPTERS. Each CHAPTER contains random number of PAGES. PAGES have MARINGS and CONTENT. On the image, pink and red parts are the MARGNIS, while everything within is CONTENT(green). CONTENT contains a single TITLE(blue). TITLE is made out ofa single JTextArea. After the TITLE, CONTENT can contain a random number of QUESTION(orange). QUESTION contains a JLabel(number) and JTextArea in one row, and below is a it's ANSWER PANEL. ANSWER PANEL contains up to five ANSWERS(yellow). Each ANSWER has a JCheckBox, JLabel (letter) and a JTextArea all in the same row.
Here I have some things marked out:
You seem to have the design you need. Break down each section and apply the required layout to achieve that section. Each section should be a self contained component.
So to my mind, start by modelling the data. You need a Document model, which contains a list of Chapters, which contains a list of Pages, which is made up of a list of Titles, which is is made up of a list of questions.
I would then provide a view for each level of the model. This will allow you to concentrate on the individual needs of each view, in isolation and reuse the code logic. It also means if you need to make changes, they will be more easy to make and reflected through the entire program
You seem to have the right idea for the Document/Chapters, being laid out within tabs.
I'd follow through. Each Page would be a self contained component, possibly using something like a GridLayout.
Each Content section would be its own component, consisting of the title editor and then the questions.
Here I'd use a BorderLyout, placing the title editor at the north position and the question panel in the center. You could then use something like a GridLayout for the questions pane.
As for the margins, you can achieve hese through the use EmptyBorders
In JavaFX 2's TableView, there is an API to add a RowFactory. That factory is used to create the TableRows; it is use for cases where the developer wants features (like a tooltip) to span the entire row.
Now, working with the feature, I noticed that the RowFactory is called not called once per visible row, but instead once more.
If you execute this piece of code, you'll notice that the UI shows 16 rows in the UI, but the counter on the console counts a 17th line.
What's curious is that the extraneous line appears to be at the beginning and filled with data, not maybe an invisible extra line at the end.
I'd think it to be the header, but in the JavaFX code, it does not look like that's the case.
Can you explain this observation?
We have a requirement where we already have pre printed stationery and want user to put data in a HTML form and be able to print data on that form. Alignment/text size etc are very important since the pre-printed stationery already has boxes for each character. What could be a good way to achieve this in java? I have thinking of using jasper reports. Any other options? May be overlay image with text or something?
Also we might need to capability to print on plain paper in which case the boxes needs to be printed by our application and the form should match after the printed with the already printed blank stationery containing data.
Do we have some open source framework to do such stuff?
Jaspersoft reports -- http://sourceforge.net/projects/jasperreports/
You will then create XML templates, then you will be able to produce a report in PDF, HTML, CSV, XLS, TXT, RTF, and more. It has all the necessary options to customize the report. Used it before and recommend it.
You will create the templates with iReport then write the code for the engine to pass the data in different possible ways.
check http://www.jaspersoft.com/jasperreports
Edit:
You can have background images and overlay the boxes over it and set a limit on the max character size ... and many more
It is very powerful and gives you plenty of options
Here is one of iReport's tutorial for a background image http://ireport-tutorial.blogspot.com/2008/12/background-image-in-ireport.html
The big problem when printing form content that has been filled in electronically, is aligning it correctly on the pre-printed form. You may get content to align for one printer, but when you use another it is completely misaligned.
Fly Software have a form design product called InForm Designer that gets around the problem nicely by allowing users to specify and save vertical and horizontal offsets for printers. This ensures filled in form content is always aligned. I've tried it and it works perfectly. Take a look for yourself here...
http://www.flysoftware.com/products/inform_designer/overview.asp
It might be worth implementing a printer offset similar to InForm's in your own application (if possible).
Some things to think about.
First in terms of the web page, do you want use the stationery as the form layout?
Does it have to be exact?
Combed boxes (one for each character)
Do you want to show it like that on the web page, or deal with the combing later.
How are you going to deal with say a combed 6 digit number. Is this right aligned. What if they enter 7 digits. Same for text. what if it won't fit.
Font choices, we had a lot of fun with W...
How aligned do you want the character within the box, what font limitations does that imply, some of the auto magic software we looked at did crap like change the size of each character.
Combed editing is a nightmare, we display combed, but raise an edit surface the size of the full box on selection.
Another thing that might drive you barking mad, you find find small differences in the size and layout of the boxes, so they look okay from a distance but a column of boxes sort of shifts about by a pixel. Some of testing guys had to lend us their electron microscopes, so we could see how many ink molecules we were out by. :(
Expect to spend a lot of time in the UI side of things, and remember printed stationery changes, so giving yourself some sort of meta description of the form to start with will save you loads of trouble later on.