Rendering a single point in a JFreeChart based on the current Value of a Slider - charts

I'm not yet as much into Java as I'd like to be, so I find my current task to be quite a bit challenging:
A chart showing data gathered in another class.
A slider whose end value is determined by the last entry of in the dataset used in the chart.
The playbutton currently doesn't do anything except letting the slider tick in steps of 5 until it is paused again.
My problem right now is: I am supposed to highlight one item at a time in the chart based on which value the slider currently shows.
And to be honest... I'm not yet used to renderers yet.
If I understood it correctly I would need to use
renderer.drawItem(java.awt.Graphics2D g2,
XYItemRendererState state,
java.awt.geom.Rectangle2D dataArea,
PlotRenderingInfo info,
XYPlot plot,
ValueAxis domainAxis,
ValueAxis rangeAxis,
XYDataset dataset,
int series,
int item,
CrosshairState crosshairState,
int pass)
but I am totally inexperienced with as well the method as its arguments and got no idea how to initialize them.
I mean... I got a plot, a dataset, and 2 series from the chart, I also suggest "item" would be the index of the item to highlight in the series, which I could convert from the slider-value.
Unfortunately plaguing google about it turned out to be rather frustrating since all I got was the very code I posted above on about 50 different pages (I gave up after).
I would like to know ... first of all if I am even about to use the correct method and, as ashamed as I am to ask like this... how to use it.
Well... looking forward to some answers and... thanks in advance.

Well, I now solved my problem in a different way than I intended to but it works out just fine for me.
Instead of highlighting a point in the curves I just simply add a Domainmarker that would adjust based on the value the slider currently shows.
class1 TestSlider
private HashSet<SliderListener> sliderListenerSet = new HashSet<SliderListener>();
public void addSliderListener(SliderListener Listener){
sliderListenerSet.add(Listener);
}
slider.addChangeListener(this);
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
JSlider source = (JSlider)e.getSource();
if (!source.getValueIsAdjusting()) {
fireSliderChanged();
}
}
public void fireSliderChanged(){
for (SliderListener currentListener : sliderListenerSet)
currentListener.sliderValueChanged();
}
class2 SliderListener
public interface SliderListener extends EventListener{
public void SliderValueChanged();
}
class3 Chart
Marker marker = new ValueMarker(0);
plot.addDomainMarker(marker); //so that it would be there at the beginning
TestSlider ts = new TestSlider();
ts.addSliderListener(new SliderListener(){
#Override
public void sliderValueChanged() {
plot.removeDomainMarker(marker); //I only want one of them at a time - the one with the value the slider is currently showing so remove the old one...
marker = new ValueMarker(ts.slider.getValue());
plot.addDomainMarker(marker); // ... and add the one with the new value
}
});
}
I tried to keep it as short and universal as I could and I hope I didnt cut out anything important.
Well, I'm still new to this site, so... in case I did a mistake somewhere feel free to tell me.

Related

Is there an function for "wait frame to end" like "WaitForEndOfFrame" in unity?

I need to do some calculations between every update(), so I need to ensure that a function is processed before the next frame.
Is there any way to achieve this? Just like "WaitForEndOfFrame" in Unity?
You can override the updateTree in your FlameGame (or in your Component, if you only want it to happen before the updates of a subtree) and do your calculations right before all the other components start updating. This would be right after the last frame, except for the first frame, but that one you can skip by setting a boolean.
So something like this:
class MyGame extends FlameGame {
bool isFirstTick = true;
#override
void updateTree(double dt) {
if(!isFirstTick) {
// Do your calculations
} else {
isFirstTick = false;
}
super.updateTree(dt);
}
}
But I have to ask, why do you need to do this? render won't be called until all the update calls are done, do can't you just put your calculations in the normal update method?
In Flutter we don't get an update() function unlike Unity. That is in the default API that we use, there are ways to tap into something of that effect. Normally we use a Ticker and create an animation to get periodic updates synced with screen refresh rate.
However, if what you are trying to do is to run something in between build() calls, WidgetsBinding.instance!.addPostFrameCallback() may be what you are looking for.
Here is a detailed answer that may help in this regard: https://stackoverflow.com/a/51273797/679553

Unity3D Text not changing after being set in Start()

I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.

SetAllDirty() not working at runtime in Unity?

