how to plot different graphs on the same QChart in Qt - qt

I am trying to plot a different graph on QChart when i click on a button. That's what I've tried till now:
QChart *charts = new QChart();
charts->legend()->hide();
charts->createDefaultAxes();
std::string name = "Channel";
charts->setTitle(QString::fromStdString(name));
QChartView *chartView_1 = new QChartView(charts);
chartView_1->setRenderHint(QPainter::Antialiasing);
QGridLayout *gridLayout_1 = new QGridLayout(ui->widget);
gridLayout_1->addWidget(chartView_1,0,0);
this is written in the constructor
void MainWindow::on_pushButton_clicked()
{
QScatterSeries *series_1 = new QScatterSeries();
for(int k = 0; k < 127; k++){
series_1->append(k + (k/2),k);
series_1->setMarkerSize(4.0);
}
QChart *charts = new QChart();
charts->addSeries(series_1);
QChartView *chartView_1 = new QChartView(charts);
chartView_1->repaint();
QGridLayout *gridLayout_1 = new QGridLayout(ui->widget);
gridLayout_1->addWidget(chartView_1,0,0);
}
and this one in the button function.

Actually I just added:
gridLayout_1->deleteLater();
and it worked

Related

How can I adapt my chart size according to my datas automatically in QT?

I have a scrolling dynamic chart. When the new data come, I cannot see because the chart size. Can I automatize it? Does qt charts have a property like that? enter image description here
void MainWindow::initChartView()
{
QChart *chart = new QChart();
chart->addSeries(series);
qDebug()<< series;
QPen green(Qt::red);
green.setWidth(2);
series->setPen(green);
chart->legend()->hide();
chart->setTitle("deneme");
chart->setAnimationOptions(QChart::AllAnimations);
QValueAxis *axisX=new QValueAxis;
axisX->setTickCount(5);
axisX->setRange(0, 2);
chart->addAxis(axisX, Qt::AlignBottom);
series->attachAxis(axisX);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(5);
axisY->setRange(0,2);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
this->setCentralWidget(chartView);
}
enter image description here

JavaFX cannot draw line in BarChart

I want a draw a line in a Barchart. the line reflects a certain value to which other values are compared. I applied the solution for a LineChart to my situation (see code). However, no line is drawn.
public XYChart buildBarChart ()
{
Line valueMarker = new Line ();
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();
BarChart<String,Number> barChart = new BarChart<String,Number> (xAxis,yAxis);
barChart.setBarGap (-10);
barChart.setCategoryGap (0);
barChart.getYAxis().setTickLabelsVisible(false);
barChart.getYAxis().setOpacity(0);
yAxis.setLabel ("Score");
// update marker
Node chartArea = barChart.lookup (".chart-plot-background");
Bounds chartAreaBounds = chartArea.localToScene (chartArea.getBoundsInLocal ());
// remember scene position of chart area
yShift = chartAreaBounds.getMinY();
// set x parameters of the valueMarker to chart area bounds
valueMarker.setStartX (chartAreaBounds.getMinX());
valueMarker.setEndX (chartAreaBounds.getMaxX());
// find pixel position of that value
double displayPosition = yAxis.getDisplayPosition (valNederland);
// update marker
valueMarker.setStartY (yShift + displayPosition);
valueMarker.setEndY (yShift + displayPosition);
BarChart.Series<String,Number> series1 = new BarChart.Series<String,Number> ();
BarChart.Series<String,Number> series2 = new BarChart.Series<String,Number> ();
BarChart.Series<String,Number> series3 = new BarChart.Series<String,Number> ();
BarChart.Series<String,Number> series4 = new BarChart.Series<String,Number> ();
series1.getData ().add (new XYChart.Data<String,Number> (sRegio, valRegio_2015));
series2.getData ().add (new XYChart.Data<String,Number> (sOmgeving, valOmgeving));
series3.getData ().add (new XYChart.Data<String,Number> (sRest, valRest));
series4.getData ().add (new XYChart.Data<String,Number> (sNl, valNederland));
barChart.getData().addAll (series1, series2, series3, series4);
return barChart;
} /*** buildBarChart ***/
Essential for this situation is to have the coordinates of the ChartArea. When I inspect the properties of ChartArea in the debugger I find that all values of _geomBounds are 'unlogic', i.e. maxX/Y = -1 and minX/Y = -1. I inspect just one line after chartASreaBounds is assigned a value.
To me it seems that the barChart lookup fails as I had a similar problem before. Does anyone have a suggestion of how to correct this situation?
Edit
The BarChart is created in the constructor as follows:
public Charter (int nTimes, int nCategories, float [] years, String [] titles, String label, Indicator ind, float [] past)
{
this ();
// all kind of code to do somethong with the parameters omitted
// ...
// Setting up the BarChart. Note that past == null in my experiments
HBox hBox = new HBox ();
XYChart bar = buildBarChart ();
bar.setPrefHeight (height);
bar.setPrefWidth (width);
VBox buttons = buildButtonView ();
if (past != null)
{
XYChart line = buildLineChart ();
line.setPrefHeight (height);
line.setPrefWidth (width);
hBox.getChildren ().addAll (bar, line);
} else
{
hBox.getChildren ().addAll (bar);
} // if
Label dsecription = new Label (label);
this.getProperties ().put ("--Indicator", ind.getName ());
this.getChildren ().addAll (dsecription, hBox);
} /*** Charter ***/
After a Charter has been created it is added to the VBox and therewith shows on the screen as VBox is already added to the scene.
It looks like you want to calculate the position of the bar chart on the screen before it is added to the scene. Since at that point it is not yet on the screen that position is -1 or not defined.
I tend to make my layouts in fxml, therefore such problems don't appear. If you need to do it in code, I think first adding it to the children of hBox before drawing the line could solve the issue.

