I was wondering, had anyone experience using JXLayer + JHotdraw, to overlay all sorts of figures (Re-sizable text box, straight line, circle…), on the top of JFreeChart.
I just would like to add drawing capability, without changing the JFreeChart source code. So that, JStock's user may draw trending lines, annotation text on their favorite stock charting.
If anyone of you had experience of doing so, I will be very happy, if you are willing to share your experience to us.
Thank you very much.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am not familiar with JFreeChart and JXLayer.
I guess JFreeChart provides a JComponent into which it draws its chart?
If this is the case, you can create a JHotDraw Figure which invokes the paint-Method of that JComponent.
Here is a rough idea on how I would do it:
1. Create a subclass of RectangleFigure.
2. Override the draw-method. Create a javax.swing.CellRendererPane. Resize it to match the bounds of the figure. Add the JFreeChart component to it. Call the paint-method of the CellRendererPane.
3. Override the getLayer method. Make it return -1. This way, this figure will stay below all other JHotDraw figures.
4. Override methods isConnectable, isSelectable, isTransformable and make them all return false. This way, the figure can not be edited.
Best,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As you see, I already got Graphics2D g2 from paintLayer method. How is it possible that I can pass the Graphics2D object to JHotDraw, and let JHotDraw handles all the drawing.
Sorry, maybe I should have elaborated my proposal a bit more.
The code snippets that you have posted are useful for displaying a JHotDraw drawing on top of JFreeChart.
This is perfectly fine. But it is not suited for editing a drawing.
My proposal is to create a new figure class which holds the JFreeChart JComponent.
I am suggesting to use RectangleFigure as super class, because JComponent's are rectangular.
Then you can add this figure to your drawing, and display that drawing in a DefaultDrawingView.
You can use DefaultDrawingEditor to make the drawing in the drawing view editable.
hth,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
final JComponentFigure jComponentFigure = new JComponentFigure(layer);
final java.awt.Rectangle rect = this.svgDrawingPanel.getBounds();
System.out.println(rect); // dimension is 0?
// Temporary hard coded.
jComponentFigure.setBounds(new Rectangle2D.Double(0, 0, 450, 450));
this.svgDrawingPanel.addFigure(jComponentFigure);
getContentPane().add(svgDrawingPanel, java.awt.BorderLayout.CENTER);
JComponentFigure code is as follow :
publicclassJComponentFigureextendsRectangleFigure{publicJComponentFigure(JComponentcomponent){this.component=component;this.cellRendererPane=newCellRendererPane();}@Overridepublicvoiddraw(Graphics2Dg){super.draw(g);finalRectangle2D.DoublerectDouble=this.getDrawingArea();finalRectanglerect=newRectangle((int)rectDouble.getX(),(int)rectDouble.getY(),(int)rectDouble.getWidth(),(int)rectDouble.getHeight());cellRendererPane.paintComponent(g,component,component.getParent(),rect);System.out.println("JComponentFigure's draw is being triggered");}privatefinalCellRendererPanecellRendererPane;privatefinalJComponentcomponent;}
svgDrawingPanel, are just simply picked from sample code found at JHotDraw\Source\jhotdraw7\src\main\java\org\jhotdraw\samples\svg\SVGDrawingPanel.java
with new method being added in SVGDrawingPanel.
public void addFigure(Figure figure) {
this.view.getDrawing().add(figure);
}
I am getting something like
By using println, I am pretty sure JComponentFigure 's pain method is being triggered.
Anything I had missed out?
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You may have to override method isShowing of the JComponent that you want to draw using the cellRenderePane.
The JavaDoc of CellRendererPane says:
"A renderer component must override isShowing() and unconditionally return true to work correctly because the Swing paint does nothing for components with isShowing false."
Best,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Alternatively, if all this gets too complicated.
You might render the JComponent into a BufferedImage, and then use an ImageFigure to represent it in the drawing.
Best,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You have to override method isShowing of JFreeChart. Since this is the JComponent that is going to be rendered by the CellRendererPane:
JFreeChart myChart = new JFreeChart() {
@Override public boolean isShowing() { return true; }
};
> My another concern is, are JHotDraw able to pass all the necessary event back to my old JXLayer and JFreeChart
Hm. Do you really want JFreeChart and JXLayer to process input events while the user is drawing on top of them?
I don't think this is a good idea.
For example what happens if the user drags a figure? Its not a good idea to let JFreeChart perform a zoom-in or zoom-out during this operation.
By integrating JFreeChart as a Figure into JHotDraw, you can easily coordinate all user input.
> JXLayer - concern about mouse move event, where when I move the mouse along, the yellow box will follow the mouse
> movement.
JHotDraw already supports tooltips on figures. You can override method getToolTipText in your JComponentFigure.
> JFreeChart - concern about mouse drag event, to handle chart zoom-in and zoom-out.
JHotDraw already has a zoom function.
I think you certainly want to keep the zoom factor of the drawing in sync with the zoom factor of the JFreeChart?
hth,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am able to have JFreeChart component display within the rectangle figure, by removing JXLayer (Not sure why, even I set isShowing to true for JXLayer), after set isShowing to true for JFreeChart.
However, one of the expected short coming is, all event listener behavior default to JFreeChart component is lost.
Is there any way, where by push down a draw button, all the event will be forwarded to JHotDraw. and by pop up a draw button, all the event will be forwarded to the component re-inside (JFreeChart component) rectangle figure?
Is not, I prefer to implement the draw code within JXLayer draw function, by using several data structure class from JHotDraw. I only need some primitive drawing feature
- click and move, on an empty draw area, to draw a new figure.
- click and move, on an already drawn figure, to drag move the figure.
- click and move, to resize the selected figure.
- figure will be circle, lines and pictures.
Do you have any suggestion on which data structure classes from JHotDraw I can re-use?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am glad that embedding JFreeChart into RectangleFigure worked.
As far as I can tell, the things that you are missing now are:
A) Tooltips (which you previously implemented by means of JXLayer)
B) Zooming (which previously was provided by JFreeChart)
To achieve A) you can override method getToolTipText(Point2D.Double) in RectangleFigure. The implementation will be very much like the one you already have. You just need to translate the point by the start point of the RectangleFigure. You can use method getStartPoint for this.
For B) you can implement a new DragTracker, which changes the scale factor of the drawing view instead of moving figures.
> Is there any way, where by push down a draw button, all the event will be forwarded to JHotDraw. and by pop up a draw
> button, all the event will be forwarded to the component re-inside (JFreeChart component) rectangle figure?
Yes. All event handling is done by Tool objects. You can create a Tool which doesn't provide drawing behavior.
If the user clicks the button for this tool, then JHotDraw is in "viewing mode", the user clicks on the button for another tool, then JHotDraw is in "editing mode".
How to put things together:
1. I suggest that you first try to implement the tooltips.
2. Then try adding a button for an additional DefaultDelegationTool to your user interface. You can use ButtonFactory.addSelectionToolTo(JToolBar, DrawingEditor, Tool) for creating the toolbar button.
3. Strip functionality from the additional DefaultDelegationTool to achieve a "viewing mode". You can do this, by creating empty implementations of HandleTracker, SelectAreaTracker and DragTracker and setting them to the DefaultDelegationTool.
4. Now implement a new DragTracker - as I suggested for B - and set it to the additional DefaultDelegationTool.
hth,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
2) Currently, if I right click on JFreeChart, it can pop up a menu with wide range of functionality selection.
- How can I pass the right click event to JFreeChart?
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Please note that my interest is just into showing you a way through the JHotDraw framework.
There might be other approaches to solve this problem. I don't know your requirements in detail.
1)
JTooltip supports HTML. You can specify the font type, alignments and stuff like this using HTML.
If this is not sufficient, you can always add new methods to your RectangleFigure and then look for uses of method Figure.getToolTipText(Point2D.Double) in JHotDraw - which will lead you to the Tool classes down to DelegationSelectionTool and the DefaultDrawingView -, and then extend these classes along this execution path.
2)
You can't pass AWT events down to JFreeChart anymore since it used as a "rubber stamp" in RectangleFigure.
If you want to have support for actions presented by the JFreeChart popup menu, _while_ the drawing editor is in "edit mode" (as described in my previous reply) you need to find a way to retrieve the underlying Actions from JFreeChart and then relegate them to method RectangleFigure.getActions(Point2D.Double).
Alternatively, if you only need support for JFreeChart functionality while the drawing editor is in "view mode" then you can use the JXLayer solution, which you already have implemented, while "view mode" is on, and the above solution, while "edit mode" is on.
Best,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Not sure whether you would like to provide additional advice?
The worst come to worst, is I plan to use data structure classes (Figure…) from JHotDraw, but implement the real painting code directly inside JXLayer. But of course, that is for the worst case, if only there isn't any more better way to integrate JHotDraw with JFreeChart.
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well, you have now explored two different alternatives. It is up to you to pick the one which suits you best.
Personally, I think both approaches are very fragile. I mean, you are jumbling together four
libraries here (JXLayer, JHotDraw, JFreeChart and your tooltips).
Personally, I would implement the chart as a Figure in JHotDraw.
This way, I would only have to deal with a single library.
Best,
Werner
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So far, I am a happy JHotDraw users. I had been using JHotDraw in JStock's Indicator Editor exclusively.
Recently, I had use JXLayer, to overlay two moving yellow message boxes, on the top of JFreeChart
http://yccheok.blogspot.com/2010/02/investment-flow-chart.html
I was wondering, had anyone experience using JXLayer + JHotdraw, to overlay all sorts of figures (Re-sizable text box, straight line, circle…), on the top of JFreeChart.
I just would like to add drawing capability, without changing the JFreeChart source code. So that, JStock's user may draw trending lines, annotation text on their favorite stock charting.
If anyone of you had experience of doing so, I will be very happy, if you are willing to share your experience to us.
Thank you very much.
Hi,
I am not familiar with JFreeChart and JXLayer.
I guess JFreeChart provides a JComponent into which it draws its chart?
If this is the case, you can create a JHotDraw Figure which invokes the paint-Method of that JComponent.
Here is a rough idea on how I would do it:
1. Create a subclass of RectangleFigure.
2. Override the draw-method. Create a javax.swing.CellRendererPane. Resize it to match the bounds of the figure. Add the JFreeChart component to it. Call the paint-method of the CellRendererPane.
3. Override the getLayer method. Make it return -1. This way, this figure will stay below all other JHotDraw figures.
4. Override methods isConnectable, isSelectable, isTransformable and make them all return false. This way, the figure can not be edited.
Best,
Werner
Thanks Werner.
Is your suggested way only able to draw rectangle figures? How about circle figures, line figures, picture figures…
For my, I prefer to do in the following way. However, I am not sure whether it is possible to do so.
As you see, I already got Graphics2D g2 from paintLayer method. How is it possible that I can pass the Graphics2D object to JHotDraw, and let JHotDraw handles all the drawing.
My experience in using JHotDraw are with
org.jhotdraw.draw.DefaultDrawingView
org.jhotdraw.draw.DefaultDrawingEditor
I am able to use them to draw various figures, by clicking on the toolbar and click on drawing area.
How is it possible I can use DefaultDrawingView and DefaultDrawingEditor within MyUI's paintLayer?
Also, shall I let MyUI handles the mouse event, or JHotDraw?
Sorry, I start getting confused.
Sorry. The code tag seems missing in previous post.
Sorry, maybe I should have elaborated my proposal a bit more.
The code snippets that you have posted are useful for displaying a JHotDraw drawing on top of JFreeChart.
This is perfectly fine. But it is not suited for editing a drawing.
My proposal is to create a new figure class which holds the JFreeChart JComponent.
I am suggesting to use RectangleFigure as super class, because JComponent's are rectangular.
Then you can add this figure to your drawing, and display that drawing in a DefaultDrawingView.
You can use DefaultDrawingEditor to make the drawing in the drawing view editable.
hth,
Werner
Thanks. Hope able to obtain your priceless support during the integration work ;)
What I start to do is :
http://jstock.cvs.sourceforge.net/viewvc/jstock/jstock/src/org/yccheok/jstock/gui/charting/ChartJDialog.java?revision=1.20&view=markup
For line 133, instead of
I change it to :
JComponentFigure code is as follow :
svgDrawingPanel, are just simply picked from sample code found at JHotDraw\Source\jhotdraw7\src\main\java\org\jhotdraw\samples\svg\SVGDrawingPanel.java
with new method being added in SVGDrawingPanel.
I am getting something like
By using println, I am pretty sure JComponentFigure 's pain method is being triggered.
Anything I had missed out?
Thanks.
You may have to override method isShowing of the JComponent that you want to draw using the cellRenderePane.
The JavaDoc of CellRendererPane says:
"A renderer component must override isShowing() and unconditionally return true to work correctly because the Swing paint does nothing for components with isShowing false."
Best,
Werner
Alternatively, if all this gets too complicated.
You might render the JComponent into a BufferedImage, and then use an ImageFigure to represent it in the drawing.
Best,
Werner
I tried
But result is still the same :(
My another concern is, are JHotDraw able to pass all the necessary event back to my old JXLayer and JFreeChart
JXLayer - concern about mouse move event, where when I move the mouse along, the yellow box will follow the mouse movement.
JFreeChart - concern about mouse drag event, to handle chart zoom-in and zoom-out.
>I tried
>…
>But result is still the same :(
You have to override method isShowing of JFreeChart. Since this is the JComponent that is going to be rendered by the CellRendererPane:
JFreeChart myChart = new JFreeChart() {
@Override public boolean isShowing() { return true; }
};
> My another concern is, are JHotDraw able to pass all the necessary event back to my old JXLayer and JFreeChart
Hm. Do you really want JFreeChart and JXLayer to process input events while the user is drawing on top of them?
I don't think this is a good idea.
For example what happens if the user drags a figure? Its not a good idea to let JFreeChart perform a zoom-in or zoom-out during this operation.
By integrating JFreeChart as a Figure into JHotDraw, you can easily coordinate all user input.
> JXLayer - concern about mouse move event, where when I move the mouse along, the yellow box will follow the mouse
> movement.
JHotDraw already supports tooltips on figures. You can override method getToolTipText in your JComponentFigure.
> JFreeChart - concern about mouse drag event, to handle chart zoom-in and zoom-out.
JHotDraw already has a zoom function.
I think you certainly want to keep the zoom factor of the drawing in sync with the zoom factor of the JFreeChart?
hth,
Werner
Sorry for late reply. I haven't try that out yet as I am working on other stuffs else. Will update here soon…
I am able to have JFreeChart component display within the rectangle figure, by removing JXLayer (Not sure why, even I set isShowing to true for JXLayer), after set isShowing to true for JFreeChart.
However, one of the expected short coming is, all event listener behavior default to JFreeChart component is lost.
Is there any way, where by push down a draw button, all the event will be forwarded to JHotDraw. and by pop up a draw button, all the event will be forwarded to the component re-inside (JFreeChart component) rectangle figure?
Is not, I prefer to implement the draw code within JXLayer draw function, by using several data structure class from JHotDraw. I only need some primitive drawing feature
- click and move, on an empty draw area, to draw a new figure.
- click and move, on an already drawn figure, to drag move the figure.
- click and move, to resize the selected figure.
- figure will be circle, lines and pictures.
Do you have any suggestion on which data structure classes from JHotDraw I can re-use?
I am glad that embedding JFreeChart into RectangleFigure worked.
As far as I can tell, the things that you are missing now are:
A) Tooltips (which you previously implemented by means of JXLayer)
B) Zooming (which previously was provided by JFreeChart)
To achieve A) you can override method getToolTipText(Point2D.Double) in RectangleFigure. The implementation will be very much like the one you already have. You just need to translate the point by the start point of the RectangleFigure. You can use method getStartPoint for this.
For B) you can implement a new DragTracker, which changes the scale factor of the drawing view instead of moving figures.
> Is there any way, where by push down a draw button, all the event will be forwarded to JHotDraw. and by pop up a draw
> button, all the event will be forwarded to the component re-inside (JFreeChart component) rectangle figure?
Yes. All event handling is done by Tool objects. You can create a Tool which doesn't provide drawing behavior.
If the user clicks the button for this tool, then JHotDraw is in "viewing mode", the user clicks on the button for another tool, then JHotDraw is in "editing mode".
How to put things together:
1. I suggest that you first try to implement the tooltips.
2. Then try adding a button for an additional DefaultDelegationTool to your user interface. You can use ButtonFactory.addSelectionToolTo(JToolBar, DrawingEditor, Tool) for creating the toolbar button.
3. Strip functionality from the additional DefaultDelegationTool to achieve a "viewing mode". You can do this, by creating empty implementations of HandleTracker, SelectAreaTracker and DragTracker and setting them to the DefaultDelegationTool.
4. Now implement a new DragTracker - as I suggested for B - and set it to the additional DefaultDelegationTool.
hth,
Werner
I still have question in doubt :)
1) public String getToolTipText(Point2D.Double p);
I afraid by overriding the getToolTipText doesn't meet my requirement as
1) http://3.bp.blogspot.com/_ttdgIQxreUA/S4ECdNEjQ-I/AAAAAAAADPY/W2OvcQoQGjU/s1600-h/genting.png
- It doesn't let me specific I want yellow semi-transparent background.
- It doesn't let me specific I want yellow border
- It doesn't let me specific the font type
- It doesn't let me specific the text alignment.
2) Currently, if I right click on JFreeChart, it can pop up a menu with wide range of functionality selection.
- How can I pass the right click event to JFreeChart?
Thanks.
Please note that my interest is just into showing you a way through the JHotDraw framework.
There might be other approaches to solve this problem. I don't know your requirements in detail.
1)
JTooltip supports HTML. You can specify the font type, alignments and stuff like this using HTML.
If this is not sufficient, you can always add new methods to your RectangleFigure and then look for uses of method Figure.getToolTipText(Point2D.Double) in JHotDraw - which will lead you to the Tool classes down to DelegationSelectionTool and the DefaultDrawingView -, and then extend these classes along this execution path.
2)
You can't pass AWT events down to JFreeChart anymore since it used as a "rubber stamp" in RectangleFigure.
If you want to have support for actions presented by the JFreeChart popup menu, _while_ the drawing editor is in "edit mode" (as described in my previous reply) you need to find a way to retrieve the underlying Actions from JFreeChart and then relegate them to method RectangleFigure.getActions(Point2D.Double).
Alternatively, if you only need support for JFreeChart functionality while the drawing editor is in "view mode" then you can use the JXLayer solution, which you already have implemented, while "view mode" is on, and the above solution, while "edit mode" is on.
Best,
Werner
Hi Werner,
I did some quick hack during weekend. I try to get some additional advice from JXLayer community. The closest solution I can get is http://forums.java.net/jive/thread.jspa?messageID=397847񡈗
Not sure whether you would like to provide additional advice?
The worst come to worst, is I plan to use data structure classes (Figure…) from JHotDraw, but implement the real painting code directly inside JXLayer. But of course, that is for the worst case, if only there isn't any more better way to integrate JHotDraw with JFreeChart.
Thanks.
Well, you have now explored two different alternatives. It is up to you to pick the one which suits you best.
Personally, I think both approaches are very fragile. I mean, you are jumbling together four
libraries here (JXLayer, JHotDraw, JFreeChart and your tooltips).
Personally, I would implement the chart as a Figure in JHotDraw.
This way, I would only have to deal with a single library.
Best,
Werner