I'm making a stock market game in which the application scrubs the internet for different stocks. I saw an idea for a stock game online, [I do not own this image]:
https://dribbble.com/shots/4161894-Invest-App-UI-Dark-Version
The image on the right has tiny line graphs to show the change in stock value based on previous values of that stock.
and I'm wondering if there is a way to simply make a line graph that applies the values to the previous stock amounts earlier in time using java. I do NOT want it to be a complete graph, with labels and X & Y markers, I just want the line itself to be present
I've tried using JavaFX line graphs, but it had a background and labels and other numbers that I didn't want for the aesthetic.
Basically, the chart consists of many parts (f.i. axis, background grid, legend, graph). Your task is to configure the state of all such that only those you want are showing, in your case (more or less) only the graph.
Astonishingly, nearly everything is configurable to be either visible or not - except for the axis: these have to be manually removed from their parent.
A code snippet to undecorate a LineChart:
protected void undecorate(LineChart chart) {
chart.setLegendVisible(false);
chart.setCreateSymbols(false);
chart.setHorizontalGridLinesVisible(false);
chart.setHorizontalZeroLineVisible(false);
chart.setVerticalGridLinesVisible(false);
chart.setVerticalZeroLineVisible(false);
undecorateAxis(chart.getXAxis());
undecorateAxis(chart.getYAxis());
}
protected void undecorateAxis(Axis axis) {
// trying to hide: not working
// xAxis.setVisible(false);
// configure all ticks/label to not visible doesn't work
// if (axis instanceof ValueAxis)
// ((ValueAxis<?>) axis).setMinorTickVisible(false);
// axis.setTickLabelsVisible(false);
//axis.setTickMarkVisible(false);
// remove from parent does work
Pane parent = (Pane) axis.getParent();
parent.getChildren().removeAll(axis);
}
Related
Could someone tell me how to implement RichTextFX CodeArea with line numbers section extended till the end of the area?
This is how it looks like now:
I don't need line numbers after line 12 but I would like to see this grey bar to fill the entire text area.
Something like here:
P.S. I'm not sure if this is even possible.
I know this is a rather old question, but since I had the same problem, let me share the solution I came up with.
What I did is to smuggle in a rectangle and make sure it is the bottom-most element (i.e. basically part of the background). However, there are a few gotchas when doing this, because the underlying CodeArea is not aware of our new node. If you just insert the rectangle, it might get removed when the CodeArea decides to rebuild the nodes. And getting the right width is a bit tricky because the width of line numbers can basically change at any time and the line-number labels themselves fade in and out of existence whenever you scroll.
So, in order to address these issues, my code sits in the layoutChildren() method and is thus called whenever the nodes in the editor have changed. First we check that the rectangle is actually there as the bottom-most node or insert it if missing. Second, we set the width of the rectangle to the width of the first visible line-number label (which might fail if there are no paragraphs at the moment).
The code itself here is in Scala, but probably easy enough to be quickly adapted to Java.
class MyCodeArea extends CodeArea {
protected val gutterRect = new Rectangle()
gutterRect.heightProperty.bind(this.heightProperty)
gutterRect.getStyleClass.add("lineno")
override protected def layoutChildren(): Unit = {
try {
val children = getChildren
if (!(children.get(0) eq gutterRect))
children.add(0, gutterRect)
val index = visibleParToAllParIndex(0)
val wd = getParagraphGraphic(index).prefWidth(-1)
gutterRect.setWidth(wd)
} catch {
case _: Throwable =>
}
super.layoutChildren()
}
}
Unfortunately, the colour of the rectangle must be assimilated manually. The reason is that the Labels used for line numbers use -fx-background-color, whereas the Rectangle uses -fx-fill. Hence, just setting the same CSS class "lineno" (as I did in my code above) does little to get the colour right. But it allowed me to put both into the same CSS class and therefore have one place where I can change it:
.lineno {
-fx-fill: ivory; // or whatever colour you like
-fx-background-color: -fx-fill;
}
As succinctly as I can manage: Given that I need the layout information of a node (the actual height/width of a node as rendered) to compute my animation, how can I get that information before javafx draws a frame with it?
A little bit longer explanation:
I've got a TreeItem that has child items appearing in it (at the front). What I'd like to have is an animation to cause all existing children to slide down to make room for the new item which would slide in. Each child tree-items contents are different and only known at run-time, meaning the height of each child tree item cannot be expressed as a constant.
This got me writing code along these lines:
groupController.groupTreeItem.getChildren().addListener(
new ListChangeListener<TreeItem<Node>>() {
#Override public void onChanged(Change<? extends TreeItem<Node>> c) {
while(c.next()){
if ( ! c.wasAdded()){
continue;
}
TreeItem newItem = c.getAddedSublist().get(0)
new Timeline(
new KeyFrame(
seconds(0),
new KeyValue(view.translateYProperty(), -1 * newItem.getHeight())
),
new KeyFrame(
seconds(1),
new KeyValue(view.translateYProperty(), 0)
)
);
}
}
}
);
the issue here is that as when a treeItem is added to another, its components aren't laid out by the time the invalidation event is fired, meaning newItem.view.getHeight() returns 0.
My next thought was to then have the animation performed as a reaction to both a change in the list content and a sequential change to the height property, (which got me to write some really hideous code that I'd rather not share --listeners adding listeners is not something I really want to write). This almost works, except that javaFX will draw a single frame with the height property set but without the animations translation applied. I could hack down this road further and try to work something out with opacity being toggled and jobs being enqueued for later, but I figured that this would be the path to madness.
I'm wondering if there's some pseudo-class foo or some clever use of a layout property I could use to help me here. I've been poking around at various combinations of various properties, and haven't gotten anywhere. It seems that as soon as the component has a height, it is rendered, regardless of any listeners you put in or around that height assignment.
Any help much appreciated!
have you tried, overriding this
#Override
protected void updateBounds() {
super.updateBounds();
}
I'm in the process of creating a agent bases modelling program. So far I have the relavent classes to model a simulator, grid, different agents etc. I've also created a 2D array of object e.g. agents moving around the array doing whatever.
I am familary with creating simple GUI's but how do I come about creating a pane\panel which then is added to the GUI. which shows the 2D array on run time with each object with its corresponding colour. Also I want to try and use the MVC pattern to basically display the simulation data differently. Such as one pane shows the different objects colour and another pane showing the same objects but every objects angry levels with different shades of red. Any guidelines would be really helpful also similar tutorials.
Thanks
I'd create a queue (JMS for a very big list of agents, but there are some in-memory queue implementations that are faster to use) and would allow all your agents to write their states in there. Then in another side, I'd write a consumer that listens to the queue to get these states to be processed by your GUI as they're coming.
If there are too many events, you may want to process them in batches, periodically, according to some refresh rate that makes sense for you.
You could use a GUI API like awt and swing (look e.g. at Java 2D game graphics), to create a canvas, upon which you would draw a representation of your system. For example, a set of circles and edges, if the circle is filled, there is an agent there, you can hover mouse over it and or click on it and another panel shows some relevant properties of the agent. Maybe an arrow from a filled circle indicates where the agent is going to go next.
You can instantiate a canvas (like java.awt.canvas), it fits into your GUI as any other widget (panel combo box etc) does it has a size you can add scrollbars etc. As opposed to other controls like combo box, a canvas is a 2d area on which you draw whatever you want.
The MVC is a design structure that separates application concerns along view, control, model axis. Whereas you could put all your control logic such as user input handling, database connection handling, network operations all that could be Don in one place in your canvas class event handling methods, in MVC you would separate all control logic from canvas, canvas event handler would just call the apprpriate controller method (such as handleNewFile). In turn the controller queries the model and tells the view what to show (for instance it loops over all agents in your model and "adds" an agent to the view. The view is where you decide how to represent the agent the controller nothing about representation.
One of the easier ways to go is to create a new Class that extends javax.swing.panel and override the paintComponent()-method.
In the constructor of the new class pass a reference to your 2D-Array.
In your overriden paintComponent()-method do something like this:
public void paintComponent(Graphics g) {
for (int x=0;x<arrayWidth;x++) {
for (int y=0;y<arrayHight;y++) {
switch (array[x][y]) {
case 1: g.setColor(Color.RED);break;
case 2: g.setColor(Color.BLUE);break;
case 3: g.setColor(Color.GREEN);break;
case 4: g.setColor(Color.YELLOW);break;
}
g.drawRect(x*10,y*10,10,10);
}
}
}
Just fit the numbers and colors to your needs.
Edit: if you have some kind of values that can't be used in a switch statement (like e.g. custom classes or Strings in older Java-versions) just replace it with if/elseifs:
public void paintComponent(Graphics g) {
for (int x=0;x<arrayWidth;x++) {
for (int y=0;y<arrayHight;y++) {
if (array[x][y].equals(value1)) {
g.setColor(Color.RED);
} else if (array[x][y].equals(value2)) {
g.setColor(Color.BLUE);
} else if (array[x][y].equals(value3)) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.YELLOW);
}
g.drawRect(x*10,y*10,10,10);
}
}
}
I've created a XYChart with numerical values different (for example temperatue with pressure) so I want to draw my own axeS just beside my chart. To do the following I've to unshow the YAxis, how should I do that ?
By using a trick: The Chart needs the Y Axis to remain in place so it knows where to render your content. You can, however, hide it. Hide the tick labels and set the axis' opacity to 0 using this code:
chart.getYAxis().setTickLabelsVisible(false);
chart.getYAxis().setOpacity(0);
The axis will still be there, but not shown.
I found that if I hid the chart using the following code:
chart.getXAxis().setTickLabelsVisible(false);
chart.getXAxis().setTickMarkVisible(false);
((Path)chart.getXAxis().lookup(".axis-minor-tick-mark")).setVisible(false);
Then I get about ~10 pixels less blank space on the bottom. IF the space was an issue for your application then you could use css offsets to correct it. This solution may have more predictable offsets.
SOLVED: I got this to work for sharing a common x-axis for two charts stacked vertically:
Create two charts, each with their own identical copy of the x-axis object, setting identical upper and lower bounds (optionally by binding).
Then hide the x-axis in the second chart like this:
chart = new LineChart<Number,Number>(xaxis2,yaxis2) {
{// hide xAxis in constructor, since not public
getChartChildren().remove(getXAxis());
// not getPlotChildren()
}
};
You'll want to set the widths of your y-axes to be the identical, e.g.
int w = 60;
yaxis.setMaxWidth(w);
yaxis.setMinWidth(w);
yaxis.setPrefWidth(w);
yaxis2.setMaxWidth(w);
yaxis2.setMinWidth(w);
yaxis2.setPrefWidth(w);
I need to implement a Bar chart Where it reads values when the user touches the graph to move it vertically. The graph moves up, recording the value in accordance with the axis . With x axis being the value and the Y axis being the variables , i need to perform calculations. Example to understand
Take a look at this example. You can also do mChartView.addPanListener and handle this event for what you need.