Assigning a MouseListener to each Region in a 2d array of Regions

I posted a question here a couple weeks ago for some help on making a chess game and I got a great response and some code that demonstrates a solution to my problem. I have been trying to dissect the code and study it so I can better understand how it works. While doing this I ran into a question I can not seem to find an answer for. The chess board is made up of a 2d array of Regions and I am trying to add a MouseListener to each Region in the 2d array so that when a Region is pressed it will print out the row and column of the Region that was pressed. Right now nothing is happening when I press on a square in my screen and I can't not figure out why my MouseListener is not working.
public class Main extends Application {
GridPane root = new GridPane();
final int size = 8;
int col = 0;
int row = 0;
#Override
public void start(Stage primaryStage) {
try {
GridPane board = new GridPane();
Region[][] fields = new Region[8][8];
for (int i = 0; i < fields.length; i++) {
Region[] flds = fields[i];
for (int j = 0; j < flds.length; j++) {
Region field = new Region();
flds[j] = field;
field.setBackground(new Background(new BackgroundFill((i + j) % 2 == 0 ? Color.WHITE : Color.LIGHTBLUE, CornerRadii.EMPTY, Insets.EMPTY)));
}
board.addRow(i, flds);
}
for (int i = 0; i < fields.length; i++) {
col = i;
for (int j = 0; j < fields[i].length; j++) {
row = j;
fields[i][j].setOnMouseClicked(e->{
System.out.println("Col:" + col + ", Row" + row);
});
}
}
// use 1/8 of the size of the Grid for each field
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(100d / 8);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(100d / 8);
for (int i = 0; i < 8; i++) {
board.getColumnConstraints().add(columnConstraints);
board.getRowConstraints().add(rowConstraints);
}
Pane piecePane = new Pane();
StackPane root = new StackPane(board, piecePane);
// NumberBinding boardSize = Bindings.min(root.widthProperty(), root.heightProperty());
NumberBinding boardSize = Bindings.min(root.widthProperty(), root.heightProperty());
// board size should be as large as possible but at most the min of the parent sizes
board.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
// same size for piecePane
piecePane.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
piecePane.maxWidthProperty().bind(boardSize);
piecePane.maxHeightProperty().bind(boardSize);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Change:
StackPane root = new StackPane(board,piecePane);
to:
StackPane root = new StackPane(piecePane,board);
🐞?
Because the board was behind the piecePane it couldn't receive events.
Before you were using global variables col and row so these variables had always the same value of 7 and 7. Running the loop those variables where changing their value,but at the end they had the values 7 7 , here we need to use local variables col and row , so you need to add this modification:
for (int i = 0; i < fields.length; i++) {
int col = i;
for (int j = 0; j < fields[i].length; j++) {
int row = j;
fields[i][j].setOnMouseClicked(e -> System.out.println("Col:" + col + ", Row" + row));
}
}
I haven't worked much in JavaFX myself, though it is very similar to java swing regarding basic "collision".
There is a rectangle class with the methods contains and intersects. If you use MouseEvent to know the mouse coordinates and when the mouse is clicked. You can do something like this:
if(mouse.isClicked() && rect.contains(mouse.x, mouse.y) { // do stuff }
You need to create rectangle objects for all the squares though. Hope it works out.
EDIT: Noticed Regions also contained the methods contains and intersects - try these beforehand, use rectangles only if you must to skip too much object creation.

Combine 3 JavaFX features into one class on single GUI window

I'm trying to combine 3 features into a single JavaFX class. My first feature displays "WELCOME TO JAVA" around in a circle. The second displays a 10x10 matrix of random 1's and 0's. The third displays a smiley face. They should be displayed one after the other in a single pane. I have the first and third features but the matrix one is throwing me off. Although everything is supposed to be in a single pane to display on the same GUI window (per professor), I don't see how else I could've done the matrix other than creating the gridPane. It displays fine without the size constraints, but then it takes up the entire screen and my other 2 features aren't visible. When I add the constraints, it gets small and the numbers aren't visible. I'm not sure how I can fix this. Can someone please help?
Pane pane = new Pane();
// Create a circle and set its properties
Circle circle = new Circle();
circle.setCenterX(100);
circle.setCenterY(100);
circle.setRadius(50);
circle.setStroke(null);
circle.setFill(null);
pane.getChildren().add(circle); // Add circle to the pane
//Display WELCOME TO JAVA with the text forming a circle
int i = 0;
String phrase = "WELCOME TO JAVA ";
double degree = 360 / phrase.length();
for (double degrees = 0; i < phrase.length(); i++, degrees += degree) {
double pointX = circle.getCenterX() + circle.getRadius() *
Math.cos(Math.toRadians(degrees));
double pointY = circle.getCenterY() + circle.getRadius() *
Math.sin(Math.toRadians(degrees));
Text letter = new Text(pointX, pointY, phrase.charAt(i) + "");
letter.setFill(Color.BLACK);
letter.setFont(Font.font("Times New Roman", FontWeight.BOLD, 20));
letter.setRotate(degrees + 90);
pane.getChildren().add(letter); }
//Create a 10x10 matrix of 1s and 0s
GridPane pane2 = new GridPane();
pane2.setHgap(1);
pane2.setVgap(1);
Button[][] matrix;
int length = 10;
int width = 10;
ArrayList<TextField> textFields = new ArrayList<>();
for (int y = 0; y < length; y++) {
ColumnConstraints colConst = new ColumnConstraints();
colConst.setPercentWidth(10);
pane2.getColumnConstraints().add(colConst);
for (int x = 0; x < width; x++) {
RowConstraints rowConst = new RowConstraints();
rowConst.setPercentHeight(10);
pane2.getRowConstraints().add(rowConst);
Random rand = new Random();
int random1 = rand.nextInt(2);
TextField textf = new TextField();
textf.setText("" + random1);
textf.setPrefSize(15, 15);
pane2.setRowIndex(textf, x);
pane2.setColumnIndex(textf, y);
pane2.getChildren().add(textf);
}}
//Create a smiley face
Circle circle2 = new Circle();
circle2.setCenterX(600.0f);
circle2.setCenterY(100.0f);
circle2.setRadius(50.0f);
circle2.setStroke(Color.BLACK);
circle2.setFill(null);
pane.getChildren().add(circle2);
Circle leftInnerEye = new Circle();
leftInnerEye.setCenterX(580.0f);
leftInnerEye.setCenterY(85.0f);
leftInnerEye.setRadius(5);
leftInnerEye.setStroke(Color.BLACK);
pane.getChildren().add(leftInnerEye);
Ellipse leftOutterEye = new Ellipse();
leftOutterEye.setCenterX(580.0f);
leftOutterEye.setCenterY(85.0f);
leftOutterEye.setRadiusX(11.0f);
leftOutterEye.setRadiusY(8.0f);
leftOutterEye.setStroke(Color.BLACK);
leftOutterEye.setFill(null);
pane.getChildren().add(leftOutterEye);
Circle rightEye = new Circle();
rightEye.setCenterX(620.0f);
rightEye.setCenterY(85.0f);
rightEye.setRadius(5);
rightEye.setStroke(Color.BLACK);
pane.getChildren().add(rightEye);
Ellipse rightOutterEye = new Ellipse();
rightOutterEye.setCenterX(620.0f);
rightOutterEye.setCenterY(85.0f);
rightOutterEye.setRadiusX(11.0f);
rightOutterEye.setRadiusY(8.0f);
rightOutterEye.setStroke(Color.BLACK);
rightOutterEye.setFill(null);
pane.getChildren().add(rightOutterEye);
Polygon nose = new Polygon();
nose.getPoints().setAll(
600d, 90d,
588d, 115d,
612d, 115d );
nose.setStroke(Color.BLACK);
nose.setFill(null);
pane.getChildren().add(nose);
Arc mouth = new Arc(600, 115, 30, 16, 180, 180);
mouth.setFill(null);
mouth.setType(ArcType.OPEN);
mouth.setStroke(Color.BLACK);
pane.getChildren().add(mouth);
HBox hbox = new HBox(pane, pane2);
hbox.autosize();
hbox.setAlignment(Pos.BASELINE_LEFT);
hbox.setPadding(new Insets(20));
// Create a scene and place it in the stage
Scene scene = new Scene(hbox, 1000, 500);
primaryStage.setTitle("Laura's Chapter 14"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
Create a pane for each feature and then add the features to either a VBox or HBox, that will root pane of the scene. That way you can have a GridPane for your second feature. There are different layouts available in JavaFX and they behave differently. Take a look at this documentation and its sub documentations.

QLayout: Cannot add a null widget to QGridLayout/

I am trying to add widgets dynamically with Qt.
My code looks like this
void MainWindow::on_actionLoad_DAS_Measurement_triggered()
{
QWidget *MeasurementsWidget = new QWidget; //Create a new widget which will show a small icon of the loaded measurements.
QGridLayout *MeasurementLayout = new QGridLayout; //Create a GridLayout which will contain the small icons.
QTextBrowser *Measurements[12] = {new QTextBrowser}; //Create an array for the loaded measurements. This will contain the actual icons respectively.
int MeasurementCount, MeasurementColumns, MeasurementLines, Number;
QStringList LoadDASMeasurement = QFileDialog::getOpenFileNames(this,"","","DAS Measurement (*.dl3; *.dl2)"); //Opening measurements in .dl2 and .dl3 format
MeasurementCount = LoadDASMeasurement.count(); //Saving the number of the loaded measurement
MeasurementCount++; //Increasing the number of the loaded measurement, to create enough columns after the division
MeasurementLines = 2; // 2 lines are used. Can be modified in the future
MeasurementColumns = MeasurementCount / MeasurementLines;
Number = 0;
for (int LineCount = 0; LineCount < MeasurementLines; LineCount++)
{
for (int ColumnCount = 0; ColumnCount < MeasurementColumns; ColumnCount++)
{
MeasurementLayout->addWidget(Measurements[Number],LineCount,ColumnCount);
Number++;
}
}
MeasurementsWidget->setLayout(MeasurementLayout); //Assign the widget to the GridLayout
setCentralWidget(MeasurementsWidget); //Set the Widget as a centralwidget, so it will be shown in the mainwindow
}
I always get a warning message:
QLayout: Cannot add a null widget to QGridLayout/
And only the first widget is shown.
Can anybody help why this warning occurs?
Here's your problem:
QTextBrowser *Measurements[12] = {new QTextBrowser};
That creates an array of 12 pointers where the first is a new QTextBrowser and the rest are all nullptr. You'll need to loop over the array and instantiate 12 individual QTextBrowsers.

Resources