We're integrating Draw2D/GEF into an application, and are encountering an issue with the standard layouts provided.
We have a collection (say 100) of elements that need to be displayed in a grid-like fashion. We implemented our view using a GraphViewer, and applied a GridLayoutAlgorithm.
This works almost as we'd like it to, but the one stipulation we haven't been able to meet is that each node must be of a constant, defined size. Say, 50x50 pixels. The current GridLayoutAlgorithm we're using resizes the nodes so that they all fit in the window. If our window is small, the 100 elements become minuscule. We would instead like them to fill the width, then wrap to multiple rows, with a vertical scrollbar.
For the life of me, I can't find a simple, straightforward way to accomplish this.
Kind of a bummer answer, but I just ended up writing my own subclass of a GridLayoutAlgorithm and did a bunch of the math by hand. Frustrating that this wasn't included out-of-the-box, but it works fine.
Related
I am currently working on a complex project and struggle with increasing the performance, because I ran out of ideas.
So this is what my program looks like at the moment:
It is a Graph, that shows the path of an object, starting at the green node and ending at the red node. The container is a JPanel, which holds another JPanel at the top right corner, containing the buttons, a JLabel at the top left corner for the status and the different Nodes itself of course. The Nodes and lines are JPanels as well.
So what exactly is the problem?
The Graph contains lots of functionalities. Zooming, DnD and adding end deleting new nodes.
All of these functionalities need the container to repaint, especially DnD needs this very often. So this is just an example with 4 nodes. everything works fine. But at 1000+ nodes and 999 lines between them, it really gets slow. The graph should be able to work with ~20K nodes without having big troubles.
Everytime you move a Node 1px with the mouse in any direction, the whole container gets repainted.
Creating a minimal reproducable example is not quiet possible, because the code for this application is long and there are a lot of dependencies, that would make it not "minimal".
The ideas I have to increase performance are:
Reducing the amount of Nodes (and so the amount of lines), so that less components need to be repainted. This is quiet hard, most nodes are not in a straight line, means there are not many ways to do this. One option would be to reduce the Nodes and increase the level of detail with the zoom function.
Clipping the area, that has to be repainted. The problem with this approach is, that I don't know how exactly this clipping function works or whether it is even possible.
The last idea of mine would be, to somehow create a JLayer object containing (total amount of nodes / 100) layers, that are all visible and only repainting the layer, that contains the specific Node. This seems very unstructured, I don't really think that this is an option, just an idea.
What am I asking for right now?:
How do you manage so much components that have to be repainted? There are definitly ways and I am open to try them all. I just want you to give me some advice, hints on useful built in libraries, that I maybe haven't found in my research. And if one of my ideas could be the one I should go for.
I am not asking for concrete code examples, just for your experience.
Thank you in advance and I'm sorry if my question does not fit the SO conventions.
This is perhaps more of a whine than a question, and I'm aware there's a workaround to the problem described in this post. But I have a situation where I have to add components to a GridLayout, possibly enlarging the grid as I go; but the components don't get created and inserted in a nice neat order; and I don't know when I'm done being handed components to insert into the grid. In other words, in a 3x3 grid I might get handed a component to put at (0,2) and then another at (1,0) and then one at (0,0). And then I might get one at (5,2) and need to enlarge the grid. And then I might get told to replace the line at (0,0) with something else.
I understand that there's no way to say "put a component at x, y". I get that I'm going to have to build a 2D array to hold my components and then empty and refill the grid from the array, each time it changes, which is going to be quite often in several large grids, so I'd rather not. I get that life is like that and the language is the language and who am I to question why.
But I'm really curious. This seems like the most basic of operations for a grid to support. Not having it feels like I'm working with a spreadsheet that only lets you enter values in order from left to right - it's simple madness.
I haven't taken apart the source code for GridLayout, but any naive understanding of how it "must work" makes me think add(component, row, col) should be trivial to implement. It must not be, because GridLayout isn't exactly new and I can't believe I'm the first to think random access to a grid is a good idea. So it must be really hard. But why?
I realize understanding why the internals of GridLayout can't support this, doesn't solve any real problems, except the problem of me unable to stop thinking about how fundamentally weird the restriction is. In the end I'm going to end up with a parallel array, or messing with the more complex GridBagLayout, unless someone knows a better way. But I just want to know why I have to.
Why not approach the problem from a different angle:
Create your grid using GridLayout
Fill the grid with empty JPanels
JPanels that each uses a BorderLayout
Keep these JPanels where they are
But swap the JPanels that they display within them in each of their BorderLayout.CENTER positions
Alternatively, you could have them use a CardLayout, but the effect would be the same
I'm taking my first steps in JavaFX. I want to animate a lot of graphic elements (ellipses, bézier curves, not images) with javafx. These elements are organized in groups of about 10 elements that have to move together. I'm trying to achieve 60 fps and I want to move thousands of these elements.
There are at least four ways to do this:
Using a single canvas, and its graphical context to draw directly at every frame.
Using groups and nodes. Each element is a node. I like this way because there are a lot of classes that can be used to draw easily what I need, and the logical structure of nodes and groups is just what I need.
Each group is a canvas. Draw its elements in its constructor using the canvas graphical context, and then move all the canvases at each frame.
Creating images with the elements that have to stick together, and then move these images. I haven't found already how this can be done, but I suppose it's not hard. The elements may change from time to time, so I will need to recreate some images, but only once in a while.
My question is, which of these ways (or another) would be the fastest way to do it? In particular, does the use of a lot of nodes and groups has a high performance impact?
I would start with option two as this seems to logically fit your needs best. It is also the most straight forward and cleanest way of doing it with JavaFX. If it later turns out that the performance is not good enough you can try to improve this by using caching together with the appropriate cache hints. For example you can optimize your code for speed or for quality this way. This even works dynamically because you can switch between these cache hints depending on the state of your application. If you switch caching on for a group this has basically the same effect as drawing it into a canvas or an image.
I would like to make something that is able to recognize different objects on the screen. Lets say I take a screenshot on a window with textfields, labels and buttons. I would like to pass in the image and it should be able to distinguish one from the other. In other words, it should put the name 'textfield' on top of the position where the textfields are located, 'button' on top of buttons and 'label' on top of labels.
Here is a sample image from the internet, to visualize a 'registration window': http://kb.parallels.com/Attachments/12828/Images/registration1.jpg
I would like to do this in Java, but I'm unsure if this is even possible. Does anyone have any ideas where I should start looking? Edge detection? Feature detection? OCR/ICR?
Does this already exist? Anyone ever come across something like this before?
Could someone please point me to the right direction? I would highly appreciate it.
Thank you! :)
This is how I would work on it:
A) Identification/Segmentation. Without knowing your data, you might be fine with something like "Find a rectangle (or something close to it, since edges are rounded) of less than half of your windows' area" (depends on your data..).
B) Classification. Personally, I'd scale every object you found to size 100*100 (or, whatever) and compare it with sample data (yes, you can scale a mini checkbox to that size. It won't look pretty, but it doesn't matter how it looks like..). Either "brute force" (which is why I scaled) or some nice classification algorithm. (Don't use neural networks, go SVM or nearest neighbour). For classification, I'd mostly look at histograms and shape factors/moments inside the rectangle. If the text confuses the data, get rid of it with some morphology before classification.
Textfields are a bit tricky, but for that, I'd use some OCR library and look at the entire picture. (Personally, I've done well with IMAQ, but it's commercial). If the text is outside a box, you've got yourself a label.
You should probably look into OpenCV.
I'm creating a Java swing GUI and I have formatted a JPanel to use a GridLayout. I need to access a specific "box" (i.e. specific coordinate) of the grid, but I cannot see a way to do so.
How can I do this?
You shouldn't depend on GUI code (the View) to give you information about program data (the model). The best solution would be to "know" which component is where from the start--maybe you should have a data structure (2D array?) that holds the components and is updated whenever something's added to the grid.
If you want a quick and very-dirty fix, though, you could start playing games with JPanel.getComponentAt(). This requires pixel coordinates, though, so you'd need to do some reverse-engineering to figure out how much space a given grid square takes up. The space between grid squares is given by your GridLayout object. This is not recommended whatsoever though. I'm just including it in the interest of completeness (and since it's a more literal response to your question).
In GridLayout, "The container is divided into equal-sized rectangles." You can add an empty, transparent component in places you want to appear empty, e.g. new JLabel(""). See also GridBagLayout and Using Layout Managers.