Edit:
After doing a little more debugging I found that it doesn't work only when I start the game and have the panel/canvas that it sits on disabled. If I have the panel/canvas enabled the whole time then it redraws correctly. However, this obviously isn't a proper solution because I can't show the results before the end of the quiz. I need the panel to be disabled so that I can show it later after the end of the quiz.Is there a reason this is happening? How can I fix this?
End Edit
So I found a script on GitHub that basically creates a UI polygon. It works great in the Editor, however, I want to modify it at runtime. From everything I read all I need to do is call the method SetAllDirty() and it will update the MaskableGraphic and Redraw it. However, whenever I call it, nothing happens. SetVerticesDirty() also did not work. Can someone see where I am going wrong here.
All I am doing is calling DrawPolygon and giving it 4 sides, and passing a float[5] I modified it so that right after I finish setting up my new variables I call SetAllDirty()
Something like this:
public void DrawPolygon(int _sides, float[] _VerticesDistances)
{
sides = _sides;
VerticesDistances = _VerticesDistances;
rotation = 0;
SetAllDirty();
}
Like I said, it works fine in the editor(not runtime), and I am also getting all the values passed to the script correctly(during runtime), but it is not redrawing. As soon as I manipulate something in the inspector it will redraw to the correct shape.
The rest of the script is posted here:
https://github.com/CiaccoDavide/Unity-UI-Polygon/blob/master/UIPolygon.cs
This is the method that I call DrawPolygon from on a Manager script. I see in the log that it prints out the statement, Quiz has ended.
void EndQuiz()
{
Debug.Log("Quiz has ended.");
QuizPanel.SetActive(false);
ResultsPanel.SetActive(true);
float[] Vertices = new float[5] { score1, score2, score3, score4, score1};
resultsPolygon.DrawPolygon(4, Vertices);
}

Get max axis value from MS Charts C#.NET

I banged and banged my head on this one for a while and I figured someone else may have this problem down the line. I'm posting my full issue and resolution to those who come later, and to offer a spot for any improvements/simplifications if anyone finds one.
Issue was I am trying to paint VerticalLineAnnotations on my ChartArea. I do not want to anchor it to any data points but merely anchor it to an X axis based on which ChartArea I send in. In my annotation constructor I was trying to set AnchorX.
double maxdate = chart.ChartAreas[0].AxisX.Maximum;
double mindate = chart.ChartAreas[0].AxisX.Minimum;
//use inputdata to find where relative spot is.
if(DateTime.TryParse(date, out ddate)) {
AnchorX = (ddate.ToOADate()) / (maxdate - mindate);
}
I kept getting the mins and maxs to return as NaN, which I found out means the ChartArea will manage itself and set its own max/mins. This was all pre-painting.
I tried post painting but then everytime it painted, it would add annotation, then do postpaint again and infinite loop.
I finally found an event that lets me do this. The Customize() event solved this issue.
private void chart_Customize(object sender, EventArgs e) {
PaintAnnotations();
}
Now immediately before the painting happens, data seems to be loaded and max and mins are already set by this point and I can get values back in the code from above.
Hope this can save someone the hours that I lost!

Problem in Large scale application development and MVP tutorial

I recently tried to follow the Large scale application development and MVP tutorial. The tutorial was great but I am having a hard time with a few things.
If you try and add a contact to the list, the contact is created. If you try and add another contact, you are taken to the edit screen of the last contact you created. No more contacts can be added once you add your first contact. What needs to be changed so you can add more than one contact.
Changes I have made to try and get it to work:
Create a new editContactsView each time the add button is pressed. This brings up a blank edit screen, but the new contact still overwrites the previous addition.
Changed contacts.size() to contacts.size()+1 when determining the ID of the new contact.
Actually, there are a couple of problems (from what I can see):
like Lumpy already mentioned, the new Contact created via EditContactPresenter doesn't get an id assigned (it's null). This is because EditContactPresenter uses the default Contact() constructor which doesn't set the id. There are many possible solutions to this: add setting the id in the default constructor (so that you don't have to keep track of the ids somewhere else in the app), delegate that function to your server (for example, make your DB generate the next available id and send it back) or just add a contact.setId(whatever); in the appropriate place in EditContactsPresenter
AppController.java:134 - this example reuses the view (which is a good idea), but it doesn't clear it if you use it for creating a new Contact. Solution: either disable view reusing (just make a new EditContactsView every time) or add a clear() or sth similar to your Views and make the Presenters call it when they want to create a new entry, instead of editing an exisiting one (in which case, the values from the current entry overwrite the old values, so it's ok).
It's weird that this sample was left with such bugs - although I understand that it's main purpose was to show how MVP and GWT go together, but still :/
When a new contact is added it's id is never set. Because the id field is a string it is stored as "". That is how the first contact is added. Now every time you create a new contact you overwrite the contact with key "". To fix this you need to set the value of the id. I did this by changing the doSave method in EditContactsPresenter.
private void doSave() {
contact.setFirstName(display.getFirstName().getValue());
contact.setLastName(display.getLastName().getValue());
contact.setEmailAddress(display.getEmailAddress().getValue());
if(History.getToken.equals("add")
rpcService.updateContact(contact, new AsyncCallback<Contact>() {
public void onSuccess(Contact result) {
eventBus.fireEvent(new ContactUpdatedEvent(result));
}
public void onFailure(Throwable caught) {
Window.alert("Error updating contact");
}
});
else
rpcService.updateContact(contact, new AsyncCallback<Contact>() {
public void onSuccess(Contact result) {
eventBus.fireEvent(new ContactUpdatedEvent(result));
}
public void onFailure(Throwable caught) {
Window.alert("Error updating contact");
}
});
}